X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=svvm_cmds.c;h=40d6c1755a5ae3f56ab4f1a08eda1a6499910bef;hp=e096554524ed8389a361c93dea4a7fdcd6be73a9;hb=c3001ce26f2c2fd69caa6af345ccca1d4376f4e5;hpb=5828c1a01ad212cd726a176e34f1d07be7410ff9 diff --git a/svvm_cmds.c b/svvm_cmds.c index e0965545..40d6c175 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -4,7 +4,7 @@ // Server #define PF_WARNING(s) do{Con_Printf(s);PRVM_PrintState();return;}while(0) -cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default +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"}; //"0.93"}; // LordHavoc: disabled autoaim by default char *vm_sv_extensions = @@ -20,6 +20,7 @@ char *vm_sv_extensions = "DP_EF_BLUE " "DP_EF_FLAME " "DP_EF_FULLBRIGHT " +"DP_EF_DOUBLESIDED " "DP_EF_NODEPTHTEST " "DP_EF_NODRAW " "DP_EF_NOSHADOW " @@ -64,6 +65,7 @@ char *vm_sv_extensions = "DP_QC_MULTIPLETEMPSTRINGS " "DP_QC_RANDOMVEC " "DP_QC_SINCOSSQRTPOW " +"DP_QC_STRINGBUFFERS " "DP_QC_TRACEBOX " "DP_QC_TRACETOSS " "DP_QC_TRACE_MOVETYPE_HITMODEL " @@ -83,6 +85,7 @@ char *vm_sv_extensions = "DP_SV_BOTCLIENT " "DP_SV_CLIENTCOLORS " "DP_SV_CLIENTNAME " +"DP_SV_CUSTOMIZEENTITYFORCLIENT " "DP_SV_DRAWONLYTOCLIENT " "DP_SV_DROPCLIENT " "DP_SV_EFFECT " @@ -109,6 +112,8 @@ char *vm_sv_extensions = "DP_TE_SPARK " "DP_TE_STANDARDEFFECTBUILTINS " "DP_VIEWZOOM " +"EXT_BITSHIFT " +//"EXT_CSQC " // not ready yet "FRIK_FILE " "KRIMZON_SV_PARSECLIENTCOMMAND " "NEH_CMD_PLAY2 " @@ -133,20 +138,6 @@ void PF_makevectors (void) AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); } -/* -============== -PF_vectorvectors - -Writes new values for v_forward, v_up, and v_right based on the given forward vector -vectorvectors(vector, vector) -============== -*/ -void PF_vectorvectors (void) -{ - VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward); - VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); -} - /* ================= PF_setorigin @@ -274,9 +265,12 @@ void PF_sprint (void) } client = svs.clients + entnum-1; + if (!client->netconnection) + return; + VM_VarString(1, string, sizeof(string)); - MSG_WriteChar(&client->message,svc_print); - MSG_WriteString(&client->message, string); + MSG_WriteChar(&client->netconnection->message,svc_print); + MSG_WriteString(&client->netconnection->message, string); } @@ -304,9 +298,12 @@ void PF_centerprint (void) } client = svs.clients + entnum-1; + if (!client->netconnection) + return; + VM_VarString(1, string, sizeof(string)); - MSG_WriteChar(&client->message,svc_centerprint); - MSG_WriteString(&client->message, string); + MSG_WriteChar(&client->netconnection->message,svc_centerprint); + MSG_WriteString(&client->netconnection->message, string); } /* @@ -878,11 +875,11 @@ void PF_lightstyle (void) for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++) { - if (client->active) + if (client->active && client->netconnection) { - MSG_WriteChar (&client->message, svc_lightstyle); - MSG_WriteChar (&client->message,style); - MSG_WriteString (&client->message, val); + MSG_WriteChar (&client->netconnection->message, svc_lightstyle); + MSG_WriteChar (&client->netconnection->message,style); + MSG_WriteString (&client->netconnection->message, val); } } } @@ -1117,12 +1114,14 @@ MESSAGE WRITING #define MSG_ONE 1 // reliable to one (msg_entity) #define MSG_ALL 2 // reliable to all #define MSG_INIT 3 // write to the init string +#define MSG_ENTITY 5 sizebuf_t *WriteDest (void) { int entnum; int dest; prvm_edict_t *ent; + extern sizebuf_t *sv2csqcbuf; dest = PRVM_G_FLOAT(OFS_PARM0); switch (dest) @@ -1133,13 +1132,13 @@ sizebuf_t *WriteDest (void) case MSG_ONE: ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity); entnum = PRVM_NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active || !svs.clients[entnum-1].netconnection) { Con_Printf ("WriteDest: tried to write to non-client\n"); return &sv.reliable_datagram; } else - return &svs.clients[entnum-1].message; + return &svs.clients[entnum-1].netconnection->message; default: Con_Printf ("WriteDest: bad destination\n"); @@ -1148,6 +1147,9 @@ sizebuf_t *WriteDest (void) case MSG_INIT: return &sv.signon; + + case MSG_ENTITY: + return sv2csqcbuf; } return NULL; @@ -1316,6 +1318,160 @@ void PF_registercvar (void) PRVM_G_FLOAT(OFS_RETURN) = 1; // success } +typedef struct +{ + unsigned char type; // 1/2/8 or other value if isn't used + int fieldoffset; +}autosentstat_t; + +static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32 +static int vm_autosentstats_last; + +void VM_AutoSentStats_Clear (void) +{ + if(vm_autosentstats) + { + free(vm_autosentstats); + vm_autosentstats = NULL; + vm_autosentstats_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) +{ + int i, v, *si; + char s[17]; + const char *t; + qboolean send; + union + { + float f; + int i; + }k; + + if(!vm_autosentstats) + 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-32)) + { + Con_Printf("PF_SV_AddStat: index >= MAX_CL_STATS\n"); + return; + } + if(i > (MAX_CL_STATS-32-4) && type == 1) + { + Con_Printf("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; +} + /* ================= PF_copyentity @@ -1813,7 +1969,7 @@ void PF_te_flamejet (void) MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2)); } -static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out) +void clippointtosurface(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; @@ -2069,6 +2225,37 @@ int SV_GetTagIndex (prvm_edict_t *e, const char *tagname) return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname); }; +void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix) +{ + float scale = PRVM_GETEDICTFIELDVALUE(ent, eval_scale)->_float; + if (scale == 0) + scale = 1; + if (viewmatrix) + Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale); + else + Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale * 0.333); +} + +int SV_GetEntityLocalTagMatrix(prvm_edict_t *ent, int tagindex, matrix4x4_t *out) +{ + int modelindex; + int frame; + model_t *model; + if (tagindex >= 0 + && (modelindex = ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS + && (model = sv.models[(int)ent->fields.server->modelindex]) + && model->animscenes) + { + // if model has wrong frame, engine automatically switches to model first frame + frame = (int)ent->fields.server->frame; + if (frame < 0 || frame >= model->numframes) + frame = 0; + return Mod_Alias_GetTagMatrix(model, model->animscenes[frame].firstframe, tagindex, out); + } + Matrix4x4_CreateIdentity(out); + return 0; +} + // Warnings/errors code: // 0 - normal (everything all-right) // 1 - world entity @@ -2081,10 +2268,10 @@ extern cvar_t cl_bobcycle; extern cvar_t cl_bobup; int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) { + int ret; prvm_eval_t *val; - int modelindex, reqframe, attachloop; + int modelindex, attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; - prvm_edict_t *attachent; model_t *model; Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix @@ -2100,84 +2287,40 @@ int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) model = sv.models[modelindex]; - if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes) - reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe; - else - reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame - - // get initial tag matrix - if (tagindex) + Matrix4x4_CreateIdentity(&tagmatrix); + // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity + attachloop = 0; + for (;;) { - int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix); - if (ret) + if (attachloop >= 256) // prevent runaway looping + return 5; + // apply transformation by child's tagindex on parent entity and then + // by parent entity itself + ret = SV_GetEntityLocalTagMatrix(ent, tagindex - 1, &attachmatrix); + if (ret && attachloop == 0) return ret; - } - else - Matrix4x4_CreateIdentity(&tagmatrix); - - if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict) - { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity - attachloop = 0; - do + Matrix4x4_Concat(out, &attachmatrix, &tagmatrix); + SV_GetEntityMatrix(ent, &entitymatrix, false); + Matrix4x4_Concat(&tagmatrix, &entitymatrix, out); + // next iteration we process the parent entity + if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict) { - attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached - val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index); - if (val->_float >= 1 && attachent->fields.server->modelindex >= 1 && attachent->fields.server->modelindex < MAX_MODELS && (model = sv.models[(int)attachent->fields.server->modelindex]) && model->animscenes && attachent->fields.server->frame >= 0 && attachent->fields.server->frame < model->numframes) - Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix); - else - Matrix4x4_CreateIdentity(&attachmatrix); - - // apply transformation by child entity matrix - val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale); - if (val->_float == 0) - val->_float = 1; - Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], val->_float); - Matrix4x4_Concat(out, &entitymatrix, &tagmatrix); - out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]); - out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]); - out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]); - Matrix4x4_Copy(&tagmatrix, out); - - // finally transformate by matrix of tag on parent entity - Matrix4x4_Concat(out, &attachmatrix, &tagmatrix); - out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3]; - out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3]; - out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3]; - Matrix4x4_Copy(&tagmatrix, out); - - ent = attachent; - attachloop += 1; - if (attachloop > 255) // prevent runaway looping - return 5; + tagindex = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index)->_float; + ent = PRVM_EDICT_NUM(val->edict); } - while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict); + else + break; + attachloop++; } - // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain) - val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale); - if (val->_float == 0) - val->_float = 1; - // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype... - Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], val->_float); - Matrix4x4_Concat(out, &entitymatrix, &tagmatrix); - out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]); - out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]); - out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]); - + // RENDER_VIEWMODEL magic if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict) - {// RENDER_VIEWMODEL magic + { Matrix4x4_Copy(&tagmatrix, out); ent = PRVM_EDICT_NUM(val->edict); - val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale); - if (val->_float == 0) - val->_float = 1; - - Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], val->_float); + SV_GetEntityMatrix(ent, &entitymatrix, true); Matrix4x4_Concat(out, &entitymatrix, &tagmatrix); - out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]); - out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]); - out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]); /* // Cl_bob, ported from rendering code @@ -2313,9 +2456,14 @@ void PF_clienttype (void) PRVM_G_FLOAT(OFS_RETURN) = 2; } +void PF_edict_num (void) +{ + VM_RETURN_EDICT(PRVM_EDICT_NUM((int)PRVM_G_FLOAT(OFS_PARM0))); +} + prvm_builtin_t vm_sv_builtins[] = { NULL, // #0 -PF_makevectors, // #1 void(entity e) makevectors +PF_makevectors, // #1 void(vector ang) makevectors PF_setorigin, // #2 void(entity e, vector o) setorigin PF_setmodel, // #3 void(entity e, string m) setmodel PF_setsize, // #4 void(entity e, vector min, vector max) setsize @@ -2435,7 +2583,35 @@ VM_stov, // #117 vector(string) stov (FRIK_FILE) VM_strzone, // #118 string(string s) strzone (FRIK_FILE) VM_strunzone, // #119 void(string s) strunzone (FRIK_FILE) e10, e10, e10, e10, e10, e10, e10, e10, // #120-199 -e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #200-299 +// FTEQW range #200-#299 +NULL, // #200 +NULL, // #201 +NULL, // #202 +NULL, // #203 +NULL, // #204 +NULL, // #205 +NULL, // #206 +NULL, // #207 +NULL, // #208 +NULL, // #209 +NULL, // #210 +NULL, // #211 +NULL, // #212 +NULL, // #213 +NULL, // #214 +NULL, // #215 +NULL, // #216 +NULL, // #217 +VM_bitshift, // #218 float(float number, float quantity) bitshift (EXT_BITSHIFT) +NULL, // #219 +e10, // #220-#229 +e10, // #230-#239 +e10, // #240-#249 +e10, // #250-#259 +e10, // #260-#269 +e10, // #270-#279 +e10, // #280-#289 +e10, // #290-#299 e10, e10, e10, e10, e10, e10, e10, e10, e10, e10, // #300-399 VM_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) @@ -2469,7 +2645,7 @@ PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightn PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) -PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) +VM_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) @@ -2496,8 +2672,28 @@ PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT) PF_WriteUnterminatedString, // #456 void(float to, string s) WriteUnterminatedString (DP_SV_WRITEUNTERMINATEDSTRING) PF_te_flamejet, // #457 void(vector org, vector vel, float howmany) te_flamejet = #457 (DP_TE_FLAMEJET) NULL, // #458 -NULL, // #459 -e10, e10, e10, e10 // #460-499 (LordHavoc) +PF_edict_num, // #459 entity(float num) (??) +VM_buf_create, // #460 float() buf_create (DP_QC_STRINGBUFFERS) +VM_buf_del, // #461 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) +VM_buf_getsize, // #462 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) +VM_buf_copy, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) +VM_buf_sort, // #464 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) +VM_buf_implode, // #465 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) +VM_bufstr_get, // #466 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) +VM_bufstr_set, // #467 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) +VM_bufstr_add, // #468 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) +VM_bufstr_free, // #469 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) +PF_SV_AddStat, // #470 void(float index, float type, .void field) SV_AddStat (EXT_CSQC) +NULL, // #471 +NULL, // #472 +NULL, // #473 +NULL, // #474 +NULL, // #475 +NULL, // #476 +NULL, // #477 +NULL, // #478 +NULL, // #479 +e10, e10 // #471-499 (LordHavoc) }; const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);