X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=pr_cmds.c;h=db3878afc135a5b6aae92ca441cefbf2fba60b35;hb=e3659f7d732ee4b564af752529bc6f0c3b489e8d;hp=7b1a17825dccd0327ea8fdcff8645ea446b4735a;hpb=c4ee1bbcc6b2f917465f07269ad09942bbf40849;p=xonotic%2Fdarkplaces.git diff --git a/pr_cmds.c b/pr_cmds.c index 7b1a1782..db3878af 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -20,9 +20,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default +cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default +cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"}; -#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) +// 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; + +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) (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) /* @@ -34,63 +51,132 @@ cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled au */ -char *PF_VarString (int first) +void PF_VarString(int first, char *out, int outlength) { - int i; - static char out[256]; - - out[0] = 0; - for (i=first ; is_name, s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + prvm_edict_t *ed; + char string[STRINGTEMP_LENGTH]; + + 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"); } /* @@ -160,21 +246,17 @@ objerror(value) */ void PF_objerror (void) { - char *s; - edict_t *ed; - - s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); - ED_Free (ed); + prvm_edict_t *ed; + char string[STRINGTEMP_LENGTH]; -// LordHavoc: bug fix - no longer kills server -// Host_Error ("Program error"); + 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); } - /* ============== PF_makevectors @@ -185,7 +267,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); } /* @@ -198,8 +280,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); } /* @@ -213,96 +295,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) { - /* - float *angles; - vec3_t rmin, rmax; - float bounds[2][3]; - float xvector[2], yvector[2]; - float a; - vec3_t base, transformed; - int i, j, k, l; - */ int i; - + for (i=0 ; i<3 ; i++) if (min[i] > max[i]) - PR_RunError ("backwards mins/maxs"); - - /* - rotate = false; // FIXME: implement rotation properly again + PF_ERROR("SetMinMaxSize: backwards mins/maxs\n"); - if (!rotate) - { - VectorCopy (min, rmin); - VectorCopy (max, rmax); - } - else - { - // find min / max for rotations - angles = e->v.angles; - - a = angles[1]/180 * M_PI; - - xvector[0] = cos(a); - xvector[1] = sin(a); - yvector[0] = -sin(a); - yvector[1] = cos(a); - - VectorCopy (min, bounds[0]); - VectorCopy (max, bounds[1]); - - rmin[0] = rmin[1] = rmin[2] = 9999; - rmax[0] = rmax[1] = rmax[2] = -9999; - - for (i=0 ; i<= 1 ; i++) - { - base[0] = bounds[i][0]; - for (j=0 ; j<= 1 ; j++) - { - base[1] = bounds[j][1]; - for (k=0 ; k<= 1 ; k++) - { - base[2] = bounds[k][2]; - - // transform the point - transformed[0] = xvector[0]*base[0] + yvector[0]*base[1]; - transformed[1] = xvector[1]*base[0] + yvector[1]*base[1]; - transformed[2] = base[2]; - - for (l=0 ; l<3 ; l++) - { - if (transformed[l] < rmin[l]) - rmin[l] = transformed[l]; - if (transformed[l] > rmax[l]) - rmax[l] = transformed[l]; - } - } - } - } - } - -// set derived values - VectorCopy (rmin, e->v.mins); - VectorCopy (rmax, e->v.maxs); - VectorSubtract (max, min, e->v.size); - */ - // 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); } @@ -319,12 +337,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); } @@ -336,45 +358,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) - PR_RunError ("no precache: %s\n", m); - - - e->v.model = m - pr_strings; - e->v.modelindex = i; //SV_ModelIndex (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; - mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true); + mod = sv.models[i]; if (mod) - /* - { // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here - vec3_t min, max; - if (mod->type == ALIASTYPE_MDL) - { - min[0] = min[1] = min[2] = -16; - max[0] = max[1] = max[2] = 16; - SetMinMaxSize (e, min, max, true); - } + { + if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer) + SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); else - SetMinMaxSize (e, mod->mins, mod->maxs, true); + SetMinMaxSize (e, quakemins, quakemaxs, true); } - */ - SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true); else SetMinMaxSize (e, vec3_origin, vec3_origin, true); } @@ -390,10 +398,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); } /* @@ -407,23 +414,22 @@ sprint(clientent, value) */ void PF_sprint (void) { - char *s; client_t *client; int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) + char string[STRINGTEMP_LENGTH]; + + entnum = PRVM_G_EDICTNUM(OFS_PARM0); + + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } - - client = &svs.clients[entnum-1]; - - 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); } @@ -438,23 +444,22 @@ centerprint(clientent, value) */ void PF_centerprint (void) { - char *s; client_t *client; int entnum; - - entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) + char string[STRINGTEMP_LENGTH]; + + entnum = PRVM_G_EDICTNUM(OFS_PARM0); + + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } - - client = &svs.clients[entnum-1]; - - 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); } @@ -470,12 +475,12 @@ void PF_normalize (void) float *value1; 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); - + if (new == 0) newvalue[0] = newvalue[1] = newvalue[2] = 0; else @@ -485,8 +490,8 @@ void PF_normalize (void) newvalue[1] = value1[1] * new; newvalue[2] = value1[2] * new; } - - VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); + + VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN)); } /* @@ -501,12 +506,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; } /* @@ -520,19 +525,19 @@ 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; } @@ -545,11 +550,9 @@ vector vectoangles(vector) */ void PF_vectoangles (void) { - float *value1; - float forward; - float yaw, pitch; - - value1 = G_VECTOR(OFS_PARM0); + double value1[3], forward, yaw, pitch; + + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), value1); if (value1[1] == 0 && value1[0] == 0) { @@ -574,14 +577,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); } /* @@ -595,11 +596,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); } /* @@ -614,11 +611,11 @@ void PF_particle (void) float *org, *dir; 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); } @@ -631,27 +628,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); - -// check to see if samp was properly precached - for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++) - if (!strcmp(*check,samp)) - break; + pos = PRVM_G_VECTOR (OFS_PARM0); + samp = PRVM_G_STRING(OFS_PARM1); + vol = PRVM_G_FLOAT(OFS_PARM2); + attenuation = PRVM_G_FLOAT(OFS_PARM3); - if (!*check) - { - Con_Printf ("no precache: %s\n", samp); +// check to see if samp was properly precached + soundnum = SV_SoundIndex(samp, 1); + if (!soundnum) return; - } large = false; if (soundnum >= 256) @@ -664,8 +654,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); @@ -694,26 +683,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); } @@ -727,9 +716,7 @@ break() */ void PF_break (void) { -// Con_Printf ("break statement\n"); -// *(int *)-4 = 0; // dump to debugger - PR_RunError ("break statement"); + PF_ERROR("break: break statement\n"); } /* @@ -747,28 +734,30 @@ void PF_traceline (void) { float *v1, *v2; trace_t trace; - int nomonsters; - edict_t *ent; - - 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 ? 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; + int move; + prvm_edict_t *ent; + + pr_xfunction->builtinsprofile += 30; + + 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 } @@ -789,56 +778,62 @@ void PF_tracebox (void) { float *v1, *v2, *m1, *m2; trace_t trace; - int nomonsters; - edict_t *ent; - - 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; + int move; + prvm_edict_t *ent; + + pr_xfunction->builtinsprofile += 30; + + 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; - ent = G_EDICT(OFS_PARM0); - ignore = G_EDICT(OFS_PARM1); + pr_xfunction->builtinsprofile += 600; + + 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); } @@ -858,23 +853,18 @@ void PF_checkpos (void) //============================================================================ +int checkpvsbytes; qbyte checkpvs[MAX_MAP_LEAFS/8]; int PF_newcheckclient (int check) { int i; - qbyte *pvs; - edict_t *ent; - mleaf_t *leaf; + 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 @@ -882,30 +872,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->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); - leaf = Mod_PointInLeaf (org, sv.worldmodel); - pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (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; } @@ -928,40 +913,36 @@ 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 + + // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { sv.lastcheck = PF_newcheckclient (sv.lastcheck); sv.lastchecktime = sv.time; } -// return check if it might be visible - ent = EDICT_NUM(sv.lastcheck); - if (ent->free || ent->v.health <= 0) + // return check if it might be visible + 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 = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) + // if current entity can't possibly see the check entity, return 0 + self = PRVM_PROG_TO_EDICT(prog->globals.server->self); + VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view); + if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view)) { -c_notvis++; - RETURN_EDICT(sv.edicts); + c_notvis++; + RETURN_EDICT(prog->edicts); return; } -// might be able to see it -c_invis++; + // might be able to see it + c_invis++; RETURN_EDICT(ent); } @@ -980,16 +961,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) - PR_RunError ("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; } @@ -998,17 +982,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)); } /* @@ -1020,11 +1001,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)); } /* @@ -1036,12 +1013,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)); } /* @@ -1055,31 +1027,57 @@ findradius (origin, radius) */ void PF_findradius (void) { - edict_t *ent, *chain; - float rad; - float *org; - vec3_t eorg; - int i, j; - - chain = (edict_t *)sv.edicts; - - org = G_VECTOR(OFS_PARM0); - rad = G_FLOAT(OFS_PARM1); - - ent = NEXT_EDICT(sv.edicts); - for (i=1 ; iedicts; + + VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org); + radius = PRVM_G_FLOAT(OFS_PARM1); + radius2 = radius * radius; + + mins[0] = org[0] - (radius + 1); + mins[1] = org[1] - (radius + 1); + mins[2] = org[2] - (radius + 1); + maxs[0] = org[0] + (radius + 1); + maxs[1] = org[1] + (radius + 1); + maxs[2] = org[2] + (radius + 1); + numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts); + if (numtouchedicts > MAX_EDICTS) { - if (ent->free) - continue; - if (ent->v.solid == SOLID_NOT) - continue; - for (j=0 ; j<3 ; j++) - eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5); - if (Length(eorg) > rad) + // 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++; + // 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); @@ -1093,80 +1091,72 @@ 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(); - /* - if (v == (int)v) - sprintf (s, "%d",(int)v); + if ((float)((int)v) == v) + sprintf(s, "%i", (int)v); else - sprintf (s, "%5.1f",v); - */ - // LordHavoc: ftos improvement - sprintf (s, "%g", v); - G_INT(OFS_RETURN) = s - pr_strings; + 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) = s - pr_strings; + 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) = s - pr_strings; + 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); } void PF_Remove (void) { - edict_t *ed; - - ed = G_EDICT(OFS_PARM0); - if (ed == sv.edicts) - PR_RunError("remove: tried to remove world\n"); - if (NUM_FOR_EDICT(ed) <= svs.maxclients) - PR_RunError("remove: tried to remove a client\n"); + prvm_edict_t *ed; + pr_xfunction->builtinsprofile += 20; + + 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); } @@ -1176,22 +1166,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++) { - ed = EDICT_NUM(e); - if (ed->free) + pr_xfunction->builtinsprofile++; + ed = PRVM_EDICT_NUM(e); + if (ed->priv.server->free) continue; t = E_STRING(ed,f); if (!t) @@ -1203,25 +1194,26 @@ void PF_Find (void) } } - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); } // LordHavoc: added this for searching float, int, and entity reference fields void PF_FindFloat (void) { - int e; + 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); - - for (e++ ; e < sv.num_edicts ; e++) + e = PRVM_G_EDICTNUM(OFS_PARM0); + f = PRVM_G_INT(OFS_PARM1); + s = PRVM_G_FLOAT(OFS_PARM2); + + for (e++ ; e < prog->num_edicts ; e++) { - ed = EDICT_NUM(e); - if (ed->free) + pr_xfunction->builtinsprofile++; + ed = PRVM_EDICT_NUM(e); + if (ed->priv.server->free) continue; if (E_FLOAT(ed,f) == s) { @@ -1230,32 +1222,33 @@ void PF_FindFloat (void) } } - RETURN_EDICT(sv.edicts); + RETURN_EDICT(prog->edicts); } // chained search for strings in entity fields // entity(.string field, string match) findchain = #402; void PF_findchain (void) { - int i; + 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)) { - if (ent->free) + pr_xfunction->builtinsprofile++; + if (ent->priv.server->free) continue; t = E_STRING(ent,f); if (!t) @@ -1263,7 +1256,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; } @@ -1274,93 +1267,105 @@ void PF_findchain (void) // entity(.string field, float match) findchainfloat = #403; void PF_findchainfloat (void) { - int i; + 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); - - ent = NEXT_EDICT(sv.edicts); - for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + f = PRVM_G_INT(OFS_PARM0); + s = PRVM_G_FLOAT(OFS_PARM1); + + ent = PRVM_NEXT_EDICT(prog->edicts); + for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent)) { - if (ent->free) + pr_xfunction->builtinsprofile++; + 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] <= ' ') - PR_RunError ("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); -} + int e; + int f; + int s; + prvm_edict_t *ed; -void PF_precache_sound (void) -{ - char *s; - int i; - - if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); + e = PRVM_G_EDICTNUM(OFS_PARM0); + f = PRVM_G_INT(OFS_PARM1); + s = (int)PRVM_G_FLOAT(OFS_PARM2); - s = G_STRING(OFS_PARM0); - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); - - 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; } - PR_RunError ("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; - - if (sv.state != ss_loading) - PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions"); + int f; + int s; + prvm_edict_t *ent, *chain; - s = G_STRING(OFS_PARM0); - if (sv.worldmodel->ishlbsp && ((!s) || (!s[0]))) - return; - G_INT(OFS_RETURN) = G_INT(OFS_PARM0); - PR_CheckEmptyString (s); + chain = (prvm_edict_t *)prog->edicts; - 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; } - PR_RunError ("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); } @@ -1381,7 +1386,7 @@ void PF_traceoff (void) void PF_eprint (void) { - ED_PrintNum (G_EDICTNUM(OFS_PARM0)); + ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0)); } /* @@ -1393,38 +1398,42 @@ float(float yaw, float dist) walkmove */ void PF_walkmove (void) { - edict_t *ent; + prvm_edict_t *ent; float yaw, dist; vec3_t move; - dfunction_t *oldf; + mfunction_t *oldf; int oldself; - - ent = PROG_TO_EDICT(pr_global_struct->self); - yaw = G_FLOAT(OFS_PARM0); - dist = G_FLOAT(OFS_PARM1); - - if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) ) - { - G_FLOAT(OFS_RETURN) = 0; + + // 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("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; - + move[0] = cos(yaw)*dist; move[1] = sin(yaw)*dist; move[2] = 0; // save program state, because SV_movestep may call other progs oldf = pr_xfunction; - oldself = pr_global_struct->self; - - G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true); - - + oldself = prog->globals.server->self; + + 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; } /* @@ -1436,26 +1445,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); - VectorCopy (ent->v.origin, end); + // 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->fields.server->origin, end); end[2] -= 256; - - trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent); - if (trace.fraction == 1 || trace.allsolid) - G_FLOAT(OFS_RETURN) = 0; - else + trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent); + + if (trace.fraction != 1) { - VectorCopy (trace.endpos, ent->v.origin); + VectorCopy (trace.endpos, ent->fields.server->origin); SV_LinkEdict (ent, false); - ent->v.flags = (int)ent->v.flags | FL_ONGROUND; - ent->v.groundentity = EDICT_TO_PROG(trace.ent); - G_FLOAT(OFS_RETURN) = 1; + ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND; + ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + // if support is destroyed, keep suspended (gross hack for floating items in various maps) + ent->priv.server->suspendedinairflag = true; } } @@ -1469,45 +1485,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)); } @@ -1518,7 +1536,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)); } /* @@ -1528,7 +1546,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = SV_PointContents (G_VECTOR(OFS_PARM0)); + PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0)); } /* @@ -1541,19 +1559,20 @@ entity nextent(entity) void PF_nextent (void) { int i; - edict_t *ent; - - i = G_EDICTNUM(OFS_PARM0); + prvm_edict_t *ent; + + 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->free) + ent = PRVM_EDICT_NUM(i); + if (!ent->priv.server->free) { RETURN_EDICT(ent); return; @@ -1571,27 +1590,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); - VectorCopy (ent->v.origin, start); + // 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->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 && tr.ent->v.takedamage == DAMAGE_AIM - && (!teamplay.integer || ent->v.team <=0 || ent->v.team != 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; } @@ -1600,22 +1629,23 @@ void PF_aim (void) VectorCopy (dir, bestdir); 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) ) { - if (check->v.takedamage != DAMAGE_AIM) + pr_xfunction->builtinsprofile++; + 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); @@ -1625,19 +1655,19 @@ void PF_aim (void) bestent = check; } } - + 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)); } } @@ -1650,14 +1680,18 @@ 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; move = ideal - current; @@ -1681,8 +1715,8 @@ void PF_changeyaw (void) if (move < -speed) move = -speed; } - - ent->v.angles[1] = ANGLEMOD (current + move); + + ent->fields.server->angles[1] = ANGLEMOD (current + move); } /* @@ -1692,27 +1726,31 @@ 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 { - PR_RunError ("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 { - PR_RunError ("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 (current == ideal) return; move = ideal - current; @@ -1736,8 +1774,8 @@ void PF_changepitch (void) if (move < -speed) move = -speed; } - - ent->v.angles[0] = ANGLEMOD (current + move); + + ent->fields.server->angles[0] = ANGLEMOD (current + move); } /* @@ -1757,110 +1795,112 @@ 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) - PR_RunError ("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: return &sv.reliable_datagram; - + case MSG_INIT: return &sv.signon; default: - PR_RunError ("WriteDest: bad destination"); + Host_Error("WriteDest: bad destination"); break; } - + return NULL; } 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)); } //============================================================================= -int SV_ModelIndex (char *name); - void PF_makestatic (void) { - edict_t *ent; - int i, large; - - ent = G_EDICT(OFS_PARM0); + prvm_edict_t *ent; + int i, large; + + 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 @@ -1876,20 +1916,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) - PR_RunError ("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]; } /* @@ -1899,30 +1941,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)); } /* @@ -1944,10 +1986,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 @@ -1962,50 +2003,38 @@ 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_PARM1); - value = G_STRING(OFS_PARM2); - 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; - + // 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) - PR_RunError ("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); - -// link the variable in - variable->next = cvar_vars; - cvar_vars = variable; - G_FLOAT(OFS_RETURN) = 1; // success + PRVM_G_FLOAT(OFS_RETURN) = 1; // success } /* @@ -2021,18 +2050,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 - PR_RunError("min: must supply at least 2 floats\n"); + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("min: must supply at least 2 floats\n"); + } } /* @@ -2048,18 +2080,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 - PR_RunError("max: must supply at least 2 floats\n"); + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("max: must supply at least 2 floats\n"); + } } /* @@ -2073,7 +2108,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)); } /* @@ -2087,7 +2122,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)); } /* @@ -2101,10 +2136,18 @@ copyentity(src, dst) */ void PF_copyentity (void) { - edict_t *in, *out; - in = G_EDICT(OFS_PARM0); - out = G_EDICT(OFS_PARM1); - memcpy(out, in, pr_edict_size); + 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); } /* @@ -2118,25 +2161,35 @@ setcolor(clientent, value) */ void PF_setcolor (void) { - client_t *client; - int entnum, i; + client_t *client; + int entnum, i; + 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]; + 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->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); + } } /* @@ -2148,50 +2201,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]) - PR_RunError("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) @@ -2199,107 +2256,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) @@ -2307,9 +2364,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) @@ -2317,9 +2374,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) @@ -2327,9 +2384,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) @@ -2337,9 +2394,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) @@ -2347,29 +2404,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) @@ -2377,9 +2434,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) @@ -2387,9 +2444,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) @@ -2397,9 +2454,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) @@ -2407,9 +2464,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) @@ -2417,9 +2474,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) @@ -2427,9 +2484,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) @@ -2437,9 +2494,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) @@ -2447,9 +2504,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) @@ -2457,9 +2514,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) @@ -2467,11 +2524,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) @@ -2479,15 +2537,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) @@ -2495,15 +2553,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) @@ -2511,15 +2569,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) @@ -2527,185 +2585,1156 @@ 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); } -void PF_Fixme (void) +static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out) { - PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin) + int i, j, k; + float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist; + const int *e; + bestdist = 1000000000; + VectorCopy(p, out); + for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3) + { + // 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++) + { + 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(prvm_edict_t *ed, int surfacenum) +{ + int modelindex; + model_t *model; + if (!ed || ed->priv.server->free) + return NULL; + modelindex = ed->fields.server->modelindex; + if (modelindex < 1 || modelindex >= MAX_MODELS) + return NULL; + model = sv.models[modelindex]; + if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) + return NULL; + return model->data_surfaces + surfacenum + model->firstmodelsurface; +} -builtin_t pr_builtin[] = +//PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; +void PF_getsurfacenumpoints(void) { -PF_Fixme, -PF_makevectors, // void(entity e) makevectors = #1; -PF_setorigin, // void(entity e, vector o) setorigin = #2; -PF_setmodel, // void(entity e, string m) setmodel = #3; -PF_setsize, // void(entity e, vector min, vector max) setsize = #4; -PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5; -PF_break, // void() break = #6; -PF_random, // float() random = #7; -PF_sound, // void(entity e, float chan, string samp) sound = #8; -PF_normalize, // vector(vector v) normalize = #9; -PF_error, // void(string e) error = #10; -PF_objerror, // void(string e) objerror = #11; -PF_vlen, // float(vector v) vlen = #12; -PF_vectoyaw, // float(vector v) vectoyaw = #13; -PF_Spawn, // entity() spawn = #14; -PF_Remove, // void(entity e) remove = #15; -PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16; -PF_checkclient, // entity() clientlist = #17; -PF_Find, // entity(entity start, .string fld, string match) find = #18; -PF_precache_sound, // void(string s) precache_sound = #19; -PF_precache_model, // void(string s) precache_model = #20; -PF_stuffcmd, // void(entity client, string s)stuffcmd = #21; -PF_findradius, // entity(vector org, float rad) findradius = #22; -PF_bprint, // void(string s) bprint = #23; -PF_sprint, // void(entity client, string s) sprint = #24; -PF_dprint, // void(string s) dprint = #25; -PF_ftos, // void(string s) ftos = #26; -PF_vtos, // void(string s) vtos = #27; -PF_coredump, -PF_traceon, -PF_traceoff, -PF_eprint, // void(entity e) debug print an entire entity -PF_walkmove, // float(float yaw, float dist) walkmove -PF_Fixme, // float(float yaw, float dist) walkmove -PF_droptofloor, -PF_lightstyle, -PF_rint, -PF_floor, -PF_ceil, -PF_Fixme, -PF_checkbottom, -PF_pointcontents, -PF_Fixme, -PF_fabs, -PF_aim, -PF_cvar, -PF_localcmd, -PF_nextent, -PF_particle, -PF_changeyaw, -PF_Fixme, -PF_vectoangles, - -PF_WriteByte, -PF_WriteChar, -PF_WriteShort, -PF_WriteLong, -PF_WriteCoord, -PF_WriteAngle, -PF_WriteString, -PF_WriteEntity, - -PF_sin, -PF_cos, -PF_sqrt, -PF_changepitch, -PF_TraceToss, -PF_etos, -PF_Fixme, - -SV_MoveToGoal, -PF_precache_file, -PF_makestatic, - -PF_changelevel, -PF_Fixme, - -PF_cvar_set, -PF_centerprint, - -PF_ambientsound, - -PF_precache_model, -PF_precache_sound, // precache_sound2 is different only for qcc -PF_precache_file, - -PF_setspawnparms, - -PF_Fixme, // #79 LordHavoc: dunno who owns 79-89, so these are just padding -PF_Fixme, // #80 -PF_Fixme, // #81 -PF_Fixme, // #82 -PF_Fixme, // #83 -PF_Fixme, // #84 -PF_Fixme, // #85 -PF_Fixme, // #86 -PF_Fixme, // #87 -PF_Fixme, // #88 -PF_Fixme, // #89 - -PF_tracebox, // #90 LordHavoc builtin range (9x) -PF_randomvec, // #91 -PF_GetLight, // #92 -PF_registercvar, // #93 -PF_min, // #94 -PF_max, // #95 -PF_bound, // #96 -PF_pow, // #97 -PF_FindFloat, // #98 -PF_checkextension, // #99 -#define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, -#define aa a a a a a a a a a a -aa // #200 -aa // #300 -aa // #400 -PF_copyentity, // #400 LordHavoc: builtin range (4xx) -PF_setcolor, // #401 -PF_findchain, // #402 -PF_findchainfloat, // #403 -PF_effect, // #404 -PF_te_blood, // #405 -PF_te_bloodshower, // #406 -PF_te_explosionrgb, // #407 -PF_te_particlecube, // #408 -PF_te_particlerain, // #409 -PF_te_particlesnow, // #410 -PF_te_spark, // #411 -PF_te_gunshotquad, // #412 -PF_te_spikequad, // #413 -PF_te_superspikequad, // #414 -PF_te_explosionquad, // #415 -PF_te_smallflash, // #416 -PF_te_customflash, // #417 -PF_te_gunshot, // #418 -PF_te_spike, // #419 -PF_te_superspike, // #420 -PF_te_explosion, // #421 -PF_te_tarexplosion, // #422 -PF_te_wizspike, // #423 -PF_te_knightspike, // #424 -PF_te_lavasplash, // #425 -PF_te_teleport, // #426 -PF_te_explosion2, // #427 -PF_te_lightning1, // #428 -PF_te_lightning2, // #429 -PF_te_lightning3, // #430 -PF_te_beam, // #431 -PF_vectorvectors, // #432 -PF_te_plasmaburn, // #433 -}; + msurface_t *surface; + // return 0 if no such surface + if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) + { + PRVM_G_FLOAT(OFS_RETURN) = 0; + return; + } + + // 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) +{ + prvm_edict_t *ed; + msurface_t *surface; + int pointnum; + VectorClear(PRVM_G_VECTOR(OFS_RETURN)); + ed = PRVM_G_EDICT(OFS_PARM0); + if (!ed || ed->priv.server->free) + return; + if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) + return; + // 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(&(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 *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 + // 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 *surface; + PRVM_G_INT(OFS_RETURN) = 0; + if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1)))) + return; + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name); +} +//PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; +void PF_getsurfacenearpoint(void) +{ + int surfacenum, best, modelindex; + vec3_t clipped, p; + vec_t dist, bestdist; + prvm_edict_t *ed; + model_t *model; + msurface_t *surface; + vec_t *point; + PRVM_G_FLOAT(OFS_RETURN) = -1; + ed = PRVM_G_EDICT(OFS_PARM0); + point = PRVM_G_VECTOR(OFS_PARM1); + + if (!ed || ed->priv.server->free) + return; + modelindex = ed->fields.server->modelindex; + if (modelindex < 1 || modelindex >= MAX_MODELS) + return; + model = sv.models[modelindex]; + if (!model->num_surfaces) + return; + + // FIXME: implement rotation/scaling + VectorSubtract(point, ed->fields.server->origin, p); + best = -1; + bestdist = 1000000000; + 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) + { + // it is, check the nearest point on the actual geometry + clippointtosurface(surface, p, clipped); + VectorSubtract(clipped, p, clipped); + dist += VectorLength2(clipped); + if (dist < bestdist) + { + // that's closer too, store it as the best match + best = surfacenum; + bestdist = dist; + } + } + } + PRVM_G_FLOAT(OFS_RETURN) = best; +} +//PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; +void PF_getsurfaceclippedpoint(void) +{ + prvm_edict_t *ed; + msurface_t *surface; + vec3_t p, out; + VectorClear(PRVM_G_VECTOR(OFS_RETURN)); + ed = PRVM_G_EDICT(OFS_PARM0); + if (!ed || ed->priv.server->free) + return; + if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1)))) + return; + // FIXME: implement rotation/scaling + VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p); + clippointtosurface(surface, p, out); + // FIXME: implement rotation/scaling + VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); +} + +#define MAX_PRFILES 256 + +qfile_t *pr_files[MAX_PRFILES]; + +void PR_Files_Init(void) +{ + memset(pr_files, 0, sizeof(pr_files)); +} + +void PR_Files_CloseAll(void) +{ + int i; + for (i = 0;i < MAX_PRFILES;i++) + { + if (pr_files[i]) + FS_Close(pr_files[i]); + pr_files[i] = NULL; + } +} + +//float(string s) stof = #81; // get numerical value from a string +void PF_stof(void) +{ + 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; + 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); + PRVM_G_FLOAT(OFS_RETURN) = -2; + return; + } + mode = PRVM_G_FLOAT(OFS_PARM1); + switch(mode) + { + case 0: // FILE_READ + modestring = "rb"; + break; + case 1: // FILE_APPEND + modestring = "ab"; + break; + case 2: // FILE_WRITE + modestring = "wb"; + break; + default: + Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode); + PRVM_G_FLOAT(OFS_RETURN) = -3; + return; + } + 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) + PRVM_G_FLOAT(OFS_RETURN) = -1; + else + PRVM_G_FLOAT(OFS_RETURN) = filenum; +} + +//void(float fhandle) fclose = #111; // closes a file +void PF_fclose(void) +{ + int filenum = PRVM_G_FLOAT(OFS_PARM0); + if (filenum < 0 || filenum >= MAX_PRFILES) + { + Con_Printf("PF_fclose: invalid file handle %i\n", filenum); + return; + } + if (pr_files[filenum] == NULL) + { + Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum); + return; + } + FS_Close(pr_files[filenum]); + pr_files[filenum] = NULL; +} + +//string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring +void PF_fgets(void) +{ + int c, end; + 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); + return; + } + if (pr_files[filenum] == NULL) + { + Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum); + return; + } + end = 0; + for (;;) + { + c = FS_Getc(pr_files[filenum]); + if (c == '\r' || c == '\n' || c < 0) + break; + 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 || end) + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); + else + 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 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); + return; + } + if (pr_files[filenum] == NULL) + { + Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum); + return; + } + 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", string); +} + +//float(string s) strlen = #114; // returns how many characters are in a string +void PF_strlen(void) +{ + const char *s; + s = PRVM_G_STRING(OFS_PARM0); + if (s) + PRVM_G_FLOAT(OFS_RETURN) = strlen(s); + else + 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 = 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, 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 < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++) + string[i] = *s; + string[i] = 0; + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string); +} + +//vector(string s) stov = #117; // returns vector value from a string +void PF_stov(void) +{ + 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) +{ + const char *in; + char *out; + in = PRVM_G_STRING(OFS_PARM0); + out = PR_AllocString(strlen(in) + 1); + strcpy(out, in); + 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) +{ + 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 +//this function originally written by KrimZon, made shorter by LordHavoc +void PF_clientcommand (void) +{ + client_t *temp_client; + int i; + + //find client for this entity + 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 (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 +//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; + p = PRVM_G_STRING(OFS_PARM0); + + num_tokens = 0; + pos = 0; + while(COM_ParseToken(&p, false)) + { + if (num_tokens >= (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; + } + + 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 = PRVM_G_FLOAT(OFS_PARM0); + if (token_num >= 0 && token_num < num_tokens) + PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]); + else + 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[] = +{ +NULL, // #0 +PF_makevectors, // #1 void(entity e) makevectors +PF_setorigin, // #2 void(entity e, vector o) setorigin +PF_setmodel, // #3 void(entity e, string m) setmodel +PF_setsize, // #4 void(entity e, vector min, vector max) setsize +NULL, // #5 void(entity e, vector min, vector max) setabssize +PF_break, // #6 void() break +PF_random, // #7 float() random +PF_sound, // #8 void(entity e, float chan, string samp) sound +PF_normalize, // #9 vector(vector v) normalize +PF_error, // #10 void(string e) error +PF_objerror, // #11 void(string e) objerror +PF_vlen, // #12 float(vector v) vlen +PF_vectoyaw, // #13 float(vector v) vectoyaw +PF_Spawn, // #14 entity() spawn +PF_Remove, // #15 void(entity e) remove +PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline +PF_checkclient, // #17 entity() clientlist +PF_Find, // #18 entity(entity start, .string fld, string match) find +PF_precache_sound, // #19 void(string s) precache_sound +PF_precache_model, // #20 void(string s) precache_model +PF_stuffcmd, // #21 void(entity client, string s)stuffcmd +PF_findradius, // #22 entity(vector org, float rad) findradius +PF_bprint, // #23 void(string s) bprint +PF_sprint, // #24 void(entity client, string s) sprint +PF_dprint, // #25 void(string s) dprint +PF_ftos, // #26 void(string s) ftos +PF_vtos, // #27 void(string s) vtos +PF_coredump, // #28 void() coredump +PF_traceon, // #29 void() traceon +PF_traceoff, // #30 void() traceoff +PF_eprint, // #31 void(entity e) eprint +PF_walkmove, // #32 float(float yaw, float dist) walkmove +NULL, // #33 +PF_droptofloor, // #34 float() droptofloor +PF_lightstyle, // #35 void(float style, string value) lightstyle +PF_rint, // #36 float(float v) rint +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 +NULL, // #42 +PF_fabs, // #43 float(float f) fabs +PF_aim, // #44 vector(entity e, float speed) aim +PF_cvar, // #45 float(string s) cvar +PF_localcmd, // #46 void(string s) localcmd +PF_nextent, // #47 entity(entity e) nextent +PF_particle, // #48 void(vector o, vector d, float color, float count) particle +PF_changeyaw, // #49 void() ChangeYaw +NULL, // #50 +PF_vectoangles, // #51 vector(vector v) vectoangles +PF_WriteByte, // #52 void(float to, float f) WriteByte +PF_WriteChar, // #53 void(float to, float f) WriteChar +PF_WriteShort, // #54 void(float to, float f) WriteShort +PF_WriteLong, // #55 void(float to, float f) WriteLong +PF_WriteCoord, // #56 void(float to, float f) WriteCoord +PF_WriteAngle, // #57 void(float to, float f) WriteAngle +PF_WriteString, // #58 void(float to, string s) WriteString +PF_WriteEntity, // #59 void(float to, entity e) WriteEntity +PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW) +PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW) +PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW) +PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) +PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS) +PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS) +NULL, // #66 +SV_MoveToGoal, // #67 void(float step) movetogoal +PF_precache_file, // #68 string(string s) precache_file +PF_makestatic, // #69 void(entity e) makestatic +PF_changelevel, // #70 void(string s) changelevel +NULL, // #71 +PF_cvar_set, // #72 void(string var, string val) cvar_set +PF_centerprint, // #73 void(entity client, strings) centerprint +PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound +PF_precache_model, // #75 string(string s) precache_model2 +PF_precache_sound, // #76 string(string s) precache_sound2 +PF_precache_file, // #77 string(string s) precache_file2 +PF_setspawnparms, // #78 void(entity e) setspawnparms +NULL, // #79 +NULL, // #80 +PF_stof, // #81 float(string s) stof (FRIK_FILE) +NULL, // #82 +NULL, // #83 +NULL, // #84 +NULL, // #85 +NULL, // #86 +NULL, // #87 +NULL, // #88 +NULL, // #89 +PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX) +PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC) +PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) +PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR) +PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) +PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) +PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) +PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW) +PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) +PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system) +NULL, // #100 +NULL, // #101 +NULL, // #102 +NULL, // #103 +NULL, // #104 +NULL, // #105 +NULL, // #106 +NULL, // #107 +NULL, // #108 +NULL, // #109 +PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE) +PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE) +PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE) +PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE) +PF_strlen, // #114 float(string s) strlen (FRIK_FILE) +PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE) +PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE) +PF_stov, // #117 vector(string) stov (FRIK_FILE) +PF_strzone, // #118 string(string s) strzone (FRIK_FILE) +PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE) +#define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +a a a a a a a a // #120-199 +a a a a a a a a a a // #200-299 +a a a a a a a a a a // #300-399 +PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) +PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR) +PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN) +PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) +PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) +PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) +PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) +PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) +PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) +PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) +PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) +PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) +PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1) +PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1) +PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1) +PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1) +PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) +PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) +PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) +PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) +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 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) +PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) +PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) +PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) +PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) +PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) +PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) +PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) +PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) +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) +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; +int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); + +void PR_Cmd_Init(void) +{ + PR_Files_Init(); + PR_Search_Init(); +} + +void PR_Cmd_Shutdown(void) +{ +} + +void PR_Cmd_Reset(void) +{ + PR_Search_Reset(); + PR_Files_CloseAll(); +} -builtin_t *pr_builtins = pr_builtin; -int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);