X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=svvm_cmds.c;h=d7fe26dc1905f8ee6cebbd83254b37a2c347b010;hb=1d8da66c6d6e2f48017b9020125538d3bfa74814;hp=bbe14a7734eb2ccea85d487feada55d67ccbfac5;hpb=c0b28902ae728d6089484e8f205aa118cd5b525b;p=xonotic%2Fdarkplaces.git diff --git a/svvm_cmds.c b/svvm_cmds.c index bbe14a77..d7fe26dc 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -1,9 +1,11 @@ +#include "quakedef.h" + #include "prvm_cmds.h" +#include "jpeg.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 = @@ -12,6 +14,7 @@ char *vm_sv_extensions = "DP_BUTTONUSE " "DP_CL_LOADSKY " "DP_CON_ALIASPARAMETERS " +"DP_CON_BESTWEAPON " "DP_CON_EXPANDCVAR " "DP_CON_SET " "DP_CON_SETA " @@ -23,6 +26,7 @@ char *vm_sv_extensions = "DP_EF_FULLBRIGHT " "DP_EF_NODEPTHTEST " "DP_EF_NODRAW " +"DP_EF_NOGUNBOB " "DP_EF_NOSHADOW " "DP_EF_RED " "DP_EF_STARDUST " @@ -34,6 +38,7 @@ char *vm_sv_extensions = "DP_ENT_LOWPRECISION " "DP_ENT_SCALE " "DP_ENT_VIEWMODEL " +"DP_GECKO_SUPPORT " "DP_GFX_EXTERNALTEXTURES " "DP_GFX_EXTERNALTEXTURES_PERMAP " "DP_GFX_FOG " @@ -51,8 +56,14 @@ char *vm_sv_extensions = "DP_MOVETYPEFOLLOW " "DP_QC_ASINACOSATANATAN2TAN " "DP_QC_CHANGEPITCH " +"DP_QC_CMD " "DP_QC_COPYENTITY " +"DP_QC_CRC16 " +"DP_QC_CVAR_DEFSTRING " "DP_QC_CVAR_STRING " +"DP_QC_CVAR_TYPE " +"DP_QC_EDICT_NUM " +"DP_QC_ENTITYDATA " "DP_QC_ETOS " "DP_QC_FINDCHAIN " "DP_QC_FINDCHAINFLAGS " @@ -62,21 +73,28 @@ char *vm_sv_extensions = "DP_QC_FS_SEARCH " "DP_QC_GETLIGHT " "DP_QC_GETSURFACE " +"DP_QC_GETSURFACEPOINTATTRIBUTE " "DP_QC_GETTAGINFO " "DP_QC_MINMAXBOUND " "DP_QC_MULTIPLETEMPSTRINGS " +"DP_QC_NUM_FOR_EDICT " "DP_QC_RANDOMVEC " "DP_QC_SINCOSSQRTPOW " "DP_QC_STRFTIME " "DP_QC_STRINGBUFFERS " "DP_QC_STRINGCOLORFUNCTIONS " +"DP_QC_STRING_CASE_FUNCTIONS " +"DP_QC_STRREPLACE " "DP_QC_TOKENIZEBYSEPARATOR " "DP_QC_TRACEBOX " "DP_QC_TRACETOSS " "DP_QC_TRACE_MOVETYPE_HITMODEL " "DP_QC_TRACE_MOVETYPE_WORLDONLY " "DP_QC_UNLIMITEDTEMPSTRINGS " +"DP_QC_URI_ESCAPE " +"DP_QC_VECTOANGLES_WITH_ROLL " "DP_QC_VECTORVECTORS " +"DP_QC_WHICHPACK " "DP_QUAKE2_MODEL " "DP_QUAKE2_SPRITE " "DP_QUAKE3_MAP " @@ -91,20 +109,31 @@ char *vm_sv_extensions = "DP_SV_BOTCLIENT " "DP_SV_CLIENTCOLORS " "DP_SV_CLIENTNAME " +"DP_SV_CMD " "DP_SV_CUSTOMIZEENTITYFORCLIENT " "DP_SV_DRAWONLYTOCLIENT " "DP_SV_DROPCLIENT " "DP_SV_EFFECT " "DP_SV_ENTITYCONTENTSTRANSITION " +"DP_SV_MODELFLAGS_AS_EFFECTS " +"DP_SV_MOVETYPESTEP_LANDEVENT " +"DP_SV_NETADDRESS " "DP_SV_NODRAWTOCLIENT " +"DP_SV_ONENTITYNOSPAWNFUNCTION " "DP_SV_PING " "DP_SV_PLAYERPHYSICS " +"DP_SV_POINTPARTICLES " +"DP_SV_POINTSOUND " "DP_SV_PRECACHEANYTIME " "DP_SV_PRINT " "DP_SV_PUNCHVECTOR " +"DP_SV_QCSTATUS " "DP_SV_ROTATINGBMODEL " "DP_SV_SETCOLOR " +"DP_SV_SHUTDOWN " "DP_SV_SLOWMO " +"DP_SV_SPAWNFUNC_PREFIX " +"DP_SV_WRITEPICTURE " "DP_SV_WRITEUNTERMINATEDSTRING " "DP_TE_BLOOD " "DP_TE_BLOODSHOWER " @@ -122,8 +151,8 @@ char *vm_sv_extensions = "DP_TRACE_HITCONTENTSMASK_SURFACEINFO " "DP_VIEWZOOM " "EXT_BITSHIFT " -//"EXT_CSQC " // not ready yet "FRIK_FILE " +"FTE_STRINGS " "KRIMZON_SV_PARSECLIENTCOMMAND " "NEH_CMD_PLAY2 " "NEH_RESTOREGAME " @@ -132,6 +161,7 @@ char *vm_sv_extensions = "PRYDON_CLIENTCURSOR " "TENEBRAE_GFX_DLIGHTS " "TW_SV_STEPCONTROL " +//"EXT_CSQC " // not ready yet ; /* @@ -166,8 +196,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; @@ -228,7 +258,7 @@ static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16}; static void VM_SV_setmodel (void) { prvm_edict_t *e; - model_t *mod; + dp_model_t *mod; int i; VM_SAFEPARMCOUNT(2, VM_setmodel); @@ -398,7 +428,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 +461,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 +495,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 +716,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 +867,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 +881,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) @@ -908,18 +981,52 @@ static void VM_SV_droptofloor (void) VectorCopy (ent->fields.server->origin, end); end[2] -= 256; - trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); + if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) + SV_UnstickEntity(ent); - if (trace.fraction != 1 || (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer)) - { - if (trace.fraction < 1) + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); + if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer) + { + vec3_t offset, org; + VectorSet(offset, 0.5f * (ent->fields.server->mins[0] + ent->fields.server->maxs[0]), 0.5f * (ent->fields.server->mins[1] + ent->fields.server->maxs[1]), ent->fields.server->mins[2]); + VectorAdd(ent->fields.server->origin, offset, org); + trace = SV_Move (org, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent, SV_GenericHitSuperContentsMask(ent)); + VectorSubtract(trace.endpos, offset, trace.endpos); + if (trace.startsolid) + { + Con_DPrintf("droptofloor at %f %f %f - COULD NOT FIX BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]); + SV_UnstickEntity(ent); + SV_LinkEdict (ent, false); + ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; + ent->fields.server->groundentity = 0; + PRVM_G_FLOAT(OFS_RETURN) = 1; + } + else if (trace.fraction < 1) + { + Con_DPrintf("droptofloor at %f %f %f - FIXED BADLY PLACED ENTITY\n", ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2]); VectorCopy (trace.endpos, ent->fields.server->origin); - SV_LinkEdict (ent, false); - ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; - ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); - PRVM_G_FLOAT(OFS_RETURN) = 1; - // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->priv.server->suspendedinairflag = true; + SV_UnstickEntity(ent); + SV_LinkEdict (ent, false); + ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; + ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + // if support is destroyed, keep suspended (gross hack for floating items in various maps) + ent->priv.server->suspendedinairflag = true; + } + } + else + { + if (trace.fraction != 1) + { + if (trace.fraction < 1) + VectorCopy (trace.endpos, ent->fields.server->origin); + SV_LinkEdict (ent, false); + ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; + ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + // if support is destroyed, keep suspended (gross hack for floating items in various maps) + ent->priv.server->suspendedinairflag = true; + } } } @@ -1104,7 +1211,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 +1238,7 @@ sizebuf_t *WriteDest (void) return &sv.signon; case MSG_ENTITY: - return sv2csqcbuf; + return sv.writeentitiestoclient_msg; } return NULL; @@ -1193,6 +1299,39 @@ static void VM_SV_WriteEntity (void) MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1)); } +// writes a picture as at most size bytes of data +// message: +// IMGNAME \0 SIZE(short) IMGDATA +// if failed to read/compress: +// IMGNAME \0 \0 \0 +//#501 void(float dest, string name, float maxsize) WritePicture (DP_SV_WRITEPICTURE)) +static void VM_SV_WritePicture (void) +{ + const char *imgname; + void *buf; + size_t size; + + VM_SAFEPARMCOUNT(3, VM_SV_WritePicture); + + imgname = PRVM_G_STRING(OFS_PARM1); + size = PRVM_G_FLOAT(OFS_PARM2); + if(size > 65535) + size = 65535; + + MSG_WriteString(WriteDest(), imgname); + if(Image_Compress(imgname, size, &buf, &size)) + { + // actual picture + MSG_WriteShort(WriteDest(), size); + SZ_Write(WriteDest(), buf, size); + } + else + { + // placeholder + MSG_WriteShort(WriteDest(), 0); + } +} + ////////////////////////////////////////////////////////// static void VM_SV_makestatic (void) @@ -1229,6 +1368,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 +1452,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 (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 +1694,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 +1716,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 +1732,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 +1762,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 +1788,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 +1814,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 +1834,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 +1846,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 +1858,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 +1870,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 +1882,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 +1894,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 +1916,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 +1928,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 +1940,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 +1952,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 +1964,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 +1976,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 +1988,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 +2000,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 +2012,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 +2024,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 +2039,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 +2057,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 +2075,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 +2093,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 +2111,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 +2122,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,9 +2140,10 @@ 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) +void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out) { int i, j, k; float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist; @@ -2056,7 +2179,7 @@ void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t ou } } -static model_t *getmodel(prvm_edict_t *ed) +static dp_model_t *getmodel(prvm_edict_t *ed) { int modelindex; if (!ed || ed->priv.server->free) @@ -2067,7 +2190,7 @@ static model_t *getmodel(prvm_edict_t *ed) return sv.models[modelindex]; } -static msurface_t *getsurface(model_t *model, int surfacenum) +static msurface_t *getsurface(dp_model_t *model, int surfacenum) { if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; @@ -2078,7 +2201,7 @@ static msurface_t *getsurface(model_t *model, int surfacenum) //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; static void VM_SV_getsurfacenumpoints(void) { - model_t *model; + dp_model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenumpoints); // return 0 if no such surface @@ -2095,7 +2218,7 @@ static void VM_SV_getsurfacenumpoints(void) static void VM_SV_getsurfacepoint(void) { prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; int pointnum; VM_SAFEPARMCOUNT(3, VM_SV_getsurfacepoint); @@ -2110,10 +2233,83 @@ 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; + dp_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) { - model_t *model; + dp_model_t *model; msurface_t *surface; vec3_t normal; VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenormal); @@ -2131,7 +2327,7 @@ static void VM_SV_getsurfacenormal(void) //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; static void VM_SV_getsurfacetexture(void) { - model_t *model; + dp_model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_SV_getsurfacetexture); PRVM_G_INT(OFS_RETURN) = OFS_NULL; @@ -2146,7 +2342,7 @@ static void VM_SV_getsurfacenearpoint(void) vec3_t clipped, p; vec_t dist, bestdist; prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; vec_t *point; VM_SAFEPARMCOUNT(2, VM_SV_getsurfacenearpoint); @@ -2192,7 +2388,7 @@ static void VM_SV_getsurfacenearpoint(void) static void VM_SV_getsurfaceclippedpoint(void) { prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; vec3_t p, out; VM_SAFEPARMCOUNT(3, VM_SV_te_getsurfaceclippedpoint); @@ -2237,7 +2433,7 @@ static void VM_SV_setattachment (void) const char *tagname = PRVM_G_STRING(OFS_PARM2); prvm_eval_t *v; int modelindex; - model_t *model; + dp_model_t *model; VM_SAFEPARMCOUNT(3, VM_SV_setattachment); if (e == prog->edicts) @@ -2281,7 +2477,7 @@ static void VM_SV_setattachment (void) int SV_GetTagIndex (prvm_edict_t *e, const char *tagname) { int i; - model_t *model; + dp_model_t *model; i = (int)e->fields.server->modelindex; if (i < 1 || i >= MAX_MODELS) @@ -2306,7 +2502,7 @@ int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out { int modelindex; int frame; - model_t *model; + dp_model_t *model; if (tagindex >= 0 && (modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex]) @@ -2338,7 +2534,7 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) prvm_eval_t *val; int modelindex, attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; - model_t *model; + dp_model_t *model; *out = identitymatrix; // warnings and errors return identical matrix @@ -2446,7 +2642,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; }; @@ -2569,7 +2766,7 @@ void VM_SV_serverkey(void) static void VM_SV_setmodelindex (void) { prvm_edict_t *e; - model_t *mod; + dp_model_t *mod; int i; VM_SAFEPARMCOUNT(2, VM_SV_setmodelindex); @@ -2651,23 +2848,49 @@ static void VM_SV_trailparticles (void) { VM_SAFEPARMCOUNT(4, VM_SV_trailparticles); + if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0) + return; + MSG_WriteByte(&sv.datagram, svc_trailparticles); MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); 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); - 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)); + if ((int)PRVM_G_FLOAT(OFS_PARM0) < 0) + return; + + 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); + } + + SV_FlushBroadcastMessages(); } prvm_builtin_t vm_sv_builtins[] = { @@ -2894,16 +3117,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 +3342,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 +3378,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,12 +3392,32 @@ NULL, // #490 NULL, // #491 NULL, // #492 NULL, // #493 -NULL, // #494 -NULL, // #495 -NULL, // #496 -NULL, // #497 -NULL, // #498 -NULL, // #499 +VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16) +VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE) +VM_numentityfields, // #496 float() numentityfields = #496; (DP_QC_ENTITYDATA) +VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA) +VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA) +VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA) +VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA) +VM_SV_WritePicture, // #501 +NULL, // #502 +VM_whichpack, // #503 string(string) whichpack = #503; +NULL, // #504 +NULL, // #505 +NULL, // #506 +NULL, // #507 +NULL, // #508 +NULL, // #509 +VM_uri_escape, // #510 string(string in) uri_escape = #510; +VM_uri_unescape, // #511 string(string in) uri_unescape = #511; +VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) +NULL, // #513 +NULL, // #514 +NULL, // #515 +NULL, // #516 +NULL, // #517 +NULL, // #518 +NULL, // #519 }; const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t); @@ -3186,6 +3429,13 @@ void VM_SV_Cmd_Init(void) void VM_SV_Cmd_Reset(void) { + if(prog->funcoffsets.SV_Shutdown) + { + func_t s = prog->funcoffsets.SV_Shutdown; + prog->funcoffsets.SV_Shutdown = 0; // prevent it from getting called again + PRVM_ExecuteProgram(s,"SV_Shutdown() required"); + } + VM_Cmd_Reset(); }