X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=pr_cmds.c;h=cbc06add83e0780f9ef53cbc9a47a1c2acf871cb;hp=7eaa915f45e5b71d07b1c1ff3c38196074c417e1;hb=6824d8ddc8a43cae0609be5bbe8bee01fa1a4225;hpb=e11263d3ea167699c332c40802df925881d8a58d diff --git a/pr_cmds.c b/pr_cmds.c index 7eaa915f..cbc06add 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -23,8 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"}; -mempool_t *pr_strings_mempool; - // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print #define STRINGTEMP_BUFFERS 16 #define STRINGTEMP_LENGTH 4096 @@ -39,7 +37,7 @@ static char *PR_GetTempString(void) return s; } -#define RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e)) +#define RETURN_EDICT(e) (PRVM_G_INT(OFS_RETURN) = PRVM_EDICT_TO_PROG(e)) #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0) #define PF_ERROR(s) do{Host_Error(s);return;}while(0) @@ -62,7 +60,7 @@ void PF_VarString(int first, char *out, int outlength) outend = out + outlength - 1; for (i = first;i < pr_argc && out < outend;i++) { - s = G_STRING((OFS_PARM0+i*3)); + s = PRVM_G_STRING((OFS_PARM0+i*3)); while (out < outend && *s) *out++ = *s++; } @@ -70,15 +68,23 @@ void PF_VarString(int first, char *out, int outlength) } char *ENGINE_EXTENSIONS = +"DP_BUTTONCHAT " +"DP_BUTTONUSE " "DP_CL_LOADSKY " +"DP_CON_SET " +"DP_CON_SETA " +"DP_CON_STARTMAP " "DP_EF_ADDITIVE " "DP_EF_BLUE " "DP_EF_FLAME " "DP_EF_FULLBRIGHT " +"DP_EF_NODEPTHTEST " "DP_EF_NODRAW " +"DP_EF_NOSHADOW " "DP_EF_RED " "DP_EF_STARDUST " "DP_ENT_ALPHA " +"DP_ENT_COLORMOD " "DP_ENT_CUSTOMCOLORMAP " "DP_ENT_EXTERIORMODELTOCLIENT " "DP_ENT_GLOW " @@ -92,7 +98,9 @@ char *ENGINE_EXTENSIONS = "DP_GFX_SKYBOX " "DP_HALFLIFE_MAP " "DP_HALFLIFE_MAP_CVAR " +"DP_HALFLIFE_SPRITE " "DP_INPUTBUTTONS " +"DP_LITSPRITES " "DP_LITSUPPORT " "DP_MONSTERWALK " "DP_MOVETYPEBOUNCEMISSILE " @@ -102,12 +110,16 @@ char *ENGINE_EXTENSIONS = "DP_QC_CVAR_STRING " "DP_QC_ETOS " "DP_QC_FINDCHAIN " +"DP_QC_FINDCHAINFLAGS " "DP_QC_FINDCHAINFLOAT " +"DP_QC_FINDFLAGS " "DP_QC_FINDFLOAT " "DP_QC_FS_SEARCH " // Black: same as in the menu qc "DP_QC_GETLIGHT " "DP_QC_GETSURFACE " +"DP_QC_GETTAGINFO " "DP_QC_MINMAXBOUND " +"DP_QC_MULTIPLETEMPSTRINGS " "DP_QC_RANDOMVEC " "DP_QC_SINCOSSQRTPOW " "DP_QC_TRACEBOX " @@ -116,15 +128,28 @@ char *ENGINE_EXTENSIONS = "DP_QC_TRACE_MOVETYPE_WORLDONLY " "DP_QC_VECTORVECTORS " "DP_QUAKE2_MODEL " +"DP_QUAKE2_SPRITE " +"DP_QUAKE3_MAP " "DP_QUAKE3_MODEL " "DP_REGISTERCVAR " +"DP_SND_DIRECTIONLESSATTNNONE " +"DP_SND_FAKETRACKS " +"DP_SND_OGGVORBIS " +"DP_SND_STEREOWAV " "DP_SOLIDCORPSE " "DP_SPRITE32 " +"DP_SV_BOTCLIENT " +"DP_SV_CLIENTCOLORS " +"DP_SV_CLIENTNAME " "DP_SV_DRAWONLYTOCLIENT " +"DP_SV_DROPCLIENT " "DP_SV_EFFECT " -"DP_SV_EXTERIORMODELTOCLIENT " "DP_SV_NODRAWTOCLIENT " +"DP_SV_PING " "DP_SV_PLAYERPHYSICS " +"DP_SV_PRECACHEANYTIME " +"DP_SV_PUNCHVECTOR " +"DP_SV_ROTATINGBMODEL " "DP_SV_SETCOLOR " "DP_SV_SLOWMO " "DP_TE_BLOOD " @@ -145,10 +170,14 @@ char *ENGINE_EXTENSIONS = "KRIMZON_SV_PARSECLIENTCOMMAND " "NEH_CMD_PLAY2 " "NEH_RESTOREGAME " +"NXQ_GFX_LETTERBOX " +"PRYDON_CLIENTCURSOR " +"TENEBRAE_GFX_DLIGHTS " "TW_SV_STEPCONTROL " +"NEXUIZ_PLAYERMODEL " ; -qboolean checkextension(char *name) +qboolean checkextension(const char *name) { int len; char *e, *start; @@ -180,7 +209,7 @@ checkextension(extensionname) */ void PF_checkextension (void) { - G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0)); } /* @@ -195,13 +224,13 @@ error(value) */ void PF_error (void) { - edict_t *ed; + prvm_edict_t *ed; char string[STRINGTEMP_LENGTH]; PF_VarString(0, string, sizeof(string)); - Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + Con_Printf("======SERVER ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string); + ed = PRVM_PROG_TO_EDICT(prog->globals.server->self); + ED_Print(ed); PF_ERROR("Program error"); } @@ -218,13 +247,13 @@ objerror(value) */ void PF_objerror (void) { - edict_t *ed; + prvm_edict_t *ed; char string[STRINGTEMP_LENGTH]; PF_VarString(0, string, sizeof(string)); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + Con_Printf("======OBJECT ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string); + ed = PRVM_PROG_TO_EDICT(prog->globals.server->self); + ED_Print(ed); ED_Free (ed); } @@ -239,7 +268,7 @@ makevectors(vector) */ void PF_makevectors (void) { - AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); + AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up); } /* @@ -252,8 +281,8 @@ vectorvectors(vector, vector) */ void PF_vectorvectors (void) { - VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward); - VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up); + 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); } /* @@ -267,21 +296,21 @@ setorigin (entity, origin) */ void PF_setorigin (void) { - edict_t *e; + prvm_edict_t *e; float *org; - e = G_EDICT(OFS_PARM0); - if (e == sv.edicts) + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) PF_WARNING("setorigin: can not modify world entity\n"); - if (e->e->free) + if (e->priv.server->free) PF_WARNING("setorigin: can not modify free entity\n"); - org = G_VECTOR(OFS_PARM1); - VectorCopy (org, e->v->origin); + org = PRVM_G_VECTOR(OFS_PARM1); + VectorCopy (org, e->fields.server->origin); SV_LinkEdict (e, false); } -void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) +void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate) { int i; @@ -290,9 +319,9 @@ void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) PF_ERROR("SetMinMaxSize: backwards mins/maxs\n"); // set derived values - VectorCopy (min, e->v->mins); - VectorCopy (max, e->v->maxs); - VectorSubtract (max, min, e->v->size); + VectorCopy (min, e->fields.server->mins); + VectorCopy (max, e->fields.server->maxs); + VectorSubtract (max, min, e->fields.server->size); SV_LinkEdict (e, false); } @@ -309,16 +338,16 @@ setsize (entity, minvector, maxvector) */ void PF_setsize (void) { - edict_t *e; + prvm_edict_t *e; float *min, *max; - e = G_EDICT(OFS_PARM0); - if (e == sv.edicts) + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) PF_WARNING("setsize: can not modify world entity\n"); - if (e->e->free) + if (e->priv.server->free) PF_WARNING("setsize: can not modify free entity\n"); - min = G_VECTOR(OFS_PARM1); - max = G_VECTOR(OFS_PARM2); + min = PRVM_G_VECTOR(OFS_PARM1); + max = PRVM_G_VECTOR(OFS_PARM2); SetMinMaxSize (e, min, max, false); } @@ -330,36 +359,31 @@ PF_setmodel setmodel(entity, model) ================= */ +static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16}; void PF_setmodel (void) { - edict_t *e; - char *m, **check; + prvm_edict_t *e; model_t *mod; int i; - e = G_EDICT(OFS_PARM0); - if (e == sv.edicts) + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) PF_WARNING("setmodel: can not modify world entity\n"); - if (e->e->free) + if (e->priv.server->free) PF_WARNING("setmodel: can not modify free entity\n"); - m = G_STRING(OFS_PARM1); - -// check to see if model was properly precached - for (i=0, check = sv.model_precache ; *check ; i++, check++) - if (!strcmp(*check, m)) - break; - - if (!*check) - PF_WARNING("setmodel: no precache\n"); - - - e->v->model = PR_SetString(*check); - e->v->modelindex = i; + i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1); + e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]); + e->fields.server->modelindex = i; - mod = sv.models[ (int)e->v->modelindex]; + mod = sv.models[i]; if (mod) - SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); + { + if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer) + SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); + else + SetMinMaxSize (e, quakemins, quakemaxs, true); + } else SetMinMaxSize (e, vec3_origin, vec3_origin, true); } @@ -377,7 +401,7 @@ void PF_bprint (void) { char string[STRINGTEMP_LENGTH]; PF_VarString(0, string, sizeof(string)); - SV_BroadcastPrintf("%s", string); + SV_BroadcastPrint(string); } /* @@ -395,17 +419,15 @@ void PF_sprint (void) int entnum; char string[STRINGTEMP_LENGTH]; - entnum = G_EDICTNUM(OFS_PARM0); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } client = svs.clients + entnum-1; - if (!client->netconnection) - return; PF_VarString(1, string, sizeof(string)); MSG_WriteChar(&client->message,svc_print); MSG_WriteString(&client->message, string); @@ -427,17 +449,15 @@ void PF_centerprint (void) int entnum; char string[STRINGTEMP_LENGTH]; - entnum = G_EDICTNUM(OFS_PARM0); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } client = svs.clients + entnum-1; - if (!client->netconnection) - return; PF_VarString(1, string, sizeof(string)); MSG_WriteChar(&client->message,svc_centerprint); MSG_WriteString(&client->message, string); @@ -457,7 +477,7 @@ void PF_normalize (void) vec3_t newvalue; float new; - value1 = G_VECTOR(OFS_PARM0); + value1 = PRVM_G_VECTOR(OFS_PARM0); new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; new = sqrt(new); @@ -472,7 +492,7 @@ void PF_normalize (void) newvalue[2] = value1[2] * new; } - VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); + VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN)); } /* @@ -487,12 +507,12 @@ void PF_vlen (void) float *value1; float new; - value1 = G_VECTOR(OFS_PARM0); + value1 = PRVM_G_VECTOR(OFS_PARM0); new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; new = sqrt(new); - G_FLOAT(OFS_RETURN) = new; + PRVM_G_FLOAT(OFS_RETURN) = new; } /* @@ -507,18 +527,18 @@ void PF_vectoyaw (void) float *value1; float yaw; - value1 = G_VECTOR(OFS_PARM0); + value1 = PRVM_G_VECTOR(OFS_PARM0); if (value1[1] == 0 && value1[0] == 0) yaw = 0; else { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + yaw = (atan2(value1[1], value1[0]) * 180 / M_PI); if (yaw < 0) yaw += 360; } - G_FLOAT(OFS_RETURN) = yaw; + PRVM_G_FLOAT(OFS_RETURN) = yaw; } @@ -531,11 +551,9 @@ vector vectoangles(vector) */ void PF_vectoangles (void) { - float *value1; - float forward; - float yaw, pitch; + double value1[3], forward, yaw, pitch; - value1 = G_VECTOR(OFS_PARM0); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), value1); if (value1[1] == 0 && value1[0] == 0) { @@ -560,14 +578,12 @@ void PF_vectoangles (void) yaw = 270; forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]); - pitch = (int) (atan2(value1[2], forward) * 180 / M_PI); + pitch = (atan2(value1[2], forward) * 180 / M_PI); if (pitch < 0) pitch += 360; } - G_FLOAT(OFS_RETURN+0) = pitch; - G_FLOAT(OFS_RETURN+1) = yaw; - G_FLOAT(OFS_RETURN+2) = 0; + VectorSet(PRVM_G_VECTOR(OFS_RETURN), pitch, yaw, 0); } /* @@ -581,11 +597,7 @@ random() */ void PF_random (void) { - float num; - - num = (rand ()&0x7fff) / ((float)0x7fff); - - G_FLOAT(OFS_RETURN) = num; + PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1); } /* @@ -601,10 +613,10 @@ void PF_particle (void) float color; float count; - org = G_VECTOR(OFS_PARM0); - dir = G_VECTOR(OFS_PARM1); - color = G_FLOAT(OFS_PARM2); - count = G_FLOAT(OFS_PARM3); + org = PRVM_G_VECTOR(OFS_PARM0); + dir = PRVM_G_VECTOR(OFS_PARM1); + color = PRVM_G_FLOAT(OFS_PARM2); + count = PRVM_G_FLOAT(OFS_PARM3); SV_StartParticle (org, dir, color, count); } @@ -617,27 +629,20 @@ PF_ambientsound */ void PF_ambientsound (void) { - char **check; - char *samp; + const char *samp; float *pos; float vol, attenuation; - int i, soundnum, large; + int soundnum, large; - pos = G_VECTOR (OFS_PARM0); - samp = G_STRING(OFS_PARM1); - vol = G_FLOAT(OFS_PARM2); - attenuation = G_FLOAT(OFS_PARM3); + pos = PRVM_G_VECTOR (OFS_PARM0); + samp = PRVM_G_STRING(OFS_PARM1); + vol = PRVM_G_FLOAT(OFS_PARM2); + attenuation = PRVM_G_FLOAT(OFS_PARM3); // check to see if samp was properly precached - for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++) - if (!strcmp(*check,samp)) - break; - - if (!*check) - { - Con_Printf ("no precache: %s\n", samp); + soundnum = SV_SoundIndex(samp, 1); + if (!soundnum) return; - } large = false; if (soundnum >= 256) @@ -650,8 +655,7 @@ void PF_ambientsound (void) else MSG_WriteByte (&sv.signon, svc_spawnstaticsound); - for (i=0 ; i<3 ; i++) - MSG_WriteDPCoord(&sv.signon, pos[i]); + MSG_WriteVector(&sv.signon, pos, sv.protocol); if (large) MSG_WriteShort (&sv.signon, soundnum); @@ -680,17 +684,17 @@ Larger attenuations will drop off. */ void PF_sound (void) { - char *sample; + const char *sample; int channel; - edict_t *entity; + prvm_edict_t *entity; int volume; float attenuation; - entity = G_EDICT(OFS_PARM0); - channel = G_FLOAT(OFS_PARM1); - sample = G_STRING(OFS_PARM2); - volume = G_FLOAT(OFS_PARM3) * 255; - attenuation = G_FLOAT(OFS_PARM4); + entity = PRVM_G_EDICT(OFS_PARM0); + channel = PRVM_G_FLOAT(OFS_PARM1); + sample = PRVM_G_STRING(OFS_PARM2); + volume = PRVM_G_FLOAT(OFS_PARM3) * 255; + attenuation = PRVM_G_FLOAT(OFS_PARM4); if (volume < 0 || volume > 255) PF_WARNING("SV_StartSound: volume must be in range 0-1\n"); @@ -731,30 +735,30 @@ void PF_traceline (void) { float *v1, *v2; trace_t trace; - int nomonsters; - edict_t *ent; + int move; + prvm_edict_t *ent; pr_xfunction->builtinsprofile += 30; - v1 = G_VECTOR(OFS_PARM0); - v2 = G_VECTOR(OFS_PARM1); - nomonsters = G_FLOAT(OFS_PARM2); - ent = G_EDICT(OFS_PARM3); - - trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); - - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; + v1 = PRVM_G_VECTOR(OFS_PARM0); + v2 = PRVM_G_VECTOR(OFS_PARM1); + move = PRVM_G_FLOAT(OFS_PARM2); + ent = PRVM_G_EDICT(OFS_PARM3); + + trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent); + + prog->globals.server->trace_allsolid = trace.allsolid; + prog->globals.server->trace_startsolid = trace.startsolid; + prog->globals.server->trace_fraction = trace.fraction; + prog->globals.server->trace_inwater = trace.inwater; + prog->globals.server->trace_inopen = trace.inopen; + VectorCopy (trace.endpos, prog->globals.server->trace_endpos); + VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = trace.plane.dist; if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); // FIXME: add trace_endcontents } @@ -775,62 +779,62 @@ void PF_tracebox (void) { float *v1, *v2, *m1, *m2; trace_t trace; - int nomonsters; - edict_t *ent; + int move; + prvm_edict_t *ent; pr_xfunction->builtinsprofile += 30; - v1 = G_VECTOR(OFS_PARM0); - m1 = G_VECTOR(OFS_PARM1); - m2 = G_VECTOR(OFS_PARM2); - v2 = G_VECTOR(OFS_PARM3); - nomonsters = G_FLOAT(OFS_PARM4); - ent = G_EDICT(OFS_PARM5); - - trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent); - - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; + v1 = PRVM_G_VECTOR(OFS_PARM0); + m1 = PRVM_G_VECTOR(OFS_PARM1); + m2 = PRVM_G_VECTOR(OFS_PARM2); + v2 = PRVM_G_VECTOR(OFS_PARM3); + move = PRVM_G_FLOAT(OFS_PARM4); + ent = PRVM_G_EDICT(OFS_PARM5); + + trace = SV_Move (v1, m1, m2, v2, move, ent); + + prog->globals.server->trace_allsolid = trace.allsolid; + prog->globals.server->trace_startsolid = trace.startsolid; + prog->globals.server->trace_fraction = trace.fraction; + prog->globals.server->trace_inwater = trace.inwater; + prog->globals.server->trace_inopen = trace.inopen; + VectorCopy (trace.endpos, prog->globals.server->trace_endpos); + VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = trace.plane.dist; if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); } -extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); -void PF_TraceToss (void) +extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore); +void PF_tracetoss (void) { trace_t trace; - edict_t *ent; - edict_t *ignore; + prvm_edict_t *ent; + prvm_edict_t *ignore; pr_xfunction->builtinsprofile += 600; - ent = G_EDICT(OFS_PARM0); - if (ent == sv.edicts) + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) PF_WARNING("tracetoss: can not use world entity\n"); - ignore = G_EDICT(OFS_PARM1); + ignore = PRVM_G_EDICT(OFS_PARM1); trace = SV_Trace_Toss (ent, ignore); - pr_global_struct->trace_allsolid = trace.allsolid; - pr_global_struct->trace_startsolid = trace.startsolid; - pr_global_struct->trace_fraction = trace.fraction; - pr_global_struct->trace_inwater = trace.inwater; - pr_global_struct->trace_inopen = trace.inopen; - VectorCopy (trace.endpos, pr_global_struct->trace_endpos); - VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; + prog->globals.server->trace_allsolid = trace.allsolid; + prog->globals.server->trace_startsolid = trace.startsolid; + prog->globals.server->trace_fraction = trace.fraction; + prog->globals.server->trace_inwater = trace.inwater; + prog->globals.server->trace_inopen = trace.inopen; + VectorCopy (trace.endpos, prog->globals.server->trace_endpos); + VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal); + prog->globals.server->trace_plane_dist = trace.plane.dist; if (trace.ent) - pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent); else - pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts); + prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts); } @@ -851,12 +855,12 @@ void PF_checkpos (void) //============================================================================ int checkpvsbytes; -qbyte checkpvs[MAX_MAP_LEAFS/8]; +unsigned char checkpvs[MAX_MAP_LEAFS/8]; int PF_newcheckclient (int check) { int i; - edict_t *ent; + prvm_edict_t *ent; vec3_t org; // cycle to the next one @@ -875,16 +879,16 @@ int PF_newcheckclient (int check) if (i == svs.maxclients+1) i = 1; // look up the client's edict - ent = EDICT_NUM(i); + ent = PRVM_EDICT_NUM(i); // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop) - if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET))) + if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET))) continue; // found a valid client (possibly the same one again) break; } // get the PVS for the entity - VectorAdd(ent->v->origin, ent->v->view_ofs, org); + 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)); @@ -910,7 +914,7 @@ name checkclient () int c_invis, c_notvis; void PF_checkclient (void) { - edict_t *ent, *self; + prvm_edict_t *ent, *self; vec3_t view; // find a new check if on a new frame @@ -921,20 +925,20 @@ void PF_checkclient (void) } // return check if it might be visible - ent = EDICT_NUM(sv.lastcheck); - if (ent->e->free || ent->v->health <= 0) + ent = PRVM_EDICT_NUM(sv.lastcheck); + if (ent->priv.server->free || ent->fields.server->health <= 0) { - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); return; } // if current entity can't possibly see the check entity, return 0 - self = PROG_TO_EDICT(pr_global_struct->self); - VectorAdd(self->v->origin, self->v->view_ofs, view); + self = PRVM_PROG_TO_EDICT(prog->globals.server->self); + VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view); if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view)) { c_notvis++; - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); return; } @@ -958,20 +962,20 @@ stuffcmd (clientent, value) void PF_stuffcmd (void) { int entnum; - char *str; + const char *str; client_t *old; - entnum = G_EDICTNUM(OFS_PARM0); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf("Can't stuffcmd to a non-client"); + Con_Print("Can't stuffcmd to a non-client\n"); return; } - str = G_STRING(OFS_PARM1); + str = PRVM_G_STRING(OFS_PARM1); old = host_client; - if ((host_client = svs.clients + entnum-1) && host_client->netconnection) - Host_ClientCommands ("%s", str); + host_client = svs.clients + entnum-1; + Host_ClientCommands ("%s", str); host_client = old; } @@ -986,7 +990,7 @@ localcmd (string) */ void PF_localcmd (void) { - Cbuf_AddText(G_STRING(OFS_PARM0)); + Cbuf_AddText(PRVM_G_STRING(OFS_PARM0)); } /* @@ -998,7 +1002,7 @@ float cvar (string) */ void PF_cvar (void) { - G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0)); } /* @@ -1010,7 +1014,7 @@ float cvar (string) */ void PF_cvar_set (void) { - Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1)); + Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1)); } /* @@ -1024,38 +1028,57 @@ findradius (origin, radius) */ void PF_findradius (void) { - edict_t *ent, *chain; - float radius; - float radius2; - float *org; - float eorg[3]; + prvm_edict_t *ent, *chain; + vec_t radius, radius2; + vec3_t org, eorg, mins, maxs; int i; + int numtouchedicts; + prvm_edict_t *touchedicts[MAX_EDICTS]; - chain = (edict_t *)sv.edicts; + chain = (prvm_edict_t *)prog->edicts; - org = G_VECTOR(OFS_PARM0); - radius = G_FLOAT(OFS_PARM1); + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + radius = PRVM_G_FLOAT(OFS_PARM1); radius2 = radius * radius; - ent = NEXT_EDICT(sv.edicts); - for (i=1 ; i MAX_EDICTS) + { + // this never happens + Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS); + numtouchedicts = MAX_EDICTS; + } + for (i = 0;i < numtouchedicts;i++) { + ent = touchedicts[i]; pr_xfunction->builtinsprofile++; - if (ent->e->free) - continue; - if (ent->v->solid == SOLID_NOT) - continue; - - // LordHavoc: compare against bounding box rather than center, - // and use DotProduct instead of Length, major speedup - eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]); - eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]); - eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]); - if (DotProduct(eorg, eorg) > radius2) + // Quake did not return non-solid entities but darkplaces does + // (note: this is the reason you can't blow up fallen zombies) + if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer) continue; - - ent->v->chain = EDICT_TO_PROG(chain); - chain = ent; + // LordHavoc: compare against bounding box rather than center so it + // doesn't miss large objects, and use DotProduct instead of Length + // for a major speedup + VectorSubtract(org, ent->fields.server->origin, eorg); + if (sv_gameplayfix_findradiusdistancetobox.integer) + { + eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]); + eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]); + 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); + if (DotProduct(eorg, eorg) < radius2) + { + ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain); + chain = ent; + } } RETURN_EDICT(chain); @@ -1073,7 +1096,7 @@ void PF_dprint (void) if (developer.integer) { PF_VarString(0, string, sizeof(string)); - Con_Printf("%s",string); + Con_Print(string); } } @@ -1081,42 +1104,42 @@ void PF_ftos (void) { float v; char *s; - v = G_FLOAT(OFS_PARM0); + v = PRVM_G_FLOAT(OFS_PARM0); s = PR_GetTempString(); if ((float)((int)v) == v) sprintf(s, "%i", (int)v); else sprintf(s, "%f", v); - G_INT(OFS_RETURN) = PR_SetString(s); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); } void PF_fabs (void) { float v; - v = G_FLOAT(OFS_PARM0); - G_FLOAT(OFS_RETURN) = fabs(v); + v = PRVM_G_FLOAT(OFS_PARM0); + PRVM_G_FLOAT(OFS_RETURN) = fabs(v); } void PF_vtos (void) { char *s; s = PR_GetTempString(); - sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); - G_INT(OFS_RETURN) = PR_SetString(s); + sprintf (s, "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); } void PF_etos (void) { char *s; s = PR_GetTempString(); - sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0)); - G_INT(OFS_RETURN) = PR_SetString(s); + sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); } void PF_Spawn (void) { - edict_t *ed; + prvm_edict_t *ed; pr_xfunction->builtinsprofile += 20; ed = ED_Alloc(); RETURN_EDICT(ed); @@ -1124,16 +1147,16 @@ void PF_Spawn (void) void PF_Remove (void) { - edict_t *ed; + prvm_edict_t *ed; pr_xfunction->builtinsprofile += 20; - ed = G_EDICT(OFS_PARM0); - if (ed == sv.edicts) + ed = PRVM_G_EDICT(OFS_PARM0); + if (ed == prog->edicts) PF_WARNING("remove: tried to remove world\n"); - if (NUM_FOR_EDICT(ed) <= svs.maxclients) + if (PRVM_NUM_FOR_EDICT(ed) <= svs.maxclients) PF_WARNING("remove: tried to remove a client\n"); // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...) - if (ed->e->free && developer.integer) + if (ed->priv.server->free && developer.integer) PF_WARNING("remove: tried to remove an entity that was already removed\n"); ED_Free (ed); } @@ -1144,23 +1167,23 @@ void PF_Find (void) { int e; int f; - char *s, *t; - edict_t *ed; + const char *s, *t; + prvm_edict_t *ed; - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_STRING(OFS_PARM2); + e = PRVM_G_EDICTNUM(OFS_PARM0); + f = PRVM_G_INT(OFS_PARM1); + s = PRVM_G_STRING(OFS_PARM2); if (!s || !s[0]) { - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); return; } - for (e++ ; e < sv.num_edicts ; e++) + for (e++ ; e < prog->num_edicts ; e++) { pr_xfunction->builtinsprofile++; - ed = EDICT_NUM(e); - if (ed->e->free) + ed = PRVM_EDICT_NUM(e); + if (ed->priv.server->free) continue; t = E_STRING(ed,f); if (!t) @@ -1172,7 +1195,7 @@ void PF_Find (void) } } - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); } // LordHavoc: added this for searching float, int, and entity reference fields @@ -1181,17 +1204,17 @@ void PF_FindFloat (void) int e; int f; float s; - edict_t *ed; + prvm_edict_t *ed; - e = G_EDICTNUM(OFS_PARM0); - f = G_INT(OFS_PARM1); - s = G_FLOAT(OFS_PARM2); + e = PRVM_G_EDICTNUM(OFS_PARM0); + f = PRVM_G_INT(OFS_PARM1); + s = PRVM_G_FLOAT(OFS_PARM2); - for (e++ ; e < sv.num_edicts ; e++) + for (e++ ; e < prog->num_edicts ; e++) { pr_xfunction->builtinsprofile++; - ed = EDICT_NUM(e); - if (ed->e->free) + ed = PRVM_EDICT_NUM(e); + if (ed->priv.server->free) continue; if (E_FLOAT(ed,f) == s) { @@ -1200,7 +1223,7 @@ void PF_FindFloat (void) } } - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); } // chained search for strings in entity fields @@ -1209,24 +1232,24 @@ void PF_findchain (void) { int i; int f; - char *s, *t; - edict_t *ent, *chain; + const char *s, *t; + prvm_edict_t *ent, *chain; - chain = (edict_t *)sv.edicts; + chain = (prvm_edict_t *)prog->edicts; - f = G_INT(OFS_PARM0); - s = G_STRING(OFS_PARM1); + f = PRVM_G_INT(OFS_PARM0); + s = PRVM_G_STRING(OFS_PARM1); if (!s || !s[0]) { - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); return; } - ent = NEXT_EDICT(sv.edicts); - for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + ent = PRVM_NEXT_EDICT(prog->edicts); + for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) { pr_xfunction->builtinsprofile++; - if (ent->e->free) + if (ent->priv.server->free) continue; t = E_STRING(ent,f); if (!t) @@ -1234,7 +1257,7 @@ void PF_findchain (void) if (strcmp(t,s)) continue; - ent->v->chain = EDICT_TO_PROG(chain); + ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain); chain = ent; } @@ -1248,91 +1271,102 @@ void PF_findchainfloat (void) int i; int f; float s; - edict_t *ent, *chain; + prvm_edict_t *ent, *chain; - chain = (edict_t *)sv.edicts; + chain = (prvm_edict_t *)prog->edicts; - f = G_INT(OFS_PARM0); - s = G_FLOAT(OFS_PARM1); + f = PRVM_G_INT(OFS_PARM0); + s = PRVM_G_FLOAT(OFS_PARM1); - ent = NEXT_EDICT(sv.edicts); - for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + ent = PRVM_NEXT_EDICT(prog->edicts); + for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) { pr_xfunction->builtinsprofile++; - if (ent->e->free) + if (ent->priv.server->free) continue; if (E_FLOAT(ent,f) != s) continue; - ent->v->chain = EDICT_TO_PROG(chain); + ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain); chain = ent; } RETURN_EDICT(chain); } -void PR_CheckEmptyString (char *s) +// LordHavoc: search for flags in float fields +void PF_findflags (void) { - if (s[0] <= ' ') - PF_ERROR("Bad string"); -} - -void PF_precache_file (void) -{ // precache_file is only used to copy files with qcc, it does nothing - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); -} - -void PF_precache_sound (void) -{ - char *s; - int i; - - if (sv.state != ss_loading) - PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions"); + int e; + int f; + int s; + prvm_edict_t *ed; - s = G_STRING(OFS_PARM0); - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); + e = PRVM_G_EDICTNUM(OFS_PARM0); + f = PRVM_G_INT(OFS_PARM1); + s = (int)PRVM_G_FLOAT(OFS_PARM2); - for (i=0 ; inum_edicts ; e++) { - if (!sv.sound_precache[i]) + pr_xfunction->builtinsprofile++; + ed = PRVM_EDICT_NUM(e); + if (ed->priv.server->free) + continue; + if ((int)E_FLOAT(ed,f) & s) { - sv.sound_precache[i] = s; + RETURN_EDICT(ed); return; } - if (!strcmp(sv.sound_precache[i], s)) - return; } - PF_ERROR("PF_precache_sound: overflow"); + + RETURN_EDICT(prog->edicts); } -void PF_precache_model (void) +// LordHavoc: chained search for flags in float fields +void PF_findchainflags (void) { - char *s; int i; + int f; + int s; + prvm_edict_t *ent, *chain; - if (sv.state != ss_loading) - PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions"); + chain = (prvm_edict_t *)prog->edicts; - s = G_STRING(OFS_PARM0); - if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0]))) - return; - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); + f = PRVM_G_INT(OFS_PARM0); + s = (int)PRVM_G_FLOAT(OFS_PARM1); - for (i=0 ; iedicts); + for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) { - if (!sv.model_precache[i]) - { - sv.model_precache[i] = s; - sv.models[i] = Mod_ForName (s, true, false, false); - return; - } - if (!strcmp(sv.model_precache[i], s)) - return; + pr_xfunction->builtinsprofile++; + if (ent->priv.server->free) + continue; + if (!((int)E_FLOAT(ent,f) & s)) + continue; + + ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain); + chain = ent; } - PF_ERROR("PF_precache_model: overflow"); + + RETURN_EDICT(chain); +} + +void PF_precache_file (void) +{ // precache_file is only used to copy files with qcc, it does nothing + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); +} + + +void PF_precache_sound (void) +{ + SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); +} + +void PF_precache_model (void) +{ + SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2); + PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); } @@ -1353,7 +1387,7 @@ void PF_traceoff (void) void PF_eprint (void) { - ED_PrintNum (G_EDICTNUM(OFS_PARM0)); + ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0)); } /* @@ -1365,24 +1399,24 @@ float(float yaw, float dist) walkmove */ void PF_walkmove (void) { - edict_t *ent; + prvm_edict_t *ent; float yaw, dist; vec3_t move; mfunction_t *oldf; int oldself; // assume failure if it returns early - G_FLOAT(OFS_RETURN) = 0; - - ent = PROG_TO_EDICT(pr_global_struct->self); - if (ent == sv.edicts) + PRVM_G_FLOAT(OFS_RETURN) = 0; + + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); + if (ent == prog->edicts) PF_WARNING("walkmove: can not modify world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("walkmove: can not modify free entity\n"); - yaw = G_FLOAT(OFS_PARM0); - dist = G_FLOAT(OFS_PARM1); + yaw = PRVM_G_FLOAT(OFS_PARM0); + dist = PRVM_G_FLOAT(OFS_PARM1); - if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) + if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) return; yaw = yaw*M_PI*2 / 360; @@ -1393,14 +1427,14 @@ void PF_walkmove (void) // save program state, because SV_movestep may call other progs oldf = pr_xfunction; - oldself = pr_global_struct->self; + oldself = prog->globals.server->self; - G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); + PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); // restore program state pr_xfunction = oldf; - pr_global_struct->self = oldself; + prog->globals.server->self = oldself; } /* @@ -1412,33 +1446,33 @@ void() droptofloor */ void PF_droptofloor (void) { - edict_t *ent; + prvm_edict_t *ent; vec3_t end; trace_t trace; // assume failure if it returns early - G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; - ent = PROG_TO_EDICT(pr_global_struct->self); - if (ent == sv.edicts) + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); + if (ent == prog->edicts) PF_WARNING("droptofloor: can not modify world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("droptofloor: can not modify free entity\n"); - VectorCopy (ent->v->origin, end); + VectorCopy (ent->fields.server->origin, end); end[2] -= 256; - trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); if (trace.fraction != 1) { - VectorCopy (trace.endpos, ent->v->origin); + VectorCopy (trace.endpos, ent->fields.server->origin); SV_LinkEdict (ent, false); - ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(trace.ent); - G_FLOAT(OFS_RETURN) = 1; + 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->e->suspendedinairflag = true; + ent->priv.server->suspendedinairflag = true; } } @@ -1452,15 +1486,15 @@ void(float style, string value) lightstyle void PF_lightstyle (void) { int style; - char *val; + const char *val; client_t *client; int j; - style = G_FLOAT(OFS_PARM0); - val = G_STRING(OFS_PARM1); + style = PRVM_G_FLOAT(OFS_PARM0); + val = PRVM_G_STRING(OFS_PARM1); // change the string in sv - sv.lightstyles[style] = val; + strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style])); // send message to all clients on this server if (sv.state != ss_active) @@ -1468,7 +1502,7 @@ void PF_lightstyle (void) for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++) { - if (client->netconnection) + if (client->active) { MSG_WriteChar (&client->message, svc_lightstyle); MSG_WriteChar (&client->message,style); @@ -1480,19 +1514,19 @@ void PF_lightstyle (void) void PF_rint (void) { float f; - f = G_FLOAT(OFS_PARM0); + f = PRVM_G_FLOAT(OFS_PARM0); if (f > 0) - G_FLOAT(OFS_RETURN) = (int)(f + 0.5); + PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5); else - G_FLOAT(OFS_RETURN) = (int)(f - 0.5); + PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5); } void PF_floor (void) { - G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0)); } void PF_ceil (void) { - G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0)); } @@ -1503,7 +1537,7 @@ PF_checkbottom */ void PF_checkbottom (void) { - G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0)); } /* @@ -1513,7 +1547,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0))); } /* @@ -1526,20 +1560,20 @@ entity nextent(entity) void PF_nextent (void) { int i; - edict_t *ent; + prvm_edict_t *ent; - i = G_EDICTNUM(OFS_PARM0); + i = PRVM_G_EDICTNUM(OFS_PARM0); while (1) { pr_xfunction->builtinsprofile++; i++; - if (i == sv.num_edicts) + if (i == prog->num_edicts) { - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); return; } - ent = EDICT_NUM(i); - if (!ent->e->free) + ent = PRVM_EDICT_NUM(i); + if (!ent->priv.server->free) { RETURN_EDICT(ent); return; @@ -1557,7 +1591,7 @@ vector aim(entity, missilespeed) */ void PF_aim (void) { - edict_t *ent, *check, *bestent; + prvm_edict_t *ent, *check, *bestent; vec3_t start, dir, end, bestdir; int i, j; trace_t tr; @@ -1565,26 +1599,29 @@ void PF_aim (void) float speed; // assume failure if it returns early - VectorClear(G_VECTOR(OFS_RETURN)); + VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN)); + // if sv_aim is so high it can't possibly accept anything, skip out early + if (sv_aim.value >= 1) + return; - ent = G_EDICT(OFS_PARM0); - if (ent == sv.edicts) + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) PF_WARNING("aim: can not use world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("aim: can not use free entity\n"); - speed = G_FLOAT(OFS_PARM1); + speed = PRVM_G_FLOAT(OFS_PARM1); - VectorCopy (ent->v->origin, start); + VectorCopy (ent->fields.server->origin, start); start[2] += 20; // try sending a trace straight - VectorCopy (pr_global_struct->v_forward, dir); + VectorCopy (prog->globals.server->v_forward, dir); VectorMA (start, 2048, dir, end); tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent); - if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM - && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) ) + if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM + && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) ) { - VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN)); + VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN)); return; } @@ -1594,22 +1631,22 @@ void PF_aim (void) bestdist = sv_aim.value; bestent = NULL; - check = NEXT_EDICT(sv.edicts); - for (i=1 ; iedicts); + for (i=1 ; inum_edicts ; i++, check = PRVM_NEXT_EDICT(check) ) { pr_xfunction->builtinsprofile++; - if (check->v->takedamage != DAMAGE_AIM) + if (check->fields.server->takedamage != DAMAGE_AIM) continue; if (check == ent) continue; - if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team) + if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team) continue; // don't aim at teammate for (j=0 ; j<3 ; j++) - end[j] = check->v->origin[j] - + 0.5*(check->v->mins[j] + check->v->maxs[j]); + end[j] = check->fields.server->origin[j] + + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]); VectorSubtract (end, start, dir); VectorNormalize (dir); - dist = DotProduct (dir, pr_global_struct->v_forward); + dist = DotProduct (dir, prog->globals.server->v_forward); if (dist < bestdist) continue; // to far to turn tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent); @@ -1622,16 +1659,16 @@ void PF_aim (void) if (bestent) { - VectorSubtract (bestent->v->origin, ent->v->origin, dir); - dist = DotProduct (dir, pr_global_struct->v_forward); - VectorScale (pr_global_struct->v_forward, dist, end); + VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir); + dist = DotProduct (dir, prog->globals.server->v_forward); + VectorScale (prog->globals.server->v_forward, dist, end); end[2] = dir[2]; VectorNormalize (end); - VectorCopy (end, G_VECTOR(OFS_RETURN)); + VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN)); } else { - VectorCopy (bestdir, G_VECTOR(OFS_RETURN)); + VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN)); } } @@ -1644,17 +1681,17 @@ This was a major timewaster in progs, so it was converted to C */ void PF_changeyaw (void) { - edict_t *ent; + prvm_edict_t *ent; float ideal, current, move, speed; - ent = PROG_TO_EDICT(pr_global_struct->self); - if (ent == sv.edicts) + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); + if (ent == prog->edicts) PF_WARNING("changeyaw: can not modify world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("changeyaw: can not modify free entity\n"); - current = ANGLEMOD(ent->v->angles[1]); - ideal = ent->v->ideal_yaw; - speed = ent->v->yaw_speed; + current = ANGLEMOD(ent->fields.server->angles[1]); + ideal = ent->fields.server->ideal_yaw; + speed = ent->fields.server->yaw_speed; if (current == ideal) return; @@ -1680,7 +1717,7 @@ void PF_changeyaw (void) move = -speed; } - ent->v->angles[1] = ANGLEMOD (current + move); + ent->fields.server->angles[1] = ANGLEMOD (current + move); } /* @@ -1690,24 +1727,24 @@ PF_changepitch */ void PF_changepitch (void) { - edict_t *ent; + prvm_edict_t *ent; float ideal, current, move, speed; - eval_t *val; + prvm_eval_t *val; - ent = G_EDICT(OFS_PARM0); - if (ent == sv.edicts) + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) PF_WARNING("changepitch: can not modify world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("changepitch: can not modify free entity\n"); - current = ANGLEMOD( ent->v->angles[0] ); - if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch))) + current = ANGLEMOD( ent->fields.server->angles[0] ); + if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch))) ideal = val->_float; else { PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n"); return; } - if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed))) + if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed))) speed = val->_float; else { @@ -1739,7 +1776,7 @@ void PF_changepitch (void) move = -speed; } - ent->v->angles[0] = ANGLEMOD (current + move); + ent->fields.server->angles[0] = ANGLEMOD (current + move); } /* @@ -1759,17 +1796,17 @@ sizebuf_t *WriteDest (void) { int entnum; int dest; - edict_t *ent; + prvm_edict_t *ent; - dest = G_FLOAT(OFS_PARM0); + dest = PRVM_G_FLOAT(OFS_PARM0); switch (dest) { case MSG_BROADCAST: return &sv.datagram; case MSG_ONE: - ent = PROG_TO_EDICT(pr_global_struct->msg_entity); - entnum = NUM_FOR_EDICT(ent); + 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) Host_Error("WriteDest: tried to write to non-client\n"); return &svs.clients[entnum-1].message; @@ -1790,81 +1827,81 @@ sizebuf_t *WriteDest (void) void PF_WriteByte (void) { - MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteChar (void) { - MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteShort (void) { - MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteLong (void) { - MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1)); } void PF_WriteAngle (void) { - MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); } void PF_WriteCoord (void) { - MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol); } void PF_WriteString (void) { - MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1)); + MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1)); } void PF_WriteEntity (void) { - MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1)); + MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1)); } //============================================================================= void PF_makestatic (void) { - edict_t *ent; + prvm_edict_t *ent; int i, large; - ent = G_EDICT(OFS_PARM0); - if (ent == sv.edicts) + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) PF_WARNING("makestatic: can not modify world entity\n"); - if (ent->e->free) + if (ent->priv.server->free) PF_WARNING("makestatic: can not modify free entity\n"); large = false; - if (ent->v->modelindex >= 256 || ent->v->frame >= 256) + if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256) large = true; if (large) { MSG_WriteByte (&sv.signon,svc_spawnstatic2); - MSG_WriteShort (&sv.signon, ent->v->modelindex); - MSG_WriteShort (&sv.signon, ent->v->frame); + MSG_WriteShort (&sv.signon, ent->fields.server->modelindex); + MSG_WriteShort (&sv.signon, ent->fields.server->frame); } else { MSG_WriteByte (&sv.signon,svc_spawnstatic); - MSG_WriteByte (&sv.signon, ent->v->modelindex); - MSG_WriteByte (&sv.signon, ent->v->frame); + MSG_WriteByte (&sv.signon, ent->fields.server->modelindex); + MSG_WriteByte (&sv.signon, ent->fields.server->frame); } - MSG_WriteByte (&sv.signon, ent->v->colormap); - MSG_WriteByte (&sv.signon, ent->v->skin); + MSG_WriteByte (&sv.signon, ent->fields.server->colormap); + MSG_WriteByte (&sv.signon, ent->fields.server->skin); for (i=0 ; i<3 ; i++) { - MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]); - MSG_WriteAngle(&sv.signon, ent->v->angles[i]); + MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol); + MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol); } // throw the entity away now @@ -1880,22 +1917,22 @@ PF_setspawnparms */ void PF_setspawnparms (void) { - edict_t *ent; + prvm_edict_t *ent; int i; client_t *client; - ent = G_EDICT(OFS_PARM0); - i = NUM_FOR_EDICT(ent); + ent = PRVM_G_EDICT(OFS_PARM0); + i = PRVM_NUM_FOR_EDICT(ent); if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active) { - Con_Printf("tried to setspawnparms on a non-client\n"); + Con_Print("tried to setspawnparms on a non-client\n"); return; } // copy spawn parms out of the client_t client = svs.clients + i-1; for (i=0 ; i< NUM_SPAWN_PARMS ; i++) - (&pr_global_struct->parm1)[i] = client->spawn_parms[i]; + (&prog->globals.server->parm1)[i] = client->spawn_parms[i]; } /* @@ -1905,30 +1942,30 @@ PF_changelevel */ void PF_changelevel (void) { - char *s; + const char *s; // make sure we don't issue two changelevels if (svs.changelevel_issued) return; svs.changelevel_issued = true; - s = G_STRING(OFS_PARM0); + s = PRVM_G_STRING(OFS_PARM0); Cbuf_AddText (va("changelevel %s\n",s)); } void PF_sin (void) { - G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0)); } void PF_cos (void) { - G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0)); } void PF_sqrt (void) { - G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0)); } /* @@ -1950,7 +1987,7 @@ void PF_randomvec (void) temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0; } while (DotProduct(temp, temp) >= 1); - VectorCopy (temp, G_VECTOR(OFS_RETURN)); + VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN)); } /* @@ -1969,26 +2006,22 @@ void PF_GetLight (void) { vec3_t ambientcolor, diffusecolor, diffusenormal; vec_t *p; - p = G_VECTOR(OFS_PARM0); + p = PRVM_G_VECTOR(OFS_PARM0); VectorClear(ambientcolor); VectorClear(diffusecolor); VectorClear(diffusenormal); if (sv.worldmodel && sv.worldmodel->brush.LightPoint) sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal); - VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN)); + VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN)); } -#define MAX_QC_CVARS 128 -cvar_t qc_cvar[MAX_QC_CVARS]; -int currentqc_cvar; - void PF_registercvar (void) { - char *name, *value; - cvar_t *variable; - name = G_STRING(OFS_PARM0); - value = G_STRING(OFS_PARM1); - G_FLOAT(OFS_RETURN) = 0; + const char *name, *value; + name = PRVM_G_STRING(OFS_PARM0); + value = PRVM_G_STRING(OFS_PARM1); + PRVM_G_FLOAT(OFS_RETURN) = 0; + // first check to see if it has already been defined if (Cvar_FindVar (name)) return; @@ -1996,23 +2029,13 @@ void PF_registercvar (void) // check for overlap with a command if (Cmd_Exists (name)) { - Con_Printf ("PF_registercvar: %s is a command\n", name); + Con_Printf("PF_registercvar: %s is a command\n", name); return; } - if (currentqc_cvar >= MAX_QC_CVARS) - PF_ERROR("PF_registercvar: ran out of cvar slots\n"); - -// copy the name and value - variable = &qc_cvar[currentqc_cvar++]; - variable->name = Z_Malloc (strlen(name)+1); - strcpy (variable->name, name); - variable->string = Z_Malloc (strlen(value)+1); - strcpy (variable->string, value); - variable->value = atof (value); + Cvar_Get(name, value, 0); - Cvar_RegisterVariable(variable); - G_FLOAT(OFS_RETURN) = 1; // success + PRVM_G_FLOAT(OFS_RETURN) = 1; // success } /* @@ -2028,19 +2051,19 @@ void PF_min (void) { // LordHavoc: 3+ argument enhancement suggested by FrikaC if (pr_argc == 2) - G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); else if (pr_argc >= 3) { int i; - float f = G_FLOAT(OFS_PARM0); + float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < pr_argc;i++) - if (G_FLOAT((OFS_PARM0+i*3)) < f) - f = G_FLOAT((OFS_PARM0+i*3)); - G_FLOAT(OFS_RETURN) = f; + if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f) + f = PRVM_G_FLOAT((OFS_PARM0+i*3)); + PRVM_G_FLOAT(OFS_RETURN) = f; } else { - G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; PF_WARNING("min: must supply at least 2 floats\n"); } } @@ -2058,19 +2081,19 @@ void PF_max (void) { // LordHavoc: 3+ argument enhancement suggested by FrikaC if (pr_argc == 2) - G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); else if (pr_argc >= 3) { int i; - float f = G_FLOAT(OFS_PARM0); + float f = PRVM_G_FLOAT(OFS_PARM0); for (i = 1;i < pr_argc;i++) - if (G_FLOAT((OFS_PARM0+i*3)) > f) - f = G_FLOAT((OFS_PARM0+i*3)); - G_FLOAT(OFS_RETURN) = f; + if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f) + f = PRVM_G_FLOAT((OFS_PARM0+i*3)); + PRVM_G_FLOAT(OFS_RETURN) = f; } else { - G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; PF_WARNING("max: must supply at least 2 floats\n"); } } @@ -2086,7 +2109,7 @@ min(min, value, max) */ void PF_bound (void) { - G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2)); + PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2)); } /* @@ -2100,7 +2123,7 @@ pow(a, b) */ void PF_pow (void) { - G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)); } /* @@ -2114,16 +2137,16 @@ copyentity(src, dst) */ void PF_copyentity (void) { - edict_t *in, *out; - in = G_EDICT(OFS_PARM0); - if (in == sv.edicts) + prvm_edict_t *in, *out; + in = PRVM_G_EDICT(OFS_PARM0); + if (in == prog->edicts) PF_WARNING("copyentity: can not read world entity\n"); - if (in->e->free) + if (in->priv.server->free) PF_WARNING("copyentity: can not read free entity\n"); - out = G_EDICT(OFS_PARM1); - if (out == sv.edicts) + out = PRVM_G_EDICT(OFS_PARM1); + if (out == prog->edicts) PF_WARNING("copyentity: can not modify world entity\n"); - if (out->e->free) + if (out->priv.server->free) PF_WARNING("copyentity: can not modify free entity\n"); memcpy(out->v, in->v, progs->entityfields * 4); } @@ -2141,27 +2164,33 @@ void PF_setcolor (void) { client_t *client; int entnum, i; - eval_t *val; + prvm_eval_t *val; - entnum = G_EDICTNUM(OFS_PARM0); - i = G_FLOAT(OFS_PARM1); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); + i = PRVM_G_FLOAT(OFS_PARM1); if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to setcolor a non-client\n"); + Con_Print("tried to setcolor a non-client\n"); return; } client = svs.clients + entnum-1; - if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors))) - val->_float = i; + if (client->edict) + { + if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors))) + val->_float = i; + client->edict->fields.server->team = (i & 15) + 1; + } client->colors = i; - client->old_colors = i; - client->edict->v->team = (i & 15) + 1; - - MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); - MSG_WriteByte (&sv.reliable_datagram, entnum - 1); - MSG_WriteByte (&sv.reliable_datagram, i); + if (client->old_colors != client->colors) + { + client->old_colors = client->colors; + // send notification to all clients + MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); + MSG_WriteByte (&sv.reliable_datagram, client - svs.clients); + MSG_WriteByte (&sv.reliable_datagram, client->colors); + } } /* @@ -2173,50 +2202,54 @@ effect(origin, modelname, startframe, framecount, framerate) */ void PF_effect (void) { - char *s; - s = G_STRING(OFS_PARM1); + int i; + const char *s; + s = PRVM_G_STRING(OFS_PARM1); if (!s || !s[0]) PF_WARNING("effect: no model specified\n"); - SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4)); + 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)); } void PF_te_blood (void) { - if (G_FLOAT(OFS_PARM2) < 1) + if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOOD); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // velocity - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count - MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); + MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); } void PF_te_bloodshower (void) { - if (G_FLOAT(OFS_PARM3) < 1) + if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER); // min - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // max - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // speed - MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2)); + MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol); // count - MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); } void PF_te_explosionrgb (void) @@ -2224,107 +2257,107 @@ void PF_te_explosionrgb (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // color - MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255)); - MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255)); - MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255)); + 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)); } void PF_te_particlecube (void) { - if (G_FLOAT(OFS_PARM3) < 1) + if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE); // min - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // max - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // velocity - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); // count - MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); // gravity true/false - MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0); + MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0); // randomvel - MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6)); + MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol); } void PF_te_particlerain (void) { - if (G_FLOAT(OFS_PARM3) < 1) + if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN); // min - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // max - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // velocity - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); // count - MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); } void PF_te_particlesnow (void) { - if (G_FLOAT(OFS_PARM3) < 1) + if (PRVM_G_FLOAT(OFS_PARM3) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW); // min - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // max - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // velocity - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); // count - MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); + MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color - MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4)); + MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4)); } void PF_te_spark (void) { - if (G_FLOAT(OFS_PARM2) < 1) + if (PRVM_G_FLOAT(OFS_PARM2) < 1) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPARK); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // velocity - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); - MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127)); + MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count - MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255)); + MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); } void PF_te_gunshotquad (void) @@ -2332,9 +2365,9 @@ void PF_te_gunshotquad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_spikequad (void) @@ -2342,9 +2375,9 @@ void PF_te_spikequad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_superspikequad (void) @@ -2352,9 +2385,9 @@ void PF_te_superspikequad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_explosionquad (void) @@ -2362,9 +2395,9 @@ void PF_te_explosionquad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_smallflash (void) @@ -2372,29 +2405,29 @@ void PF_te_smallflash (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SMALLFLASH); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_customflash (void) { - if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0)) + if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0)) return; MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // radius - MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255)); + MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255)); // lifetime - MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255)); + MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255)); // color - MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255)); - MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255)); - MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255)); + 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)); } void PF_te_gunshot (void) @@ -2402,9 +2435,9 @@ void PF_te_gunshot (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOT); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_spike (void) @@ -2412,9 +2445,9 @@ void PF_te_spike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKE); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_superspike (void) @@ -2422,9 +2455,9 @@ void PF_te_superspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_explosion (void) @@ -2432,9 +2465,9 @@ void PF_te_explosion (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_tarexplosion (void) @@ -2442,9 +2475,9 @@ void PF_te_tarexplosion (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_wizspike (void) @@ -2452,9 +2485,9 @@ void PF_te_wizspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_WIZSPIKE); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_knightspike (void) @@ -2462,9 +2495,9 @@ void PF_te_knightspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_lavasplash (void) @@ -2472,9 +2505,9 @@ void PF_te_lavasplash (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LAVASPLASH); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_teleport (void) @@ -2482,9 +2515,9 @@ void PF_te_teleport (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TELEPORT); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } void PF_te_explosion2 (void) @@ -2492,11 +2525,12 @@ void PF_te_explosion2 (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION2); // origin - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); // color - MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1)); + MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1)); + MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2)); } void PF_te_lightning1 (void) @@ -2504,15 +2538,15 @@ void PF_te_lightning1 (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING1); // owner entity - MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // end - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); } void PF_te_lightning2 (void) @@ -2520,15 +2554,15 @@ void PF_te_lightning2 (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING2); // owner entity - MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // end - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); } void PF_te_lightning3 (void) @@ -2536,15 +2570,15 @@ void PF_te_lightning3 (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LIGHTNING3); // owner entity - MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // end - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); } void PF_te_beam (void) @@ -2552,183 +2586,204 @@ void PF_te_beam (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BEAM); // owner entity - MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); + MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol); + MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // end - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + 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); } void PF_te_plasmaburn (void) { MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PLASMABURN); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + 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); } -static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out) +static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out) { - int i, j; - vec3_t v1, clipplanenormal, normal; - vec_t clipplanedist, clipdist; + 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); - if (surf->flags & SURF_PLANEBACK) - VectorNegate(surf->plane->normal, normal); - else - VectorCopy(surf->plane->normal, normal); - for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++) - { - VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1); - VectorNormalizeFast(v1); - CrossProduct(v1, normal, clipplanenormal); - clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal); - clipdist = DotProduct(out, clipplanenormal) - clipplanedist; - if (clipdist > 0) + for (i = 0, e = (surface->groupmesh->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; + TriangleNormal(v[0], v[1], v[2], facenormal); + VectorNormalize(facenormal); + offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal); + VectorMA(p, offsetdist, facenormal, temp); + for (j = 0, k = 2;j < 3;k = j, j++) { - clipdist = -clipdist; - VectorMA(out, clipdist, clipplanenormal, out); + VectorSubtract(v[k], v[j], edgenormal); + CrossProduct(edgenormal, facenormal, sidenormal); + VectorNormalize(sidenormal); + offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal); + if (offsetdist < 0) + VectorMA(temp, offsetdist, sidenormal, temp); + } + dist = VectorDistance2(temp, p); + if (bestdist > dist) + { + bestdist = dist; + VectorCopy(temp, out); } } } -static msurface_t *getsurface(edict_t *ed, int surfnum) +static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum) { int modelindex; model_t *model; - if (!ed || ed->e->free) + if (!ed || ed->priv.server->free) return NULL; - modelindex = ed->v->modelindex; + modelindex = ed->fields.server->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) return NULL; model = sv.models[modelindex]; - if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces) + if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; - return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface; + return model->data_surfaces + surfacenum + model->firstmodelsurface; } //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; void PF_getsurfacenumpoints(void) { - msurface_t *surf; + msurface_t *surface; // return 0 if no such surface - if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) { - G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; return; } - G_FLOAT(OFS_RETURN) = surf->poly_numverts; + // note: this (incorrectly) assumes it is a simple polygon + PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices; } //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435; void PF_getsurfacepoint(void) { - edict_t *ed; - msurface_t *surf; + prvm_edict_t *ed; + msurface_t *surface; int pointnum; - VectorClear(G_VECTOR(OFS_RETURN)); - ed = G_EDICT(OFS_PARM0); - if (!ed || ed->e->free) + VectorClear(PRVM_G_VECTOR(OFS_RETURN)); + ed = PRVM_G_EDICT(OFS_PARM0); + if (!ed || ed->priv.server->free) return; - if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) + if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) return; - pointnum = G_FLOAT(OFS_PARM2); - if (pointnum < 0 || pointnum >= surf->poly_numverts) + // note: this (incorrectly) assumes it is a simple polygon + pointnum = PRVM_G_FLOAT(OFS_PARM2); + if (pointnum < 0 || pointnum >= surface->num_vertices) return; // FIXME: implement rotation/scaling - VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN)); + VectorAdd(&(surface->groupmesh->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) { - msurface_t *surf; - VectorClear(G_VECTOR(OFS_RETURN)); - if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + 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)))) return; // FIXME: implement rotation/scaling - if (surf->flags & SURF_PLANEBACK) - VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN)); - else - VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN)); + // 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); + VectorNormalize(normal); + VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; void PF_getsurfacetexture(void) { - msurface_t *surf; - G_INT(OFS_RETURN) = 0; - if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) + msurface_t *surface; + PRVM_G_INT(OFS_RETURN) = 0; + if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) return; - G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name); + 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 surfnum, best, modelindex; + int surfacenum, best, modelindex; vec3_t clipped, p; vec_t dist, bestdist; - edict_t *ed; + prvm_edict_t *ed; model_t *model; - msurface_t *surf; + msurface_t *surface; vec_t *point; - G_FLOAT(OFS_RETURN) = -1; - ed = G_EDICT(OFS_PARM0); - point = G_VECTOR(OFS_PARM1); + PRVM_G_FLOAT(OFS_RETURN) = -1; + ed = PRVM_G_EDICT(OFS_PARM0); + point = PRVM_G_VECTOR(OFS_PARM1); - if (!ed || ed->e->free) + if (!ed || ed->priv.server->free) return; - modelindex = ed->v->modelindex; + modelindex = ed->fields.server->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) return; model = sv.models[modelindex]; - if (!model->brushq1.numsurfaces) + if (!model->num_surfaces) return; // FIXME: implement rotation/scaling - VectorSubtract(point, ed->v->origin, p); + VectorSubtract(point, ed->fields.server->origin, p); best = -1; bestdist = 1000000000; - for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++) - { - surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface; - dist = PlaneDiff(p, surf->plane); - dist = dist * dist; + for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++) + { + surface = model->data_surfaces + surfacenum + model->firstmodelsurface; + // first see if the nearest point on the surface's box is closer than the previous match + clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0]; + clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1]; + clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2]; + dist = VectorLength2(clipped); if (dist < bestdist) { - clippointtosurface(surf, p, clipped); + // it is, check the nearest point on the actual geometry + clippointtosurface(surface, p, clipped); VectorSubtract(clipped, p, clipped); - dist += DotProduct(clipped, clipped); + dist += VectorLength2(clipped); if (dist < bestdist) { - best = surfnum; + // that's closer too, store it as the best match + best = surfacenum; bestdist = dist; } } } - G_FLOAT(OFS_RETURN) = best; + PRVM_G_FLOAT(OFS_RETURN) = best; } //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; void PF_getsurfaceclippedpoint(void) { - edict_t *ed; - msurface_t *surf; + prvm_edict_t *ed; + msurface_t *surface; vec3_t p, out; - VectorClear(G_VECTOR(OFS_RETURN)); - ed = G_EDICT(OFS_PARM0); - if (!ed || ed->e->free) + VectorClear(PRVM_G_VECTOR(OFS_RETURN)); + ed = PRVM_G_EDICT(OFS_PARM0); + if (!ed || ed->priv.server->free) return; - if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) + if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) return; // FIXME: implement rotation/scaling - VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p); - clippointtosurface(surf, p, out); + VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p); + clippointtosurface(surface, p, out); // FIXME: implement rotation/scaling - VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN)); + VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); } #define MAX_PRFILES 256 @@ -2756,24 +2811,24 @@ void PF_stof(void) { char string[STRINGTEMP_LENGTH]; PF_VarString(0, string, sizeof(string)); - G_FLOAT(OFS_RETURN) = atof(string); + PRVM_G_FLOAT(OFS_RETURN) = atof(string); } //float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason void PF_fopen(void) { int filenum, mode; - char *modestring, *filename; + const char *modestring, *filename; for (filenum = 0;filenum < MAX_PRFILES;filenum++) if (pr_files[filenum] == NULL) break; if (filenum >= MAX_PRFILES) { Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES); - G_FLOAT(OFS_RETURN) = -2; + PRVM_G_FLOAT(OFS_RETURN) = -2; return; } - mode = G_FLOAT(OFS_PARM1); + mode = PRVM_G_FLOAT(OFS_PARM1); switch(mode) { case 0: // FILE_READ @@ -2787,31 +2842,26 @@ void PF_fopen(void) break; default: Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode); - G_FLOAT(OFS_RETURN) = -3; - return; - } - filename = G_STRING(OFS_PARM0); - // .. is parent directory on many platforms - // / is parent directory on Amiga - // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea) - // \ is a windows-ism (so it's naughty to use it, / works on all platforms) - if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\')) - { - Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename); - G_FLOAT(OFS_RETURN) = -4; + PRVM_G_FLOAT(OFS_RETURN) = -3; return; } - pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false); + filename = PRVM_G_STRING(OFS_PARM0); + // -4 failure (dangerous/non-portable filename) removed, FS_Open checks + pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false, false); + + if (pr_files[filenum] == NULL && modestring == "rb") + pr_files[filenum] = FS_Open(filename, modestring, false, false); + if (pr_files[filenum] == NULL) - G_FLOAT(OFS_RETURN) = -1; + PRVM_G_FLOAT(OFS_RETURN) = -1; else - G_FLOAT(OFS_RETURN) = filenum; + PRVM_G_FLOAT(OFS_RETURN) = filenum; } //void(float fhandle) fclose = #111; // closes a file void PF_fclose(void) { - int filenum = G_FLOAT(OFS_PARM0); + int filenum = PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= MAX_PRFILES) { Con_Printf("PF_fclose: invalid file handle %i\n", filenum); @@ -2831,7 +2881,7 @@ void PF_fgets(void) { int c, end; static char string[STRINGTEMP_LENGTH]; - int filenum = G_FLOAT(OFS_PARM0); + int filenum = PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= MAX_PRFILES) { Con_Printf("PF_fgets: invalid file handle %i\n", filenum); @@ -2854,13 +2904,17 @@ void PF_fgets(void) string[end] = 0; // remove \n following \r if (c == '\r') + { c = FS_Getc(pr_files[filenum]); + if (c != '\n') + FS_UnGetc(pr_files[filenum], (unsigned char)c); + } if (developer.integer) Con_Printf("fgets: %s\n", string); - if (c >= 0) - G_INT(OFS_RETURN) = PR_SetString(string); + if (c >= 0 || end) + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); else - G_INT(OFS_RETURN) = 0; + PRVM_G_INT(OFS_RETURN) = 0; } //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file @@ -2868,7 +2922,7 @@ void PF_fputs(void) { int stringlength; char string[STRINGTEMP_LENGTH]; - int filenum = G_FLOAT(OFS_PARM0); + int filenum = PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= MAX_PRFILES) { Con_Printf("PF_fputs: invalid file handle %i\n", filenum); @@ -2889,12 +2943,12 @@ void PF_fputs(void) //float(string s) strlen = #114; // returns how many characters are in a string void PF_strlen(void) { - char *s; - s = G_STRING(OFS_PARM0); + const char *s; + s = PRVM_G_STRING(OFS_PARM0); if (s) - G_FLOAT(OFS_RETURN) = strlen(s); + PRVM_G_FLOAT(OFS_RETURN) = strlen(s); else - G_FLOAT(OFS_RETURN) = 0; + PRVM_G_FLOAT(OFS_RETURN) = 0; } //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring @@ -2902,24 +2956,25 @@ void PF_strcat(void) { char *s = PR_GetTempString(); PF_VarString(0, s, STRINGTEMP_LENGTH); - G_INT(OFS_RETURN) = PR_SetString(s); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s); } //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring void PF_substring(void) { int i, start, length; - char *s, *string = PR_GetTempString(); - s = G_STRING(OFS_PARM0); - start = G_FLOAT(OFS_PARM1); - length = G_FLOAT(OFS_PARM2); + const char *s; + char *string = PR_GetTempString(); + s = PRVM_G_STRING(OFS_PARM0); + start = PRVM_G_FLOAT(OFS_PARM1); + length = PRVM_G_FLOAT(OFS_PARM2); if (!s) s = ""; for (i = 0;i < start && *s;i++, s++); for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++) string[i] = *s; string[i] = 0; - G_INT(OFS_RETURN) = PR_SetString(string); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); } //vector(string s) stov = #117; // returns vector value from a string @@ -2927,23 +2982,24 @@ void PF_stov(void) { char string[STRINGTEMP_LENGTH]; PF_VarString(0, string, sizeof(string)); - Math_atov(string, G_VECTOR(OFS_RETURN)); + Math_atov(string, PRVM_G_VECTOR(OFS_RETURN)); } //string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often) void PF_strzone(void) { - char *in, *out; - in = G_STRING(OFS_PARM0); - out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1); + const char *in; + char *out; + in = PRVM_G_STRING(OFS_PARM0); + out = PR_AllocString(strlen(in) + 1); strcpy(out, in); - G_INT(OFS_RETURN) = PR_SetString(out); + PRVM_G_INT(OFS_RETURN) = PR_SetQCString(out); } //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!) void PF_strunzone(void) { - Mem_Free(G_STRING(OFS_PARM0)); + PR_FreeString((char *)PRVM_G_STRING(OFS_PARM0)); } //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client @@ -2954,104 +3010,302 @@ void PF_clientcommand (void) int i; //find client for this entity - i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1); + i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1); if (i < 0 || i >= svs.maxclients || !svs.clients[i].active) { - Con_Printf("PF_clientcommand: entity is not a client"); + Con_Print("PF_clientcommand: entity is not a client\n"); return; } temp_client = host_client; host_client = svs.clients + i; - Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client); + Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client); host_client = temp_client; } //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many //this function originally written by KrimZon, made shorter by LordHavoc -char **tokens = NULL; -int max_tokens, num_tokens = 0; +//20040203: rewritten by LordHavoc (no longer uses allocations) +int num_tokens = 0; +char *tokens[256], tokenbuf[4096]; void PF_tokenize (void) { + int pos; const char *p; - char *str; - str = G_STRING(OFS_PARM0); - - if (tokens != NULL) - { - int i; - for (i=0;i= (int)(sizeof(tokens)/sizeof(tokens[0]))) + break; + if (pos + strlen(com_token) + 1 > sizeof(tokenbuf)) + break; + tokens[num_tokens++] = tokenbuf + pos; + strcpy(tokenbuf + pos, com_token); + pos += strlen(com_token) + 1; } - G_FLOAT(OFS_RETURN) = num_tokens; + PRVM_G_FLOAT(OFS_RETURN) = num_tokens; } //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index) //this function originally written by KrimZon, made shorter by LordHavoc void PF_argv (void) { - int token_num = G_FLOAT(OFS_PARM0); + int token_num = PRVM_G_FLOAT(OFS_PARM0); if (token_num >= 0 && token_num < num_tokens) - G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]); else - G_INT(OFS_RETURN) = PR_SetString(""); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL); } //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) void PF_setattachment (void) { - edict_t *e = G_EDICT(OFS_PARM0); - edict_t *tagentity = G_EDICT(OFS_PARM1); - char *tagname = G_STRING(OFS_PARM2); - eval_t *v; - int i, modelindex; + prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); + prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1); + const char *tagname = PRVM_G_STRING(OFS_PARM2); + prvm_eval_t *v; + int modelindex; model_t *model; - if (e == sv.edicts) + if (e == prog->edicts) PF_WARNING("setattachment: can not modify world entity\n"); - if (e->e->free) + if (e->priv.server->free) PF_WARNING("setattachment: can not modify free entity\n"); if (tagentity == NULL) - tagentity = sv.edicts; + tagentity = prog->edicts; - v = GETEDICTFIELDVALUE(e, eval_tag_entity); + v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity); if (v) - v->edict = EDICT_TO_PROG(tagentity); + fields.server->edict = PRVM_EDICT_TO_PROG(tagentity); - v = GETEDICTFIELDVALUE(e, eval_tag_index); + v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index); if (v) - v->_float = 0; - if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0]) + fields.server->_float = 0; + if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0]) { - modelindex = (int)tagentity->v->modelindex; + modelindex = (int)tagentity->fields.server->modelindex; if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) { - if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames) - for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++) - if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name)) - v->_float = i + 1; - if (v->_float == 0 && model->alias.aliasnum_tags) - for (i = 0;i < model->alias.aliasnum_tags;i++) - if (!strcmp(tagname, model->alias.aliasdata_tags[i].name)) - v->_float = i + 1; - 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", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name); + fields.server->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname); + if (fields.server->_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); } else - Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity)); + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity)); + } +} + +///////////////////////////////////////// +// DP_MD3_TAGINFO extension coded by VorteX + +int SV_GetTagIndex (prvm_edict_t *e, const char *tagname) +{ + int i; + model_t *model; + + i = 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); +}; + +// Warnings/errors code: +// 0 - normal (everything all-right) +// 1 - world entity +// 2 - free entity +// 3 - null or non-precached model +// 4 - no tags with requested index +// 5 - runaway loop at attachment chain +extern cvar_t cl_bob; +extern cvar_t cl_bobcycle; +extern cvar_t cl_bobup; +int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) +{ + prvm_eval_t *val; + int modelindex, reqframe, attachloop; + matrix4x4_t entitymatrix, tagmatrix, attachmatrix; + prvm_edict_t *attachent; + model_t *model; + + Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix + + if (ent == prog->edicts) + return 1; + if (ent->priv.server->free) + return 2; + + modelindex = (int)ent->fields.server->modelindex; + if (modelindex <= 0 || modelindex > MAX_MODELS) + return 3; + + 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) + { + int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix); + if (ret) + 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 + { + 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; + } + while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict); + } + + // 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]); + + 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); + 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 + if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value) + { + double bob, cycle; + // LordHavoc: this code is *weird*, but not replacable (I think it + // should be done in QC on the server, but oh well, quake is quake) + // LordHavoc: figured out bobup: the time at which the sin is at 180 + // degrees (which allows lengthening or squishing the peak or valley) + cycle = sv.time/cl_bobcycle.value; + cycle -= (int)cycle; + if (cycle < cl_bobup.value) + cycle = sin(M_PI * cycle / cl_bobup.value); + else + cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value)); + // bob is proportional to velocity in the xy plane + // (don't count Z, or jumping messes it up) + bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value; + bob = bob*0.3 + bob*0.7*cycle; + out->m[2][3] += bound(-7, bob, 4); + } + */ + } + return 0; +} + +//float(entity ent, string tagname) gettagindex; + +void PF_gettagindex (void) +{ + prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0); + const char *tag_name = PRVM_G_STRING(OFS_PARM1); + int modelindex, tag_index; + + if (ent == prog->edicts) + PF_WARNING("gettagindex: can't affect world entity\n"); + if (ent->priv.server->free) + PF_WARNING("gettagindex: can't affect free entity\n"); + + modelindex = (int)ent->fields.server->modelindex; + tag_index = 0; + if (modelindex <= 0 || modelindex > MAX_MODELS) + Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent)); + else + { + 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); + } + PRVM_G_FLOAT(OFS_RETURN) = tag_index; +}; + +//vector(entity ent, float tagindex) gettaginfo; +void PF_gettaginfo (void) +{ + prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0); + int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); + matrix4x4_t tag_matrix; + int returncode; + + returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex); + Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN)); + + switch(returncode) + { + case 1: + PF_WARNING("gettagindex: can't affect world entity\n"); + break; + case 2: + PF_WARNING("gettagindex: can't affect free entity\n"); + break; + case 3: + Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e)); + break; + case 4: + Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex); + break; + case 5: + Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e)); + break; } } @@ -3089,16 +3343,16 @@ float search_begin(string pattern, float caseinsensitive, float quiet) void PF_search_begin(void) { int handle; - char *pattern; + const char *pattern; int caseinsens, quiet; - pattern = G_STRING(OFS_PARM0); + pattern = PRVM_G_STRING(OFS_PARM0); + if (!pattern || pattern[0] <= ' ') + PF_ERROR("PF_search_begin: Bad string"); - PR_CheckEmptyString(pattern); + caseinsens = PRVM_G_FLOAT(OFS_PARM1); + quiet = PRVM_G_FLOAT(OFS_PARM2); - caseinsens = G_FLOAT(OFS_PARM1); - quiet = G_FLOAT(OFS_PARM2); - for(handle = 0; handle < MAX_SEARCHES; handle++) if(!pr_fssearchlist[handle]) break; @@ -3106,14 +3360,14 @@ void PF_search_begin(void) if(handle >= MAX_SEARCHES) { Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES); - G_FLOAT(OFS_RETURN) = -2; + PRVM_G_FLOAT(OFS_RETURN) = -2; return; } if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet))) - G_FLOAT(OFS_RETURN) = -1; + PRVM_G_FLOAT(OFS_RETURN) = -1; else - G_FLOAT(OFS_RETURN) = handle; + PRVM_G_FLOAT(OFS_RETURN) = handle; } /* @@ -3127,8 +3381,8 @@ void PF_search_end(void) { int handle; - handle = G_FLOAT(OFS_PARM0); - + handle = PRVM_G_FLOAT(OFS_PARM0); + if(handle < 0 || handle >= MAX_SEARCHES) { Con_Printf("PF_search_end: invalid handle %i\n", handle); @@ -3155,7 +3409,7 @@ void PF_search_getsize(void) { int handle; - handle = G_FLOAT(OFS_PARM0); + handle = PRVM_G_FLOAT(OFS_PARM0); if(handle < 0 || handle >= MAX_SEARCHES) { @@ -3167,8 +3421,8 @@ void PF_search_getsize(void) Con_Printf("PF_search_getsize: no such handle %i\n", handle); return; } - - G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames; + + PRVM_G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames; } /* @@ -3183,8 +3437,8 @@ void PF_search_getfilename(void) int handle, filenum; char *tmp; - handle = G_FLOAT(OFS_PARM0); - filenum = G_FLOAT(OFS_PARM1); + handle = PRVM_G_FLOAT(OFS_PARM0); + filenum = PRVM_G_FLOAT(OFS_PARM1); if(handle < 0 || handle >= MAX_SEARCHES) { @@ -3201,29 +3455,81 @@ void PF_search_getfilename(void) Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum); return; } - + tmp = PR_GetTempString(); strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]); - G_INT(OFS_RETURN) = PR_SetString(tmp); + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); } void PF_cvar_string (void) { - char *str; + const char *str; cvar_t *var; char *tmp; - str = G_STRING(OFS_PARM0); + str = PRVM_G_STRING(OFS_PARM0); var = Cvar_FindVar (str); + if (var) + { + tmp = PR_GetTempString(); + strcpy(tmp, var->string); + } + else + tmp = NULL; + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); +} - tmp = PR_GetTempString(); - strcpy(tmp, var->string); - - G_INT(OFS_RETURN) = PR_SetString(tmp); +//void(entity clent) dropclient (DP_SV_DROPCLIENT) +void PF_dropclient (void) +{ + int clientnum; + client_t *oldhostclient; + clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1; + if (clientnum < 0 || clientnum >= svs.maxclients) + PF_WARNING("dropclient: not a client\n"); + if (!svs.clients[clientnum].active) + PF_WARNING("dropclient: that client slot is not connected\n"); + oldhostclient = host_client; + host_client = svs.clients + clientnum; + SV_DropClient(false); + host_client = oldhostclient; } +//entity() spawnclient (DP_SV_BOTCLIENT) +void PF_spawnclient (void) +{ + int i; + prvm_edict_t *ed; + pr_xfunction->builtinsprofile += 2; + ed = prog->edicts; + for (i = 0;i < svs.maxclients;i++) + { + if (!svs.clients[i].active) + { + pr_xfunction->builtinsprofile += 100; + SV_ConnectClient (i, NULL); + ed = PRVM_EDICT_NUM(i + 1); + break; + } + } + RETURN_EDICT(ed); +} +//float(entity clent) clienttype (DP_SV_BOTCLIENT) +void PF_clienttype (void) +{ + int clientnum; + clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1; + if (clientnum < 0 || clientnum >= svs.maxclients) + PRVM_G_FLOAT(OFS_RETURN) = 3; + else if (!svs.clients[clientnum].active) + PRVM_G_FLOAT(OFS_RETURN) = 0; + else if (svs.clients[clientnum].netconnection) + PRVM_G_FLOAT(OFS_RETURN) = 1; + else + PRVM_G_FLOAT(OFS_RETURN) = 2; +} builtin_t pr_builtin[] = { @@ -3268,7 +3574,7 @@ PF_floor, // #37 float(float v) floor PF_ceil, // #38 float(float v) ceil NULL, // #39 PF_checkbottom, // #40 float(entity e) checkbottom -PF_pointcontents , // #41 float(vector v) pointcontents +PF_pointcontents, // #41 float(vector v) pointcontents NULL, // #42 PF_fabs, // #43 float(float f) fabs PF_aim, // #44 vector(entity e, float speed) aim @@ -3378,7 +3684,7 @@ PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUI PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) -PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) 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) @@ -3395,13 +3701,23 @@ PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_P PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) -PF_search_begin, // #444 -PF_search_end, // #445 -PF_search_getsize, // #446 -PF_search_getfilename, // #447 +PF_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH) +PF_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH) +PF_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH) +PF_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH) PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) -NULL, // #449 -a a a a a // #450-499 (LordHavoc) +PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS) +PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) +PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO) +PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO) +PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT) +PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT) +PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT) +NULL, // #456 +NULL, // #457 +NULL, // #458 +NULL, // #459 +a a a a // #460-499 (LordHavoc) }; builtin_t *pr_builtins = pr_builtin; @@ -3409,14 +3725,16 @@ int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); void PR_Cmd_Init(void) { - pr_strings_mempool = Mem_AllocPool("pr_stringszone"); PR_Files_Init(); PR_Search_Init(); } +void PR_Cmd_Shutdown(void) +{ +} + void PR_Cmd_Reset(void) { - Mem_EmptyPool(pr_strings_mempool); PR_Search_Reset(); PR_Files_CloseAll(); }