]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - svvm_cmds.c
rename VM_hash to VM_crc16, and the extension to DP_QC_CRC16. That way, it is specifi...
[xonotic/darkplaces.git] / svvm_cmds.c
index bbe14a7734eb2ccea85d487feada55d67ccbfac5..65953bda51cdecb8bcec0332f2b67c817a3fa182 100644 (file)
@@ -1,9 +1,10 @@
+#include "quakedef.h"
+
 #include "prvm_cmds.h"
 
 //============================================================================
 // Server
 
-cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2", "maximum cosine angle for quake's vertical autoaim, a value above 1 completely disables the autoaim, quake used 0.93"};
 
 
 char *vm_sv_extensions =
@@ -24,6 +25,7 @@ char *vm_sv_extensions =
 "DP_EF_NODEPTHTEST "
 "DP_EF_NODRAW "
 "DP_EF_NOSHADOW "
+"DP_EF_NOGUNBOB "
 "DP_EF_RED "
 "DP_EF_STARDUST "
 "DP_ENT_ALPHA "
@@ -52,6 +54,7 @@ char *vm_sv_extensions =
 "DP_QC_ASINACOSATANATAN2TAN "
 "DP_QC_CHANGEPITCH "
 "DP_QC_COPYENTITY "
+"DP_QC_CVAR_DEFSTRING "
 "DP_QC_CVAR_STRING "
 "DP_QC_ETOS "
 "DP_QC_FINDCHAIN "
@@ -68,6 +71,7 @@ char *vm_sv_extensions =
 "DP_QC_RANDOMVEC "
 "DP_QC_SINCOSSQRTPOW "
 "DP_QC_STRFTIME "
+"DP_QC_STRING_CASE_FUNCTIONS "
 "DP_QC_STRINGBUFFERS "
 "DP_QC_STRINGCOLORFUNCTIONS "
 "DP_QC_TOKENIZEBYSEPARATOR "
@@ -76,6 +80,7 @@ char *vm_sv_extensions =
 "DP_QC_TRACE_MOVETYPE_HITMODEL "
 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
 "DP_QC_UNLIMITEDTEMPSTRINGS "
+"DP_QC_VECTOANGLES_WITH_ROLL "
 "DP_QC_VECTORVECTORS "
 "DP_QUAKE2_MODEL "
 "DP_QUAKE2_SPRITE "
@@ -96,9 +101,14 @@ char *vm_sv_extensions =
 "DP_SV_DROPCLIENT "
 "DP_SV_EFFECT "
 "DP_SV_ENTITYCONTENTSTRANSITION "
+"DP_SV_ONENTITYNOSPAWNFUNCTION "
+"DP_SV_MODELFLAGS_AS_EFFECTS "
+"DP_SV_NETADDRESS "
 "DP_SV_NODRAWTOCLIENT "
 "DP_SV_PING "
 "DP_SV_PLAYERPHYSICS "
+"DP_SV_POINTPARTICLES "
+"DP_SV_POINTSOUND "
 "DP_SV_PRECACHEANYTIME "
 "DP_SV_PRINT "
 "DP_SV_PUNCHVECTOR "
@@ -132,6 +142,12 @@ char *vm_sv_extensions =
 "PRYDON_CLIENTCURSOR "
 "TENEBRAE_GFX_DLIGHTS "
 "TW_SV_STEPCONTROL "
+"DP_SV_CMD "
+"DP_QC_CMD "
+"FTE_STRINGS "
+"DP_CON_BESTWEAPON "
+"DP_QC_STRREPLACE "
+"DP_QC_CRC16 "
 ;
 
 /*
@@ -166,8 +182,8 @@ static void VM_SV_setorigin (void)
        SV_LinkEdict (e, false);
 }
 
-
-void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
+// TODO: rotate param isnt used.. could be a bug. please check this and remove it if possible [1/10/2008 Black]
+static void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
 {
        int             i;
 
@@ -398,7 +414,7 @@ static void VM_SV_ambientsound (void)
 
        MSG_WriteVector(&sv.signon, pos, sv.protocol);
 
-       if (large)
+       if (large || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
                MSG_WriteShort (&sv.signon, soundnum);
        else
                MSG_WriteByte (&sv.signon, soundnum);
@@ -431,13 +447,18 @@ static void VM_SV_sound (void)
        int             volume;
        float attenuation;
 
-       VM_SAFEPARMCOUNT(5, VM_SV_sound);
+       VM_SAFEPARMCOUNTRANGE(4, 5, VM_SV_sound);
 
        entity = PRVM_G_EDICT(OFS_PARM0);
        channel = (int)PRVM_G_FLOAT(OFS_PARM1);
        sample = PRVM_G_STRING(OFS_PARM2);
        volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255);
        attenuation = PRVM_G_FLOAT(OFS_PARM4);
+       if (prog->argc < 5)
+       {
+               Con_DPrintf("VM_SV_sound: given only 4 parameters, expected 5, assuming attenuation = ATTN_NORMAL\n");
+               attenuation = 1;
+       }
 
        if (volume < 0 || volume > 255)
        {
@@ -460,6 +481,45 @@ static void VM_SV_sound (void)
        SV_StartSound (entity, channel, sample, volume, attenuation);
 }
 
+/*
+=================
+VM_SV_pointsound
+
+Follows the same logic as VM_SV_sound, except instead of
+an entity, an origin for the sound is provided, and channel
+is omitted (since no entity is being tracked).
+
+=================
+*/
+static void VM_SV_pointsound(void)
+{
+       const char      *sample;
+       int             volume;
+       float           attenuation;
+       vec3_t          org;
+
+       VM_SAFEPARMCOUNT(4, VM_SV_pointsound);
+
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
+       sample = PRVM_G_STRING(OFS_PARM1);
+       volume = (int)(PRVM_G_FLOAT(OFS_PARM2) * 255);
+       attenuation = PRVM_G_FLOAT(OFS_PARM3);
+
+       if (volume < 0 || volume > 255)
+       {
+               VM_Warning("SV_StartPointSound: volume must be in range 0-1\n");
+               return;
+       }
+
+       if (attenuation < 0 || attenuation > 4)
+       {
+               VM_Warning("SV_StartPointSound: attenuation must be in range 0-4\n");
+               return;
+       }
+
+       SV_StartPointSound (org, sample, volume, attenuation);
+}
+
 /*
 =================
 VM_SV_traceline
@@ -642,7 +702,7 @@ static int VM_SV_newcheckclient (int check)
        VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
        checkpvsbytes = 0;
        if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
-               checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
+               checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs), false);
 
        return i;
 }
@@ -793,7 +853,7 @@ static void VM_SV_findradius (void)
                        eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
                }
                else
-                       VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
+                       VectorMAMAM(1, eorg, -0.5f, ent->fields.server->mins, -0.5f, ent->fields.server->maxs, eorg);
                if (DotProduct(eorg, eorg) < radius2)
                {
                        ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
@@ -807,8 +867,7 @@ static void VM_SV_findradius (void)
 static void VM_SV_precache_sound (void)
 {
        VM_SAFEPARMCOUNT(1, VM_SV_precache_sound);
-       SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
-       PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
+       PRVM_G_FLOAT(OFS_RETURN) = SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
 }
 
 static void VM_SV_precache_model (void)
@@ -1104,7 +1163,6 @@ sizebuf_t *WriteDest (void)
        int             entnum;
        int             dest;
        prvm_edict_t    *ent;
-       extern sizebuf_t *sv2csqcbuf;
 
        dest = (int)PRVM_G_FLOAT(OFS_PARM0);
        switch (dest)
@@ -1132,7 +1190,7 @@ sizebuf_t *WriteDest (void)
                return &sv.signon;
 
        case MSG_ENTITY:
-               return sv2csqcbuf;
+               return sv.writeentitiestoclient_msg;
        }
 
        return NULL;
@@ -1229,6 +1287,12 @@ static void VM_SV_makestatic (void)
                MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
                MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame);
        }
+       else if (sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3)
+       {
+               MSG_WriteByte (&sv.signon,svc_spawnstatic);
+               MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex);
+               MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame);
+       }
        else
        {
                MSG_WriteByte (&sv.signon,svc_spawnstatic);
@@ -1307,102 +1371,51 @@ typedef struct
 {
        unsigned char   type;   // 1/2/8 or other value if isn't used
        int             fieldoffset;
-}autosentstat_t;
+}customstat_t;
 
-static autosentstat_t *vm_autosentstats = NULL;        //[515]: it starts from 0, not 32
-static int vm_autosentstats_last;
+static customstat_t *vm_customstats = NULL;    //[515]: it starts from 0, not 32
+static int vm_customstats_last;
 
-void VM_AutoSentStats_Clear (void)
+void VM_CustomStats_Clear (void)
 {
-       if(vm_autosentstats)
+       if(vm_customstats)
        {
-               Z_Free(vm_autosentstats);
-               vm_autosentstats = NULL;
-               vm_autosentstats_last = -1;
+               Z_Free(vm_customstats);
+               vm_customstats = NULL;
+               vm_customstats_last = -1;
        }
 }
 
-//[515]: add check if even bigger ? "try to use two stats, cause it's too big" ?
-#define VM_SENDSTAT(a,b,c)\
-{\
-/*     if((c))*/\
-       if((c)==(unsigned char)(c))\
-       {\
-               MSG_WriteByte((a), svc_updatestatubyte);\
-               MSG_WriteByte((a), (b));\
-               MSG_WriteByte((a), (c));\
-       }\
-       else\
-       {\
-               MSG_WriteByte((a), svc_updatestat);\
-               MSG_WriteByte((a), (b));\
-               MSG_WriteLong((a), (c));\
-       }\
-}\
-
-void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
+void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats)
 {
-       int                     i, v, *si;
+       int                     i;
        char            s[17];
-       const char      *t;
-       qboolean        send;
-       union
-       {
-               float   f;
-               int             i;
-       }k;
 
-       if(!vm_autosentstats)
+       if(!vm_customstats)
                return;
 
-       send = (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5);
-
-       for(i=0; i<vm_autosentstats_last+1 ;i++)
+       for(i=0; i<vm_customstats_last+1 ;i++)
        {
-               if(!vm_autosentstats[i].type)
+               if(!vm_customstats[i].type)
                        continue;
-               switch(vm_autosentstats[i].type)
+               switch(vm_customstats[i].type)
                {
-               //string
+               //string as 16 bytes
                case 1:
-                       t = PRVM_E_STRING(ent, vm_autosentstats[i].fieldoffset);
-                       if(t && t[0])
-                       {
-                               memset(s, 0, 17);
-                               strlcpy(s, t, 16);
-                               si = (int*)s;
-                               if (!send)
-                               {
-                                       stats[i+32] = si[0];
-                                       stats[i+33] = si[1];
-                                       stats[i+34] = si[2];
-                                       stats[i+35] = si[3];
-                               }
-                               else
-                               {
-                                       VM_SENDSTAT(msg, i+32, si[0]);
-                                       VM_SENDSTAT(msg, i+33, si[1]);
-                                       VM_SENDSTAT(msg, i+34, si[2]);
-                                       VM_SENDSTAT(msg, i+35, si[3]);
-                               }
-                       }
+                       memset(s, 0, 17);
+                       strlcpy(s, PRVM_E_STRING(ent, vm_customstats[i].fieldoffset), 16);
+                       stats[i+32] = s[ 0] + s[ 1] * 256 + s[ 2] * 65536 + s[ 3] * 16777216;
+                       stats[i+33] = s[ 4] + s[ 5] * 256 + s[ 6] * 65536 + s[ 7] * 16777216;
+                       stats[i+34] = s[ 8] + s[ 9] * 256 + s[10] * 65536 + s[11] * 16777216;
+                       stats[i+35] = s[12] + s[13] * 256 + s[14] * 65536 + s[15] * 16777216;
                        break;
-               //float
+               //float field sent as-is
                case 2:
-                       k.f = PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset);       //[515]: use PRVM_E_INT ?
-                       k.i = LittleLong (k.i);
-                       if (!send)
-                               stats[i+32] = k.i;
-                       else
-                               VM_SENDSTAT(msg, i+32, k.i);
+                       stats[i+32] = PRVM_E_INT(ent, vm_customstats[i].fieldoffset);
                        break;
-               //integer
+               //integer value of float field
                case 8:
-                       v = (int)PRVM_E_FLOAT(ent, vm_autosentstats[i].fieldoffset);    //[515]: use PRVM_E_INT ?
-                       if (!send)
-                               stats[i+32] = v;
-                       else
-                               VM_SENDSTAT(msg, i+32, v);
+                       stats[i+32] = (int)PRVM_E_FLOAT(ent, vm_customstats[i].fieldoffset);
                        break;
                default:
                        break;
@@ -1424,10 +1437,10 @@ static void VM_SV_AddStat (void)
 
        VM_SAFEPARMCOUNT(3, VM_SV_AddStat);
 
-       if(!vm_autosentstats)
+       if(!vm_customstats)
        {
-               vm_autosentstats = (autosentstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(autosentstat_t));
-               if(!vm_autosentstats)
+               vm_customstats = (customstat_t *)Z_Malloc((MAX_CL_STATS-32) * sizeof(customstat_t));
+               if(!vm_customstats)
                {
                        VM_Warning("PF_SV_AddStat: not enough memory\n");
                        return;
@@ -1453,10 +1466,10 @@ static void VM_SV_AddStat (void)
                VM_Warning("PF_SV_AddStat: index > (MAX_CL_STATS-4) with string\n");
                return;
        }
-       vm_autosentstats[i].type                = type;
-       vm_autosentstats[i].fieldoffset = off;
-       if(vm_autosentstats_last < i)
-               vm_autosentstats_last = i;
+       vm_customstats[i].type          = type;
+       vm_customstats[i].fieldoffset   = off;
+       if(vm_customstats_last < i)
+               vm_customstats_last = i;
 }
 
 /*
@@ -1600,6 +1613,7 @@ static void VM_SV_te_blood (void)
        MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
        // count
        MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_bloodshower (void)
@@ -1621,6 +1635,7 @@ static void VM_SV_te_bloodshower (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
        // count
        MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_explosionrgb (void)
@@ -1636,6 +1651,7 @@ static void VM_SV_te_explosionrgb (void)
        MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
        MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
        MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_particlecube (void)
@@ -1665,6 +1681,7 @@ static void VM_SV_te_particlecube (void)
        MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
        // randomvel
        MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_particlerain (void)
@@ -1690,6 +1707,7 @@ static void VM_SV_te_particlerain (void)
        MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
        // color
        MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_particlesnow (void)
@@ -1715,6 +1733,7 @@ static void VM_SV_te_particlesnow (void)
        MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
        // color
        MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_spark (void)
@@ -1734,6 +1753,7 @@ static void VM_SV_te_spark (void)
        MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
        // count
        MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_gunshotquad (void)
@@ -1745,6 +1765,7 @@ static void VM_SV_te_gunshotquad (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_spikequad (void)
@@ -1756,6 +1777,7 @@ static void VM_SV_te_spikequad (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_superspikequad (void)
@@ -1767,6 +1789,7 @@ static void VM_SV_te_superspikequad (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_explosionquad (void)
@@ -1778,6 +1801,7 @@ static void VM_SV_te_explosionquad (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_smallflash (void)
@@ -1789,6 +1813,7 @@ static void VM_SV_te_smallflash (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_customflash (void)
@@ -1810,6 +1835,7 @@ static void VM_SV_te_customflash (void)
        MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
        MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
        MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_gunshot (void)
@@ -1821,6 +1847,7 @@ static void VM_SV_te_gunshot (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_spike (void)
@@ -1832,6 +1859,7 @@ static void VM_SV_te_spike (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_superspike (void)
@@ -1843,6 +1871,7 @@ static void VM_SV_te_superspike (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_explosion (void)
@@ -1854,6 +1883,7 @@ static void VM_SV_te_explosion (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_tarexplosion (void)
@@ -1865,6 +1895,7 @@ static void VM_SV_te_tarexplosion (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_wizspike (void)
@@ -1876,6 +1907,7 @@ static void VM_SV_te_wizspike (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_knightspike (void)
@@ -1887,6 +1919,7 @@ static void VM_SV_te_knightspike (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_lavasplash (void)
@@ -1898,6 +1931,7 @@ static void VM_SV_te_lavasplash (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_teleport (void)
@@ -1909,6 +1943,7 @@ static void VM_SV_te_teleport (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_explosion2 (void)
@@ -1923,6 +1958,7 @@ static void VM_SV_te_explosion2 (void)
        // color
        MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
        MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_lightning1 (void)
@@ -1940,6 +1976,7 @@ static void VM_SV_te_lightning1 (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_lightning2 (void)
@@ -1957,6 +1994,7 @@ static void VM_SV_te_lightning2 (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_lightning3 (void)
@@ -1974,6 +2012,7 @@ static void VM_SV_te_lightning3 (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_beam (void)
@@ -1991,6 +2030,7 @@ static void VM_SV_te_beam (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_plasmaburn (void)
@@ -2001,6 +2041,7 @@ static void VM_SV_te_plasmaburn (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 static void VM_SV_te_flamejet (void)
@@ -2018,6 +2059,7 @@ static void VM_SV_te_flamejet (void)
        MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
        // count
        MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2));
+       SV_FlushBroadcastMessages();
 }
 
 void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out)
@@ -2110,6 +2152,79 @@ static void VM_SV_getsurfacepoint(void)
        // FIXME: implement rotation/scaling
        VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
 }
+//PF_getsurfacepointattribute,     // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+// float SPA_POSITION = 0;
+// float SPA_S_AXIS = 1;
+// float SPA_T_AXIS = 2;
+// float SPA_R_AXIS = 3; // same as SPA_NORMAL
+// float SPA_TEXCOORDS0 = 4;
+// float SPA_LIGHTMAP0_TEXCOORDS = 5;
+// float SPA_LIGHTMAP0_COLOR = 6;
+static void VM_SV_getsurfacepointattribute(void)
+{
+       prvm_edict_t *ed;
+       model_t *model;
+       msurface_t *surface;
+       int pointnum;
+       int attributetype;
+
+       VM_SAFEPARMCOUNT(4, VM_SV_getsurfacepoint);
+       VectorClear(PRVM_G_VECTOR(OFS_RETURN));
+       ed = PRVM_G_EDICT(OFS_PARM0);
+       if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1))))
+               return;
+       // note: this (incorrectly) assumes it is a simple polygon
+       pointnum = (int)PRVM_G_FLOAT(OFS_PARM2);
+       if (pointnum < 0 || pointnum >= surface->num_vertices)
+               return;
+       // FIXME: implement rotation/scaling
+       attributetype = (int) PRVM_G_FLOAT(OFS_PARM3);
+
+       switch( attributetype ) {
+               // float SPA_POSITION = 0;
+               case 0:
+                       VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_S_AXIS = 1;
+               case 1:
+                       VectorCopy(&(model->surfmesh.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_T_AXIS = 2;
+               case 2:
+                       VectorCopy(&(model->surfmesh.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_R_AXIS = 3; // same as SPA_NORMAL
+               case 3:
+                       VectorCopy(&(model->surfmesh.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               // float SPA_TEXCOORDS0 = 4;
+               case 4: {
+                       float *ret = PRVM_G_VECTOR(OFS_RETURN);
+                       float *texcoord = &(model->surfmesh.data_texcoordtexture2f + 2 * surface->num_firstvertex)[pointnum * 2];
+                       ret[0] = texcoord[0];
+                       ret[1] = texcoord[1];
+                       ret[2] = 0.0f;
+                       break;
+               }
+               // float SPA_LIGHTMAP0_TEXCOORDS = 5;
+               case 5: {
+                       float *ret = PRVM_G_VECTOR(OFS_RETURN);
+                       float *texcoord = &(model->surfmesh.data_texcoordlightmap2f + 2 * surface->num_firstvertex)[pointnum * 2];
+                       ret[0] = texcoord[0];
+                       ret[1] = texcoord[1];
+                       ret[2] = 0.0f;
+                       break;
+               }
+               // float SPA_LIGHTMAP0_COLOR = 6;
+               case 6:
+                       // ignore alpha for now..
+                       VectorCopy( &(model->surfmesh.data_lightmapcolor4f + 4 * surface->num_firstvertex)[pointnum * 4], PRVM_G_VECTOR(OFS_RETURN));
+                       break;
+               default:
+                       VectorSet( PRVM_G_VECTOR(OFS_RETURN), 0.0f, 0.0f, 0.0f );
+                       break;
+       }
+}
 //PF_getsurfacenormal,    // #436 vector(entity e, float s) getsurfacenormal = #436;
 static void VM_SV_getsurfacenormal(void)
 {
@@ -2446,7 +2561,8 @@ static void VM_SV_gettagindex (void)
        {
                tag_index = SV_GetTagIndex(ent, tag_name);
                if (tag_index == 0)
-                       Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
+                       if(developer.integer >= 100)
+                               Con_Printf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
        }
        PRVM_G_FLOAT(OFS_RETURN) = tag_index;
 };
@@ -2656,18 +2772,37 @@ static void VM_SV_trailparticles (void)
        MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1));
        MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
        MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol);
+       SV_FlushBroadcastMessages();
 }
 
 //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC)
 static void VM_SV_pointparticles (void)
 {
-       VM_SAFEPARMCOUNT(4, VM_SV_pointparticles);
+       int effectnum, count;
+       vec3_t org, vel;
+       VM_SAFEPARMCOUNTRANGE(4, 8, VM_SV_pointparticles);
+       effectnum = (int)PRVM_G_FLOAT(OFS_PARM0);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM1), org);
+       VectorCopy(PRVM_G_VECTOR(OFS_PARM2), vel);
+       count = bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535);
+       if (count == 1 && !VectorLength2(vel))
+       {
+               // 1+2+12=15 bytes
+               MSG_WriteByte(&sv.datagram, svc_pointparticles1);
+               MSG_WriteShort(&sv.datagram, effectnum);
+               MSG_WriteVector(&sv.datagram, org, sv.protocol);
+       }
+       else
+       {
+               // 1+2+12+12+2=29 bytes
+               MSG_WriteByte(&sv.datagram, svc_pointparticles);
+               MSG_WriteShort(&sv.datagram, effectnum);
+               MSG_WriteVector(&sv.datagram, org, sv.protocol);
+               MSG_WriteVector(&sv.datagram, vel, sv.protocol);
+               MSG_WriteShort(&sv.datagram, count);
+       }
 
-       MSG_WriteByte(&sv.datagram, svc_pointparticles);
-       MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM0));
-       MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1), sv.protocol);
-       MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol);
-       MSG_WriteShort(&sv.datagram, bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535));
+       SV_FlushBroadcastMessages();
 }
 
 prvm_builtin_t vm_sv_builtins[] = {
@@ -2894,16 +3029,16 @@ NULL,                                                   // #217
 VM_bitshift,                                   // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT)
 NULL,                                                  // #219
 NULL,                                                  // #220
-NULL,                                                  // #221
+VM_strstrofs,                                  // #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
 VM_str2chr,                                            // #222 float(string str, float ofs) str2chr (FTE_STRINGS)
 VM_chr2str,                                            // #223 string(float c, ...) chr2str (FTE_STRINGS)
-NULL,                                                  // #224
-NULL,                                                  // #225
-NULL,                                                  // #226
-NULL,                                                  // #227
+VM_strconv,                                            // #224 string(float ccase, float calpha, float cnum, string s, ...) strconv (FTE_STRINGS)
+VM_strpad,                                             // #225 string(float chars, string s, ...) strpad (FTE_STRINGS)
+VM_infoadd,                                            // #226 string(string info, string key, string value, ...) infoadd (FTE_STRINGS)
+VM_infoget,                                            // #227 string(string info, string key) infoget (FTE_STRINGS)
 VM_strncmp,                                            // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
-NULL,                                                  // #229
-NULL,                                                  // #230
+VM_strncasecmp,                                        // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
+VM_strncasecmp,                                        // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
 NULL,                                                  // #231
 VM_SV_AddStat,                                 // #232 void(float index, float type, .void field) SV_AddStat (EXT_CSQC)
 NULL,                                                  // #233
@@ -3119,10 +3254,10 @@ VM_SV_clientcommand,                    // #440 void(entity e, string s) clientcommand (KRIMZON_S
 VM_tokenize,                                   // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
 VM_argv,                                               // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
 VM_SV_setattachment,                   // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
-VM_search_begin,                               // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
-VM_search_end,                                 // #445 void(float handle) search_end (DP_FS_SEARCH)
-VM_search_getsize,                             // #446 float(float handle) search_getsize (DP_FS_SEARCH)
-VM_search_getfilename,                 // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
+VM_search_begin,                               // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_QC_FS_SEARCH)
+VM_search_end,                                 // #445 void(float handle) search_end (DP_QC_FS_SEARCH)
+VM_search_getsize,                             // #446 float(float handle) search_getsize (DP_QC_FS_SEARCH)
+VM_search_getfilename,                 // #447 string(float handle, float num) search_getfilename (DP_QC_FS_SEARCH)
 VM_cvar_string,                                        // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
 VM_findflags,                                  // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
 VM_findchainflags,                             // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
@@ -3155,13 +3290,13 @@ VM_strlennocol,                                 // #476 float(string s) : DRESK - String Length (not countin
 VM_strdecolorize,                              // #477 string(string s) : DRESK - Decolorized String (DP_SV_STRINGCOLORFUNCTIONS)
 VM_strftime,                                   // #478 string(float uselocaltime, string format, ...) (DP_QC_STRFTIME)
 VM_tokenizebyseparator,                        // #479 float(string s) tokenizebyseparator (DP_QC_TOKENIZEBYSEPARATOR)
-NULL,                                                  // #480
-NULL,                                                  // #481
-NULL,                                                  // #482
-NULL,                                                  // #483
-NULL,                                                  // #484
-NULL,                                                  // #485
-NULL,                                                  // #486
+VM_strtolower,                                 // #480 string(string s) VM_strtolower (DP_QC_STRING_CASE_FUNCTIONS)
+VM_strtoupper,                                 // #481 string(string s) VM_strtoupper (DP_QC_STRING_CASE_FUNCTIONS)
+VM_cvar_defstring,                             // #482 string(string s) cvar_defstring (DP_QC_CVAR_DEFSTRING)
+VM_SV_pointsound,                              // #483 void(vector origin, string sample, float volume, float attenuation) (DP_SV_POINTSOUND)
+VM_strreplace,                                 // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE)
+VM_strireplace,                                        // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE)
+VM_SV_getsurfacepointattribute,// #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
 NULL,                                                  // #487
 NULL,                                                  // #488
 NULL,                                                  // #489
@@ -3169,7 +3304,7 @@ NULL,                                                     // #490
 NULL,                                                  // #491
 NULL,                                                  // #492
 NULL,                                                  // #493
-NULL,                                                  // #494
+VM_crc16,                                              // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16)
 NULL,                                                  // #495
 NULL,                                                  // #496
 NULL,                                                  // #497