X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=pr_cmds.c;h=23edb617d31057d66a177123746b7abf3b8fcbc1;hp=b432657bd800c37fe2671cba0539dd7038b846b7;hb=491556ae8663fb14efed17c3a2b50770f7760afc;hpb=9912a20422cea9a76f89ad056033368c5c97c687 diff --git a/pr_cmds.c b/pr_cmds.c index b432657b..23edb617 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -23,13 +23,23 @@ 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; - -#define MAX_VARSTRING 4096 +// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print +#define STRINGTEMP_BUFFERS 16 +#define STRINGTEMP_LENGTH 4096 +static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH]; +static int pr_string_tempindex = 0; -char pr_varstring_temp[MAX_VARSTRING]; +static char *PR_GetTempString(void) +{ + char *s; + s = pr_string_temp[pr_string_tempindex]; + pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS; + return s; +} -#define RETURN_EDICT(e) (((int *)pr_globals)[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) /* @@ -41,71 +51,105 @@ char pr_varstring_temp[MAX_VARSTRING]; */ -char *PF_VarString (int first) +void PF_VarString(int first, char *out, int outlength) { int i; const char *s; - char *out, *outend; + char *outend; - out = pr_varstring_temp; - outend = pr_varstring_temp + sizeof(pr_varstring_temp) - 1; + 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++; } *out++ = 0; - return pr_varstring_temp; } char *ENGINE_EXTENSIONS = +"DP_BUTTONCHAT " +"DP_BUTTONUSE " "DP_CL_LOADSKY " -"DP_EF_NODRAW " +"DP_CON_SET " +"DP_CON_SETA " +"DP_CON_STARTMAP " "DP_EF_ADDITIVE " "DP_EF_BLUE " -"DP_EF_RED " -"DP_EF_FULLBRIGHT " "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_LOWPRECISION " "DP_ENT_GLOW " +"DP_ENT_LOWPRECISION " "DP_ENT_SCALE " "DP_ENT_VIEWMODEL " +"DP_GFX_EXTERNALTEXTURES " "DP_GFX_FOG " +"DP_GFX_QUAKE3MODELTAGS " +"DP_GFX_SKINFILES " "DP_GFX_SKYBOX " "DP_HALFLIFE_MAP " +"DP_HALFLIFE_MAP_CVAR " +"DP_HALFLIFE_SPRITE " "DP_INPUTBUTTONS " +"DP_LITSPRITES " +"DP_LITSUPPORT " "DP_MONSTERWALK " "DP_MOVETYPEBOUNCEMISSILE " "DP_MOVETYPEFOLLOW " "DP_QC_CHANGEPITCH " "DP_QC_COPYENTITY " +"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 " "DP_QC_TRACETOSS " +"DP_QC_TRACE_MOVETYPE_HITMODEL " +"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 " @@ -126,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; @@ -161,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)); } /* @@ -176,15 +224,15 @@ error(value) */ void PF_error (void) { - char *s; - edict_t *ed; + prvm_edict_t *ed; + char string[STRINGTEMP_LENGTH]; - s = PF_VarString(0); - Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + PF_VarString(0, string, sizeof(string)); + 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); - Host_Error ("Program error"); + PF_ERROR("Program error"); } /* @@ -199,13 +247,13 @@ objerror(value) */ void PF_objerror (void) { - char *s; - edict_t *ed; + prvm_edict_t *ed; + char string[STRINGTEMP_LENGTH]; - s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + PF_VarString(0, string, sizeof(string)); + 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); } @@ -220,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); } /* @@ -233,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); } /* @@ -248,28 +296,32 @@ setorigin (entity, origin) */ void PF_setorigin (void) { - edict_t *e; + prvm_edict_t *e; float *org; - e = G_EDICT(OFS_PARM0); - org = G_VECTOR(OFS_PARM1); - VectorCopy (org, e->v->origin); + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) + PF_WARNING("setorigin: can not modify world entity\n"); + if (e->priv.server->free) + PF_WARNING("setorigin: can not modify free entity\n"); + 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; for (i=0 ; i<3 ; i++) if (min[i] > max[i]) - Host_Error ("backwards mins/maxs"); + 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); } @@ -286,12 +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); - min = G_VECTOR(OFS_PARM1); - max = G_VECTOR(OFS_PARM2); + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) + PF_WARNING("setsize: can not modify world entity\n"); + if (e->priv.server->free) + PF_WARNING("setsize: can not modify free entity\n"); + min = PRVM_G_VECTOR(OFS_PARM1); + max = PRVM_G_VECTOR(OFS_PARM2); SetMinMaxSize (e, min, max, false); } @@ -303,32 +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); - 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) - Host_Error ("no precache: %s\n", m); + e = PRVM_G_EDICT(OFS_PARM0); + if (e == prog->edicts) + PF_WARNING("setmodel: can not modify world entity\n"); + if (e->priv.server->free) + PF_WARNING("setmodel: can not modify free entity\n"); + i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1); + e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]); + e->fields.server->modelindex = i; - - e->v->model = PR_SetString(*check); - e->v->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); } @@ -344,10 +399,9 @@ bprint(value) */ void PF_bprint (void) { - char *s; - - s = PF_VarString(0); - SV_BroadcastPrintf ("%s", s); + char string[STRINGTEMP_LENGTH]; + PF_VarString(0, string, sizeof(string)); + SV_BroadcastPrint(string); } /* @@ -361,23 +415,22 @@ sprint(clientent, value) */ void PF_sprint (void) { - char *s; client_t *client; int entnum; + char string[STRINGTEMP_LENGTH]; - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) + 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]; - - MSG_WriteChar (&client->message,svc_print); - MSG_WriteString (&client->message, s ); + client = svs.clients + entnum-1; + PF_VarString(1, string, sizeof(string)); + MSG_WriteChar(&client->message,svc_print); + MSG_WriteString(&client->message, string); } @@ -392,23 +445,22 @@ centerprint(clientent, value) */ void PF_centerprint (void) { - char *s; client_t *client; int entnum; + char string[STRINGTEMP_LENGTH]; - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) + 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]; - - MSG_WriteChar (&client->message,svc_centerprint); - MSG_WriteString (&client->message, s ); + client = svs.clients + entnum-1; + PF_VarString(1, string, sizeof(string)); + MSG_WriteChar(&client->message,svc_centerprint); + MSG_WriteString(&client->message, string); } @@ -425,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); @@ -440,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)); } /* @@ -455,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; } /* @@ -475,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; } @@ -499,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) { @@ -528,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); } /* @@ -549,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); } /* @@ -569,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); } @@ -585,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) @@ -618,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); @@ -648,26 +684,26 @@ 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) - Host_Error ("SV_StartSound: volume = %i", volume); + PF_WARNING("SV_StartSound: volume must be in range 0-1\n"); if (attenuation < 0 || attenuation > 4) - Host_Error ("SV_StartSound: attenuation = %f", attenuation); + PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n"); if (channel < 0 || channel > 7) - Host_Error ("SV_StartSound: channel = %i", channel); + PF_WARNING("SV_StartSound: channel must be in range 0-7\n"); SV_StartSound (entity, channel, sample, volume, attenuation); } @@ -681,7 +717,7 @@ break() */ void PF_break (void) { - Host_Error ("break statement"); + PF_ERROR("break: break statement\n"); } /* @@ -699,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 } @@ -743,60 +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); - ignore = G_EDICT(OFS_PARM1); + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + PF_WARNING("tracetoss: can not use world entity\n"); + 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); } @@ -816,21 +854,18 @@ void PF_checkpos (void) //============================================================================ +int checkpvsbytes; qbyte 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 - if (check < 1) - check = 1; - if (check > svs.maxclients) - check = svs.maxclients; - + check = bound(1, check, svs.maxclients); if (check == svs.maxclients) i = 1; else @@ -838,29 +873,25 @@ int PF_newcheckclient (int check) for ( ; ; i++) { + // count the cost pr_xfunction->builtinsprofile++; + // wrap around if (i == svs.maxclients+1) i = 1; - - ent = EDICT_NUM(i); - - if (i == check) - break; // didn't find anything else - - if (ent->e->free) - continue; - if (ent->v->health <= 0) + // look up the client's edict + 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->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET))) continue; - if ((int)ent->v->flags & FL_NOTARGET) - continue; - - // anything that is a client, or has a client as an enemy + // 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); - memcpy (checkpvs, sv.worldmodel->LeafPVS(sv.worldmodel, sv.worldmodel->PointInLeaf(sv.worldmodel, org)), (sv.worldmodel->numleafs+7)>>3 ); + 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)); return i; } @@ -883,9 +914,7 @@ name checkclient () int c_invis, c_notvis; void PF_checkclient (void) { - edict_t *ent, *self; - mleaf_t *leaf; - int l; + prvm_edict_t *ent, *self; vec3_t view; // find a new check if on a new frame @@ -896,26 +925,21 @@ 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); - leaf = sv.worldmodel->PointInLeaf(sv.worldmodel, view); - if (leaf) + 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)) { - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) - { - c_notvis++; - RETURN_EDICT(sv.edicts); - return; - } + c_notvis++; + RETURN_EDICT(prog->edicts); + return; } // might be able to see it @@ -938,16 +962,19 @@ stuffcmd (clientent, value) void PF_stuffcmd (void) { int entnum; - char *str; + const char *str; client_t *old; - entnum = G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) - Host_Error ("Parm 0 not a client"); - str = G_STRING(OFS_PARM1); + entnum = PRVM_G_EDICTNUM(OFS_PARM0); + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) + { + Con_Print("Can't stuffcmd to a non-client\n"); + return; + } + str = PRVM_G_STRING(OFS_PARM1); old = host_client; - host_client = &svs.clients[entnum-1]; + host_client = svs.clients + entnum-1; Host_ClientCommands ("%s", str); host_client = old; } @@ -956,17 +983,14 @@ void PF_stuffcmd (void) ================= PF_localcmd -Sends text over to the client's execution buffer +Sends text to server console localcmd (string) ================= */ void PF_localcmd (void) { - char *str; - - str = G_STRING(OFS_PARM0); - Cbuf_AddText (str); + Cbuf_AddText(PRVM_G_STRING(OFS_PARM0)); } /* @@ -978,11 +1002,7 @@ float cvar (string) */ void PF_cvar (void) { - char *str; - - str = G_STRING(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); + PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0)); } /* @@ -994,12 +1014,7 @@ float cvar (string) */ void PF_cvar_set (void) { - char *var, *val; - - var = G_STRING(OFS_PARM0); - val = G_STRING(OFS_PARM1); - - Cvar_Set (var, val); + Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1)); } /* @@ -1013,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); @@ -1058,61 +1092,54 @@ PF_dprint */ void PF_dprint (void) { - Con_DPrintf ("%s",PF_VarString(0)); -} - -// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print -#define STRINGTEMP_BUFFERS 16 -#define STRINGTEMP_LENGTH 128 -static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH]; -static int pr_string_tempindex = 0; - -static char *PR_GetTempString(void) -{ - char *s; - s = pr_string_temp[pr_string_tempindex]; - pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS; - return s; + char string[STRINGTEMP_LENGTH]; + if (developer.integer) + { + PF_VarString(0, string, sizeof(string)); + Con_Print(string); + } } void PF_ftos (void) { float v; char *s; - v = G_FLOAT(OFS_PARM0); + v = PRVM_G_FLOAT(OFS_PARM0); s = PR_GetTempString(); - // LordHavoc: ftos improvement - sprintf (s, "%g", v); - G_INT(OFS_RETURN) = PR_SetString(s); + if ((float)((int)v) == v) + sprintf(s, "%i", (int)v); + else + sprintf(s, "%f", v); + 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); @@ -1120,14 +1147,17 @@ 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) - Host_Error("remove: tried to remove world\n"); - if (NUM_FOR_EDICT(ed) <= svs.maxclients) - Host_Error("remove: tried to remove a client\n"); + ed = PRVM_G_EDICT(OFS_PARM0); + if (ed == prog->edicts) + PF_WARNING("remove: tried to remove world\n"); + 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->priv.server->free && developer.integer) + PF_WARNING("remove: tried to remove an entity that was already removed\n"); ED_Free (ed); } @@ -1137,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) @@ -1165,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 @@ -1174,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) { @@ -1193,7 +1223,7 @@ void PF_FindFloat (void) } } - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); } // chained search for strings in entity fields @@ -1202,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) @@ -1227,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; } @@ -1241,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] <= ' ') - Host_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) - Host_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; } - Host_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) - Host_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->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; } - Host_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); } @@ -1346,7 +1387,7 @@ void PF_traceoff (void) void PF_eprint (void) { - ED_PrintNum (G_EDICTNUM(OFS_PARM0)); + ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0)); } /* @@ -1358,21 +1399,25 @@ 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; - ent = PROG_TO_EDICT(pr_global_struct->self); - yaw = G_FLOAT(OFS_PARM0); - dist = G_FLOAT(OFS_PARM1); + // assume failure if it returns early + PRVM_G_FLOAT(OFS_RETURN) = 0; - if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) - { - 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->priv.server->free) + PF_WARNING("walkmove: can not modify free entity\n"); + yaw = PRVM_G_FLOAT(OFS_PARM0); + dist = PRVM_G_FLOAT(OFS_PARM1); + + if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) return; - } yaw = yaw*M_PI*2 / 360; @@ -1382,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; } /* @@ -1401,28 +1446,33 @@ void() droptofloor */ void PF_droptofloor (void) { - edict_t *ent; + prvm_edict_t *ent; vec3_t end; trace_t trace; - ent = PROG_TO_EDICT(pr_global_struct->self); + // assume failure if it returns early + PRVM_G_FLOAT(OFS_RETURN) = 0; + + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); + if (ent == prog->edicts) + PF_WARNING("droptofloor: can not modify world entity\n"); + 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) - G_FLOAT(OFS_RETURN) = 0; - else + 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; } } @@ -1436,45 +1486,47 @@ 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) return; - for (j=0, client = svs.clients ; jactive || client->spawned) + for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++) + { + if (client->active) { MSG_WriteChar (&client->message, svc_lightstyle); MSG_WriteChar (&client->message,style); MSG_WriteString (&client->message, val); } + } } 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)); } @@ -1485,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)); } /* @@ -1495,7 +1547,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = sv.worldmodel->PointContents(sv.worldmodel, G_VECTOR(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0)); } /* @@ -1508,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; @@ -1539,27 +1591,37 @@ 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; float dist, bestdist; float speed; - ent = G_EDICT(OFS_PARM0); - speed = G_FLOAT(OFS_PARM1); + // assume failure if it returns early + 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 = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + PF_WARNING("aim: can not use world entity\n"); + if (ent->priv.server->free) + PF_WARNING("aim: can not use free entity\n"); + 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; } @@ -1569,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); @@ -1597,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)); } } @@ -1619,13 +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); - current = ANGLEMOD(ent->v->angles[1]); - ideal = ent->v->ideal_yaw; - speed = ent->v->yaw_speed; + ent = PRVM_PROG_TO_EDICT(prog->globals.server->self); + if (ent == prog->edicts) + PF_WARNING("changeyaw: can not modify world entity\n"); + if (ent->priv.server->free) + PF_WARNING("changeyaw: can not modify free entity\n"); + current = ANGLEMOD(ent->fields.server->angles[1]); + ideal = ent->fields.server->ideal_yaw; + speed = ent->fields.server->yaw_speed; if (current == ideal) return; @@ -1651,7 +1717,7 @@ void PF_changeyaw (void) move = -speed; } - ent->v->angles[1] = ANGLEMOD (current + move); + ent->fields.server->angles[1] = ANGLEMOD (current + move); } /* @@ -1661,24 +1727,28 @@ PF_changepitch */ void PF_changepitch (void) { - edict_t *ent; + prvm_edict_t *ent; float ideal, current, move, speed; - eval_t *val; - - ent = G_EDICT(OFS_PARM0); - current = ANGLEMOD( ent->v->angles[0] ); - if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch))) + prvm_eval_t *val; + + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + PF_WARNING("changepitch: can not modify world entity\n"); + if (ent->priv.server->free) + PF_WARNING("changepitch: can not modify free entity\n"); + current = ANGLEMOD( ent->fields.server->angles[0] ); + if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch))) ideal = val->_float; else { - Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + 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 { - Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n"); return; } @@ -1706,7 +1776,7 @@ void PF_changepitch (void) move = -speed; } - ent->v->angles[0] = ANGLEMOD (current + move); + ent->fields.server->angles[0] = ANGLEMOD (current + move); } /* @@ -1726,19 +1796,19 @@ 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); - if (entnum < 1 || entnum > svs.maxclients) - Host_Error ("WriteDest: not a client"); + 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; case MSG_ALL: @@ -1748,7 +1818,7 @@ sizebuf_t *WriteDest (void) return &sv.signon; default: - Host_Error ("WriteDest: bad destination"); + Host_Error("WriteDest: bad destination"); break; } @@ -1757,77 +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); + ent = PRVM_G_EDICT(OFS_PARM0); + if (ent == prog->edicts) + PF_WARNING("makestatic: can not modify world entity\n"); + 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 @@ -1843,20 +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); - if (i < 1 || i > svs.maxclients) - Host_Error ("Entity is not a client"); + ent = PRVM_G_EDICT(OFS_PARM0); + i = PRVM_NUM_FOR_EDICT(ent); + if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active) + { + Con_Print("tried to setspawnparms on a non-client\n"); + return; + } // copy spawn parms out of the client_t - client = svs.clients + (i-1); - + 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]; } /* @@ -1866,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)); } /* @@ -1911,10 +1987,9 @@ 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)); } -void SV_LightPoint (vec3_t color, vec3_t p); /* ================= PF_GetLight @@ -1929,24 +2004,24 @@ getlight(vector) */ void PF_GetLight (void) { - vec3_t color; - vec_t* p; - p = G_VECTOR(OFS_PARM0); - SV_LightPoint (color, p); - VectorCopy (color, G_VECTOR(OFS_RETURN)); + vec3_t ambientcolor, diffusecolor, diffusenormal; + vec_t *p; + 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, 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; @@ -1954,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) - Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS); + Cvar_Get(name, value, 0); -// 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_RegisterVariable(variable); - G_FLOAT(OFS_RETURN) = 1; // success + PRVM_G_FLOAT(OFS_RETURN) = 1; // success } /* @@ -1986,18 +2051,21 @@ 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 - Host_Error("min: must supply at least 2 floats\n"); + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("min: must supply at least 2 floats\n"); + } } /* @@ -2013,18 +2081,21 @@ 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 - Host_Error("max: must supply at least 2 floats\n"); + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("max: must supply at least 2 floats\n"); + } } /* @@ -2038,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)); } /* @@ -2052,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)); } /* @@ -2066,9 +2137,17 @@ copyentity(src, dst) */ void PF_copyentity (void) { - edict_t *in, *out; - in = G_EDICT(OFS_PARM0); - out = G_EDICT(OFS_PARM1); + 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->priv.server->free) + PF_WARNING("copyentity: can not read free entity\n"); + out = PRVM_G_EDICT(OFS_PARM1); + if (out == prog->edicts) + PF_WARNING("copyentity: can not modify world entity\n"); + if (out->priv.server->free) + PF_WARNING("copyentity: can not modify free entity\n"); memcpy(out->v, in->v, progs->entityfields * 4); } @@ -2085,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) + 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; + client = svs.clients + entnum-1; + 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); + } } /* @@ -2117,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]) - Host_Error("effect: no model specified\n"); + 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) @@ -2168,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) @@ -2276,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) @@ -2286,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) @@ -2296,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) @@ -2306,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) @@ -2316,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) @@ -2346,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) @@ -2356,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) @@ -2366,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) @@ -2376,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) @@ -2386,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) @@ -2396,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) @@ -2406,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) @@ -2416,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) @@ -2426,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) @@ -2436,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) @@ -2448,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) @@ -2464,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) @@ -2480,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) @@ -2496,185 +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 (model->type != mod_brush) - return NULL; - if (surfnum < 0 || surfnum >= model->nummodelsurfaces) + if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; - return model->surfaces + surfnum + model->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->type != mod_brush) + 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->nummodelsurfaces;surfnum++) - { - surf = model->surfaces + surfnum + model->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 @@ -2700,25 +2809,26 @@ void PR_Files_CloseAll(void) //float(string s) stof = #81; // get numerical value from a string void PF_stof(void) { - char *s = PF_VarString(0); - G_FLOAT(OFS_RETURN) = atof(s); + char string[STRINGTEMP_LENGTH]; + PF_VarString(0, string, sizeof(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 @@ -2732,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); @@ -2775,8 +2880,8 @@ void PF_fclose(void) void PF_fgets(void) { int c, end; - static char string[MAX_VARSTRING]; - int filenum = G_FLOAT(OFS_PARM0); + static char string[STRINGTEMP_LENGTH]; + int filenum = PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= MAX_PRFILES) { Con_Printf("PF_fgets: invalid file handle %i\n", filenum); @@ -2793,27 +2898,31 @@ void PF_fgets(void) c = FS_Getc(pr_files[filenum]); if (c == '\r' || c == '\n' || c < 0) break; - if (end < MAX_VARSTRING - 1) + if (end < STRINGTEMP_LENGTH - 1) string[end++] = c; } 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 void PF_fputs(void) { int stringlength; - char *s = PF_VarString(1); - int filenum = G_FLOAT(OFS_PARM0); + char string[STRINGTEMP_LENGTH]; + int filenum = PRVM_G_FLOAT(OFS_PARM0); if (filenum < 0 || filenum >= MAX_PRFILES) { Con_Printf("PF_fputs: invalid file handle %i\n", filenum); @@ -2824,67 +2933,73 @@ void PF_fputs(void) Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum); return; } - if ((stringlength = strlen(s))) - FS_Write(pr_files[filenum], s, stringlength); + PF_VarString(1, string, sizeof(string)); + if ((stringlength = strlen(string))) + FS_Write(pr_files[filenum], string, stringlength); if (developer.integer) - Con_Printf("fputs: %s\n", s); + Con_Printf("fputs: %s\n", string); } //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 void PF_strcat(void) { - char *s = PF_VarString(0); - G_INT(OFS_RETURN) = PR_SetString(s); + char *s = PR_GetTempString(); + PF_VarString(0, s, STRINGTEMP_LENGTH); + 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, end; - char *s, string[MAX_VARSTRING]; - s = G_STRING(OFS_PARM0); - start = G_FLOAT(OFS_PARM1); - end = G_FLOAT(OFS_PARM2) + start; + int i, start, length; + 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 < MAX_VARSTRING - 1 && *s && i < end;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 void PF_stov(void) { - Math_atov(PF_VarString(0), G_VECTOR(OFS_RETURN)); + char string[STRINGTEMP_LENGTH]; + PF_VarString(0, string, sizeof(string)); + 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 @@ -2895,58 +3010,526 @@ void PF_clientcommand (void) int i; //find client for this entity - i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1); - if (i < 0 || i >= svs.maxclients) - Host_Error("PF_clientcommand: entity is not a client"); + i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1); + if (i < 0 || i >= svs.maxclients || !svs.clients[i].active) + { + 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); + host_client = svs.clients + i; + 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) +{ + 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 == prog->edicts) + PF_WARNING("setattachment: can not modify world entity\n"); + if (e->priv.server->free) + PF_WARNING("setattachment: can not modify free entity\n"); + + if (tagentity == NULL) + tagentity = prog->edicts; + + v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity); + if (v) + fields.server->edict = PRVM_EDICT_TO_PROG(tagentity); + + v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index); + if (v) + fields.server->_float = 0; + if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0]) + { + modelindex = (int)tagentity->fields.server->modelindex; + if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) + { + 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", 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; + } +} + + +///////////////////////////////////////// +// DP_QC_FS_SEARCH extension + +// qc fs search handling +#define MAX_SEARCHES 128 + +fssearch_t *pr_fssearchlist[MAX_SEARCHES]; + +void PR_Search_Init(void) +{ + memset(pr_fssearchlist,0,sizeof(pr_fssearchlist)); +} + +void PR_Search_Reset(void) +{ + int i; + // reset the fssearch list + for(i = 0; i < MAX_SEARCHES; i++) + if(pr_fssearchlist[i]) + FS_FreeSearch(pr_fssearchlist[i]); + memset(pr_fssearchlist,0,sizeof(pr_fssearchlist)); +} + +/* +========= +PF_search_begin + +float search_begin(string pattern, float caseinsensitive, float quiet) +========= +*/ +void PF_search_begin(void) +{ + int handle; + const char *pattern; + int caseinsens, quiet; + + pattern = PRVM_G_STRING(OFS_PARM0); + if (!pattern || pattern[0] <= ' ') + PF_ERROR("PF_search_begin: Bad string"); + + caseinsens = PRVM_G_FLOAT(OFS_PARM1); + quiet = PRVM_G_FLOAT(OFS_PARM2); + + for(handle = 0; handle < MAX_SEARCHES; handle++) + if(!pr_fssearchlist[handle]) + break; + + if(handle >= MAX_SEARCHES) + { + Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES); + PRVM_G_FLOAT(OFS_RETURN) = -2; + return; + } + + if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet))) + PRVM_G_FLOAT(OFS_RETURN) = -1; + else + PRVM_G_FLOAT(OFS_RETURN) = handle; +} + +/* +========= +VM_search_end + +void search_end(float handle) +========= +*/ +void PF_search_end(void) +{ + int handle; + + handle = PRVM_G_FLOAT(OFS_PARM0); + + if(handle < 0 || handle >= MAX_SEARCHES) + { + Con_Printf("PF_search_end: invalid handle %i\n", handle); + return; + } + if(pr_fssearchlist[handle] == NULL) + { + Con_Printf("PF_search_end: no such handle %i\n", handle); + return; + } + + FS_FreeSearch(pr_fssearchlist[handle]); + pr_fssearchlist[handle] = NULL; +} + +/* +========= +VM_search_getsize + +float search_getsize(float handle) +========= +*/ +void PF_search_getsize(void) +{ + int handle; + + handle = PRVM_G_FLOAT(OFS_PARM0); + + if(handle < 0 || handle >= MAX_SEARCHES) + { + Con_Printf("PF_search_getsize: invalid handle %i\n", handle); + return; + } + if(pr_fssearchlist[handle] == NULL) + { + Con_Printf("PF_search_getsize: no such handle %i\n", handle); + return; + } + + PRVM_G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames; +} + +/* +========= +VM_search_getfilename + +string search_getfilename(float handle, float num) +========= +*/ +void PF_search_getfilename(void) +{ + int handle, filenum; + char *tmp; + + handle = PRVM_G_FLOAT(OFS_PARM0); + filenum = PRVM_G_FLOAT(OFS_PARM1); + + if(handle < 0 || handle >= MAX_SEARCHES) + { + Con_Printf("PF_search_getfilename: invalid handle %i\n", handle); + return; + } + if(pr_fssearchlist[handle] == NULL) + { + Con_Printf("PF_search_getfilename: no such handle %i\n", handle); + return; + } + if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames) + { + Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum); + return; + } + + tmp = PR_GetTempString(); + strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]); + + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp); +} + +void PF_cvar_string (void) +{ + const char *str; + cvar_t *var; + char *tmp; + + 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); +} + +//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[] = { @@ -2991,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 @@ -3101,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) @@ -3117,14 +3700,24 @@ PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfac PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) -NULL, // #443 -NULL, // #444 -NULL, // #445 -NULL, // #446 -NULL, // #447 -NULL, // #448 -NULL, // #449 -a a a a a // #450-499 (LordHavoc) +PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) +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) +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; @@ -3132,13 +3725,17 @@ 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(); }