X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=svvm_cmds.c;h=da749e3de90d5743c82a12a1df326d55d48017d5;hp=89b03104523a0b2f068c5b38f780fc49ec938ac5;hb=01ba19424cec267526ca273d809516ff36fe23cb;hpb=fab6eb344365652bd53d03faa1ea43e14fbe1d7f diff --git a/svvm_cmds.c b/svvm_cmds.c index 89b03104..da749e3d 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 " @@ -108,7 +111,10 @@ char *vm_sv_extensions = "DP_TE_SMALLFLASH " "DP_TE_SPARK " "DP_TE_STANDARDEFFECTBUILTINS " +"DP_TRACE_HITCONTENTSMASK_SURFACEINFO " "DP_VIEWZOOM " +"EXT_BITSHIFT " +//"EXT_CSQC " // not ready yet "FRIK_FILE " "KRIMZON_SV_PARSECLIENTCOMMAND " "NEH_CMD_PLAY2 " @@ -133,20 +139,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 +266,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 +299,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); } /* @@ -326,7 +324,7 @@ void PF_particle (void) dir = PRVM_G_VECTOR(OFS_PARM1); color = PRVM_G_FLOAT(OFS_PARM2); count = PRVM_G_FLOAT(OFS_PARM3); - SV_StartParticle (org, dir, color, count); + SV_StartParticle (org, dir, (int)color, (int)count); } @@ -371,8 +369,8 @@ void PF_ambientsound (void) else MSG_WriteByte (&sv.signon, soundnum); - MSG_WriteByte (&sv.signon, vol*255); - MSG_WriteByte (&sv.signon, attenuation*64); + MSG_WriteByte (&sv.signon, (int)(vol*255)); + MSG_WriteByte (&sv.signon, (int)(attenuation*64)); } @@ -400,9 +398,9 @@ void PF_sound (void) float attenuation; entity = PRVM_G_EDICT(OFS_PARM0); - channel = PRVM_G_FLOAT(OFS_PARM1); + channel = (int)PRVM_G_FLOAT(OFS_PARM1); sample = PRVM_G_STRING(OFS_PARM2); - volume = PRVM_G_FLOAT(OFS_PARM3) * 255; + volume = (int)(PRVM_G_FLOAT(OFS_PARM3) * 255); attenuation = PRVM_G_FLOAT(OFS_PARM4); if (volume < 0 || volume > 255) @@ -434,14 +432,18 @@ void PF_traceline (void) trace_t trace; int move; prvm_edict_t *ent; + prvm_eval_t *val; prog->xfunction->builtinsprofile += 30; v1 = PRVM_G_VECTOR(OFS_PARM0); v2 = PRVM_G_VECTOR(OFS_PARM1); - move = PRVM_G_FLOAT(OFS_PARM2); + move = (int)PRVM_G_FLOAT(OFS_PARM2); ent = PRVM_G_EDICT(OFS_PARM3); + if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) + PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); + trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent); prog->globals.server->trace_allsolid = trace.allsolid; @@ -456,7 +458,23 @@ void PF_traceline (void) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); - // FIXME: add trace_endcontents + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents))) + val->_float = trace.startsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents))) + val->_float = trace.hitsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags))) + val->_float = trace.hitq3surfaceflags; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename))) + { + if (trace.hittexture) + { + char *s = VM_GetTempString(); + strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH); + val->string = PRVM_SetEngineString(s); + } + else + val->string = 0; + } } @@ -478,6 +496,7 @@ void PF_tracebox (void) trace_t trace; int move; prvm_edict_t *ent; + prvm_eval_t *val; prog->xfunction->builtinsprofile += 30; @@ -485,9 +504,12 @@ void PF_tracebox (void) m1 = PRVM_G_VECTOR(OFS_PARM1); m2 = PRVM_G_VECTOR(OFS_PARM2); v2 = PRVM_G_VECTOR(OFS_PARM3); - move = PRVM_G_FLOAT(OFS_PARM4); + move = (int)PRVM_G_FLOAT(OFS_PARM4); ent = PRVM_G_EDICT(OFS_PARM5); + if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) + PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); + trace = SV_Move (v1, m1, m2, v2, move, ent); prog->globals.server->trace_allsolid = trace.allsolid; @@ -502,6 +524,23 @@ void PF_tracebox (void) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents))) + val->_float = trace.startsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents))) + val->_float = trace.hitsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags))) + val->_float = trace.hitq3surfaceflags; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename))) + { + if (trace.hittexture) + { + char *s = VM_GetTempString(); + strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH); + val->string = PRVM_SetEngineString(s); + } + else + val->string = 0; + } } extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore); @@ -510,6 +549,7 @@ void PF_tracetoss (void) trace_t trace; prvm_edict_t *ent; prvm_edict_t *ignore; + prvm_eval_t *val; prog->xfunction->builtinsprofile += 600; @@ -532,6 +572,23 @@ void PF_tracetoss (void) prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dpstartcontents))) + val->_float = trace.startsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitcontents))) + val->_float = trace.hitsupercontents; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphitq3surfaceflags))) + val->_float = trace.hitq3surfaceflags; + if ((val = PRVM_GETGLOBALFIELDVALUE(gval_trace_dphittexturename))) + { + if (trace.hittexture) + { + char *s = VM_GetTempString(); + strlcpy(s, trace.hittexture->name, VM_STRINGTEMP_LENGTH); + val->string = PRVM_SetEngineString(s); + } + else + val->string = 0; + } } @@ -653,14 +710,14 @@ PF_stuffcmd Sends text over to the client's execution buffer -stuffcmd (clientent, value) +stuffcmd (clientent, value, ...) ================= */ void PF_stuffcmd (void) { int entnum; - const char *str; client_t *old; + char string[VM_STRINGTEMP_LENGTH]; entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) @@ -668,11 +725,12 @@ void PF_stuffcmd (void) Con_Print("Can't stuffcmd to a non-client\n"); return; } - str = PRVM_G_STRING(OFS_PARM1); + + VM_VarString(1, string, sizeof(string)); old = host_client; host_client = svs.clients + entnum-1; - Host_ClientCommands ("%s", str); + Host_ClientCommands ("%s", string); host_client = old; } @@ -861,7 +919,7 @@ void PF_lightstyle (void) client_t *client; int j; - style = PRVM_G_FLOAT(OFS_PARM0); + style = (int)PRVM_G_FLOAT(OFS_PARM0); val = PRVM_G_STRING(OFS_PARM1); if( (unsigned) style >= MAX_LIGHTSTYLES ) { @@ -877,11 +935,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); } } } @@ -1116,14 +1174,16 @@ 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); + dest = (int)PRVM_G_FLOAT(OFS_PARM0); switch (dest) { case MSG_BROADCAST: @@ -1132,13 +1192,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"); @@ -1147,6 +1207,9 @@ sizebuf_t *WriteDest (void) case MSG_INIT: return &sv.signon; + + case MSG_ENTITY: + return sv2csqcbuf; } return NULL; @@ -1154,22 +1217,22 @@ sizebuf_t *WriteDest (void) void PF_WriteByte (void) { - MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteByte (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteChar (void) { - MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteChar (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteShort (void) { - MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteShort (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteLong (void) { - MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteLong (WriteDest(), (int)PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteAngle (void) @@ -1218,18 +1281,18 @@ void PF_makestatic (void) if (large) { MSG_WriteByte (&sv.signon,svc_spawnstatic2); - MSG_WriteShort (&sv.signon, ent->fields.server->modelindex); - MSG_WriteShort (&sv.signon, ent->fields.server->frame); + MSG_WriteShort (&sv.signon, (int)ent->fields.server->modelindex); + MSG_WriteShort (&sv.signon, (int)ent->fields.server->frame); } else { MSG_WriteByte (&sv.signon,svc_spawnstatic); - MSG_WriteByte (&sv.signon, ent->fields.server->modelindex); - MSG_WriteByte (&sv.signon, ent->fields.server->frame); + MSG_WriteByte (&sv.signon, (int)ent->fields.server->modelindex); + MSG_WriteByte (&sv.signon, (int)ent->fields.server->frame); } - MSG_WriteByte (&sv.signon, ent->fields.server->colormap); - MSG_WriteByte (&sv.signon, ent->fields.server->skin); + MSG_WriteByte (&sv.signon, (int)ent->fields.server->colormap); + MSG_WriteByte (&sv.signon, (int)ent->fields.server->skin); for (i=0 ; i<3 ; i++) { MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol); @@ -1315,6 +1378,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) + { + Z_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 @@ -1357,7 +1574,7 @@ void PF_setcolor (void) prvm_eval_t *val; entnum = PRVM_G_EDICTNUM(OFS_PARM0); - i = PRVM_G_FLOAT(OFS_PARM1); + i = (int)PRVM_G_FLOAT(OFS_PARM1); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { @@ -1401,7 +1618,7 @@ void PF_effect (void) i = SV_ModelIndex(s, 1); if (!i) PF_WARNING("effect: model not precached\n"); - SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4)); + SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, (int)PRVM_G_FLOAT(OFS_PARM2), (int)PRVM_G_FLOAT(OFS_PARM3), (int)PRVM_G_FLOAT(OFS_PARM4)); } void PF_te_blood (void) @@ -1439,7 +1656,7 @@ void PF_te_bloodshower (void) // speed MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol); // count - MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); } void PF_te_explosionrgb (void) @@ -1475,9 +1692,9 @@ void PF_te_particlecube (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); // count - MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); // gravity true/false MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0); // randomvel @@ -1503,9 +1720,9 @@ void PF_te_particlerain (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); // count - MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); } void PF_te_particlesnow (void) @@ -1527,9 +1744,9 @@ void PF_te_particlesnow (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); // count - MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); } void PF_te_spark (void) @@ -1611,13 +1828,13 @@ void PF_te_customflash (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); // radius - MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255)); + MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255)); // lifetime - MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255)); + MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255)); // color - MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255)); - MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255)); - MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255)); + 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)); } void PF_te_gunshot (void) @@ -1719,8 +1936,8 @@ void PF_te_explosion2 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); // color - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1)); - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); } void PF_te_lightning1 (void) @@ -1809,23 +2026,23 @@ void PF_te_flamejet (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // count - MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2)); + MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); } -static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out) +void clippointtosurface(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; const int *e; bestdist = 1000000000; VectorCopy(p, out); - for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3) + for (i = 0, e = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3) { // clip original point to each triangle of the surface and find the // triangle that is closest - v[0] = surface->groupmesh->data_vertex3f + e[0] * 3; - v[1] = surface->groupmesh->data_vertex3f + e[1] * 3; - v[2] = surface->groupmesh->data_vertex3f + e[2] * 3; + v[0] = model->surfmesh.data_vertex3f + e[0] * 3; + v[1] = model->surfmesh.data_vertex3f + e[1] * 3; + v[2] = model->surfmesh.data_vertex3f + e[2] * 3; TriangleNormal(v[0], v[1], v[2], facenormal); VectorNormalize(facenormal); offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal); @@ -1848,16 +2065,19 @@ static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out) } } -static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum) +static model_t *getmodel(prvm_edict_t *ed) { int modelindex; - model_t *model; if (!ed || ed->priv.server->free) return NULL; - modelindex = ed->fields.server->modelindex; + modelindex = (int)ed->fields.server->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) return NULL; - model = sv.models[modelindex]; + return sv.models[modelindex]; +} + +static msurface_t *getsurface(model_t *model, int surfacenum) +{ if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; return model->data_surfaces + surfacenum + model->firstmodelsurface; @@ -1867,9 +2087,10 @@ static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum) //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; void PF_getsurfacenumpoints(void) { + model_t *model; msurface_t *surface; // return 0 if no such surface - if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) { PRVM_G_FLOAT(OFS_RETURN) = 0; return; @@ -1882,50 +2103,51 @@ void PF_getsurfacenumpoints(void) void PF_getsurfacepoint(void) { prvm_edict_t *ed; + model_t *model; msurface_t *surface; int pointnum; VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); - if (!ed || ed->priv.server->free) - return; - if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // note: this (incorrectly) assumes it is a simple polygon - pointnum = PRVM_G_FLOAT(OFS_PARM2); + pointnum = (int)PRVM_G_FLOAT(OFS_PARM2); if (pointnum < 0 || pointnum >= surface->num_vertices) return; // FIXME: implement rotation/scaling - VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); + VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; void PF_getsurfacenormal(void) { + model_t *model; msurface_t *surface; vec3_t normal; VectorClear(PRVM_G_VECTOR(OFS_RETURN)); - if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // FIXME: implement rotation/scaling // note: this (incorrectly) assumes it is a simple polygon // note: this only returns the first triangle, so it doesn't work very // well for curved surfaces or arbitrary meshes - TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); + TriangleNormal((model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex), (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 3, (model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); VectorNormalize(normal); VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; void PF_getsurfacetexture(void) { + model_t *model; msurface_t *surface; PRVM_G_INT(OFS_RETURN) = 0; - if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = getmodel(PRVM_G_EDICT(OFS_PARM0))) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name); } //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; void PF_getsurfacenearpoint(void) { - int surfacenum, best, modelindex; + int surfacenum, best; vec3_t clipped, p; vec_t dist, bestdist; prvm_edict_t *ed; @@ -1938,11 +2160,8 @@ void PF_getsurfacenearpoint(void) if (!ed || ed->priv.server->free) return; - modelindex = ed->fields.server->modelindex; - if (modelindex < 1 || modelindex >= MAX_MODELS) - return; - model = sv.models[modelindex]; - if (!model->num_surfaces) + model = getmodel(ed); + if (!model || !model->num_surfaces) return; // FIXME: implement rotation/scaling @@ -1960,7 +2179,7 @@ void PF_getsurfacenearpoint(void) if (dist < bestdist) { // it is, check the nearest point on the actual geometry - clippointtosurface(surface, p, clipped); + clippointtosurface(model, surface, p, clipped); VectorSubtract(clipped, p, clipped); dist += VectorLength2(clipped); if (dist < bestdist) @@ -1977,17 +2196,16 @@ void PF_getsurfacenearpoint(void) void PF_getsurfaceclippedpoint(void) { prvm_edict_t *ed; + model_t *model; msurface_t *surface; vec3_t p, out; VectorClear(PRVM_G_VECTOR(OFS_RETURN)); ed = PRVM_G_EDICT(OFS_PARM0); - if (!ed || ed->priv.server->free) - return; - if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) + if (!(model = getmodel(ed)) || !(surface = getsurface(model, (int)PRVM_G_FLOAT(OFS_PARM1)))) return; // FIXME: implement rotation/scaling VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p); - clippointtosurface(surface, p, out); + clippointtosurface(model, surface, p, out); // FIXME: implement rotation/scaling VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); } @@ -2043,7 +2261,7 @@ void PF_setattachment (void) modelindex = (int)tagentity->fields.server->modelindex; if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) { - v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname); + v->_float = Mod_Alias_GetTagIndexForName(model, (int)tagentity->fields.server->skin, tagname); if (v->_float == 0) Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name); } @@ -2060,14 +2278,45 @@ int SV_GetTagIndex (prvm_edict_t *e, const char *tagname) int i; model_t *model; - i = e->fields.server->modelindex; + i = (int)e->fields.server->modelindex; if (i < 1 || i >= MAX_MODELS) return -1; model = sv.models[i]; - return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname); + return Mod_Alias_GetTagIndexForName(model, (int)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 = (int)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); + } + *out = identitymatrix; + return 0; +} + // Warnings/errors code: // 0 - normal (everything all-right) // 1 - world entity @@ -2080,13 +2329,13 @@ 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 + *out = identitymatrix; // warnings and errors return identical matrix if (ent == prog->edicts) return 1; @@ -2099,84 +2348,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) + tagmatrix = identitymatrix; + // 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 = (int)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 @@ -2290,6 +2495,9 @@ void PF_spawnclient (void) { prog->xfunction->builtinsprofile += 100; SV_ConnectClient (i, NULL); + // this has to be set or else ClientDisconnect won't be called + // we assume the qc will call ClientConnect... + svs.clients[i].clientconnectcalled = true; ed = PRVM_EDICT_NUM(i + 1); break; } @@ -2312,9 +2520,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 @@ -2434,7 +2647,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) @@ -2468,7 +2709,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) @@ -2495,8 +2736,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 // #480-499 (LordHavoc) }; const int vm_sv_numbuiltins = sizeof(vm_sv_builtins) / sizeof(prvm_builtin_t);