X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=pr_cmds.c;h=0839455e32e146397e174ba87a37b4ed6843df5c;hp=304773cc3e8a5e16a14cb577e4513cfb96b021be;hb=febb49ee41691a359b1f33435eb9a13ebb6f2c90;hpb=fb5638603d5fb14033bb41a99dbaba135b5e7985 diff --git a/pr_cmds.c b/pr_cmds.c index 304773cc..0839455e 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -20,9 +20,28 @@ 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)) +mempool_t *pr_strings_mempool; + +// LordHavoc: added this to semi-fix the problem of using many ftos calls in a print +#define STRINGTEMP_BUFFERS 16 +#define STRINGTEMP_LENGTH 4096 +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) (G_INT(OFS_RETURN) = 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,45 +53,76 @@ 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[4096]; // FIXME: buffer overflow potential + int i; + const char *s; + char *outend; - out[0] = 0; - for (i = first;i < pr_argc;i++) - strcat (out, G_STRING((OFS_PARM0+i*3))); - return out; + outend = out + outlength - 1; + for (i = first;i < pr_argc && out < outend;i++) + { + s = G_STRING((OFS_PARM0+i*3)); + while (out < outend && *s) + *out++ = *s++; + } + *out++ = 0; } char *ENGINE_EXTENSIONS = +"DP_CL_LOADSKY " +"DP_EF_ADDITIVE " +"DP_EF_BLUE " +"DP_EF_FLAME " +"DP_EF_FULLBRIGHT " +"DP_EF_NODRAW " +"DP_EF_NOSHADOW " +"DP_EF_RED " +"DP_EF_STARDUST " "DP_ENT_ALPHA " "DP_ENT_CUSTOMCOLORMAP " "DP_ENT_EXTERIORMODELTOCLIENT " -"DP_ENT_LOWPRECISION " "DP_ENT_GLOW " +"DP_ENT_LOWPRECISION " "DP_ENT_SCALE " "DP_ENT_VIEWMODEL " +"DP_GFX_EXTERNALTEXTURES " "DP_GFX_FOG " +"DP_GFX_QUAKE3MODELTAGS " +"DP_GFX_SKINFILES " +"DP_GFX_SKYBOX " "DP_HALFLIFE_MAP " +"DP_HALFLIFE_MAP_CVAR " "DP_INPUTBUTTONS " +"DP_LITSUPPORT " "DP_MONSTERWALK " +"DP_MOVETYPEBOUNCEMISSILE " "DP_MOVETYPEFOLLOW " "DP_QC_CHANGEPITCH " "DP_QC_COPYENTITY " +"DP_QC_CVAR_STRING " "DP_QC_ETOS " "DP_QC_FINDCHAIN " "DP_QC_FINDCHAINFLOAT " "DP_QC_FINDFLOAT " +"DP_QC_FS_SEARCH " // Black: same as in the menu qc "DP_QC_GETLIGHT " +"DP_QC_GETSURFACE " "DP_QC_MINMAXBOUND " +"DP_QC_MULTIPLETEMPSTRINGS " "DP_QC_RANDOMVEC " "DP_QC_SINCOSSQRTPOW " "DP_QC_TRACEBOX " "DP_QC_TRACETOSS " +"DP_QC_TRACE_MOVETYPE_HITMODEL " +"DP_QC_TRACE_MOVETYPE_WORLDONLY " "DP_QC_VECTORVECTORS " "DP_QUAKE2_MODEL " +"DP_QUAKE3_MODEL " "DP_REGISTERCVAR " +"DP_SND_DIRECTIONLESSATTNNONE " +"DP_SND_OGGVORBIS " +"DP_SND_STEREOWAV " "DP_SOLIDCORPSE " "DP_SPRITE32 " "DP_SV_DRAWONLYTOCLIENT " @@ -80,17 +130,28 @@ char *ENGINE_EXTENSIONS = "DP_SV_EXTERIORMODELTOCLIENT " "DP_SV_NODRAWTOCLIENT " "DP_SV_PLAYERPHYSICS " +"DP_SV_ROTATINGBMODEL " "DP_SV_SETCOLOR " "DP_SV_SLOWMO " "DP_TE_BLOOD " "DP_TE_BLOODSHOWER " +"DP_TE_CUSTOMFLASH " "DP_TE_EXPLOSIONRGB " +"DP_TE_FLAMEJET " "DP_TE_PARTICLECUBE " "DP_TE_PARTICLERAIN " "DP_TE_PARTICLESNOW " +"DP_TE_PLASMABURN " +"DP_TE_QUADEFFECTS1 " +"DP_TE_SMALLFLASH " "DP_TE_SPARK " +"DP_TE_STANDARDEFFECTBUILTINS " +"DP_VIEWZOOM " +"FRIK_FILE " +"KRIMZON_SV_PARSECLIENTCOMMAND " "NEH_CMD_PLAY2 " "NEH_RESTOREGAME " +"TENEBRAE_GFX_DLIGHTS " "TW_SV_STEPCONTROL " ; @@ -141,15 +202,15 @@ error(value) */ void PF_error (void) { - char *s; edict_t *ed; + char string[STRINGTEMP_LENGTH]; - s = PF_VarString(0); - Con_Printf ("======SERVER ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); + PF_VarString(0, string, sizeof(string)); + Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string); ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + ED_Print(ed); - Host_Error ("Program error"); + PF_ERROR("Program error"); } /* @@ -164,13 +225,13 @@ objerror(value) */ void PF_objerror (void) { - char *s; edict_t *ed; + char string[STRINGTEMP_LENGTH]; - s = PF_VarString(0); - Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s); + PF_VarString(0, string, sizeof(string)); + Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string); ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); + ED_Print(ed); ED_Free (ed); } @@ -217,6 +278,10 @@ void PF_setorigin (void) float *org; e = G_EDICT(OFS_PARM0); + if (e == sv.edicts) + PF_WARNING("setorigin: can not modify world entity\n"); + if (e->e->free) + PF_WARNING("setorigin: can not modify free entity\n"); org = G_VECTOR(OFS_PARM1); VectorCopy (org, e->v->origin); SV_LinkEdict (e, false); @@ -226,10 +291,10 @@ void PF_setorigin (void) void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate) { int i; - + for (i=0 ; i<3 ; i++) if (min[i] > max[i]) - Host_Error ("backwards mins/maxs"); + PF_ERROR("SetMinMaxSize: backwards mins/maxs\n"); // set derived values VectorCopy (min, e->v->mins); @@ -253,8 +318,12 @@ void PF_setsize (void) { edict_t *e; float *min, *max; - + e = G_EDICT(OFS_PARM0); + if (e == sv.edicts) + PF_WARNING("setsize: can not modify world entity\n"); + if (e->e->free) + PF_WARNING("setsize: can not modify free entity\n"); min = G_VECTOR(OFS_PARM1); max = G_VECTOR(OFS_PARM2); SetMinMaxSize (e, min, max, false); @@ -276,6 +345,10 @@ void PF_setmodel (void) int i; e = G_EDICT(OFS_PARM0); + if (e == sv.edicts) + PF_WARNING("setmodel: can not modify world entity\n"); + if (e->e->free) + PF_WARNING("setmodel: can not modify free entity\n"); m = G_STRING(OFS_PARM1); // check to see if model was properly precached @@ -284,10 +357,10 @@ void PF_setmodel (void) break; if (!*check) - Host_Error ("no precache: %s\n", m); + PF_WARNING("setmodel: no precache\n"); - e->v->model = m - pr_strings; + e->v->model = PR_SetString(*check); e->v->modelindex = i; mod = sv.models[ (int)e->v->modelindex]; @@ -309,10 +382,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); } /* @@ -326,23 +398,24 @@ sprint(clientent, value) */ void PF_sprint (void) { - char *s; client_t *client; int entnum; - + char string[STRINGTEMP_LENGTH]; + entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) + + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_print); - MSG_WriteString (&client->message, s ); + + client = svs.clients + entnum-1; + if (!client->netconnection) + return; + PF_VarString(1, string, sizeof(string)); + MSG_WriteChar(&client->message,svc_print); + MSG_WriteString(&client->message, string); } @@ -357,23 +430,24 @@ centerprint(clientent, value) */ void PF_centerprint (void) { - char *s; client_t *client; int entnum; - + char string[STRINGTEMP_LENGTH]; + entnum = G_EDICTNUM(OFS_PARM0); - s = PF_VarString(1); - - if (entnum < 1 || entnum > svs.maxclients) + + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) { - Con_Printf ("tried to sprint to a non-client\n"); + Con_Print("tried to sprint to a non-client\n"); return; } - - client = &svs.clients[entnum-1]; - - MSG_WriteChar (&client->message,svc_centerprint); - MSG_WriteString (&client->message, s ); + + client = svs.clients + entnum-1; + if (!client->netconnection) + return; + PF_VarString(1, string, sizeof(string)); + MSG_WriteChar(&client->message,svc_centerprint); + MSG_WriteString(&client->message, string); } @@ -389,12 +463,12 @@ void PF_normalize (void) float *value1; vec3_t newvalue; float new; - + value1 = 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 @@ -404,7 +478,7 @@ void PF_normalize (void) newvalue[1] = value1[1] * new; newvalue[2] = value1[2] * new; } - + VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); } @@ -424,7 +498,7 @@ void PF_vlen (void) new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; new = sqrt(new); - + G_FLOAT(OFS_RETURN) = new; } @@ -439,7 +513,7 @@ void PF_vectoyaw (void) { float *value1; float yaw; - + value1 = G_VECTOR(OFS_PARM0); if (value1[1] == 0 && value1[0] == 0) @@ -467,7 +541,7 @@ void PF_vectoangles (void) float *value1; float forward; float yaw, pitch; - + value1 = G_VECTOR(OFS_PARM0); if (value1[1] == 0 && value1[0] == 0) @@ -515,9 +589,9 @@ random() void PF_random (void) { float num; - + num = (rand ()&0x7fff) / ((float)0x7fff); - + G_FLOAT(OFS_RETURN) = num; } @@ -533,7 +607,7 @@ 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); @@ -556,11 +630,11 @@ void PF_ambientsound (void) float vol, attenuation; int i, soundnum, large; - pos = G_VECTOR (OFS_PARM0); + 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)) @@ -568,7 +642,7 @@ void PF_ambientsound (void) if (!*check) { - Con_Printf ("no precache: %s\n", samp); + Con_Printf("no precache: %s\n", samp); return; } @@ -618,21 +692,21 @@ void PF_sound (void) 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); - + 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); } @@ -646,7 +720,7 @@ break() */ void PF_break (void) { - Host_Error ("break statement"); + PF_ERROR("break: break statement\n"); } /* @@ -664,15 +738,17 @@ void PF_traceline (void) { float *v1, *v2; trace_t trace; - int nomonsters; + int move; edict_t *ent; + pr_xfunction->builtinsprofile += 30; + v1 = G_VECTOR(OFS_PARM0); v2 = G_VECTOR(OFS_PARM1); - nomonsters = G_FLOAT(OFS_PARM2); + move = G_FLOAT(OFS_PARM2); ent = G_EDICT(OFS_PARM3); - trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent); + trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent); pr_global_struct->trace_allsolid = trace.allsolid; pr_global_struct->trace_startsolid = trace.startsolid; @@ -706,17 +782,19 @@ void PF_tracebox (void) { float *v1, *v2, *m1, *m2; trace_t trace; - int nomonsters; + int move; edict_t *ent; + pr_xfunction->builtinsprofile += 30; + v1 = G_VECTOR(OFS_PARM0); m1 = G_VECTOR(OFS_PARM1); m2 = G_VECTOR(OFS_PARM2); v2 = G_VECTOR(OFS_PARM3); - nomonsters = G_FLOAT(OFS_PARM4); + move = G_FLOAT(OFS_PARM4); ent = G_EDICT(OFS_PARM5); - trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent); + trace = SV_Move (v1, m1, m2, v2, move, ent); pr_global_struct->trace_allsolid = trace.allsolid; pr_global_struct->trace_startsolid = trace.startsolid; @@ -725,7 +803,7 @@ void PF_tracebox (void) 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; + pr_global_struct->trace_plane_dist = trace.plane.dist; if (trace.ent) pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); else @@ -739,7 +817,11 @@ void PF_TraceToss (void) edict_t *ent; edict_t *ignore; + pr_xfunction->builtinsprofile += 600; + ent = G_EDICT(OFS_PARM0); + if (ent == sv.edicts) + PF_WARNING("tracetoss: can not use world entity\n"); ignore = G_EDICT(OFS_PARM1); trace = SV_Trace_Toss (ent, ignore); @@ -751,7 +833,7 @@ void PF_TraceToss (void) 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; + pr_global_struct->trace_plane_dist = trace.plane.dist; if (trace.ent) pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent); else @@ -775,23 +857,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; 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 @@ -799,30 +876,25 @@ int PF_newcheckclient (int check) for ( ; ; i++) { + // count the cost + pr_xfunction->builtinsprofile++; + // wrap around if (i == svs.maxclients+1) i = 1; - + // look up the client's edict ent = EDICT_NUM(i); - - if (i == check) - break; // didn't find anything else - - if (ent->free) - continue; - if (ent->v->health <= 0) + // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop) + if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET))) 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->v->origin, ent->v->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; } @@ -846,8 +918,6 @@ int c_invis, c_notvis; void PF_checkclient (void) { edict_t *ent, *self; - mleaf_t *leaf; - int l; vec3_t view; // find a new check if on a new frame @@ -859,7 +929,7 @@ void PF_checkclient (void) // return check if it might be visible ent = EDICT_NUM(sv.lastcheck); - if (ent->free || ent->v->health <= 0) + if (ent->e->free || ent->v->health <= 0) { RETURN_EDICT(sv.edicts); return; @@ -867,17 +937,12 @@ void PF_checkclient (void) // 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); - if (leaf) + VectorAdd(self->v->origin, self->v->view_ofs, view); + if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view)) { - l = (leaf - sv.worldmodel->leafs) - 1; - if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) ) - { - c_notvis++; - RETURN_EDICT(sv.edicts); - return; - } + c_notvis++; + RETURN_EDICT(sv.edicts); + return; } // might be able to see it @@ -902,15 +967,18 @@ void PF_stuffcmd (void) int entnum; char *str; client_t *old; - + entnum = G_EDICTNUM(OFS_PARM0); - if (entnum < 1 || entnum > svs.maxclients) - Host_Error ("Parm 0 not a client"); - str = G_STRING(OFS_PARM1); + if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active) + { + Con_Print("Can't stuffcmd to a non-client\n"); + return; + } + str = G_STRING(OFS_PARM1); old = host_client; - host_client = &svs.clients[entnum-1]; - Host_ClientCommands ("%s", str); + if ((host_client = svs.clients + entnum-1) && host_client->netconnection) + Host_ClientCommands ("%s", str); host_client = old; } @@ -918,17 +986,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(G_STRING(OFS_PARM0)); } /* @@ -940,11 +1005,7 @@ float cvar (string) */ void PF_cvar (void) { - char *str; - - str = G_STRING(OFS_PARM0); - - G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str); + G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0)); } /* @@ -956,12 +1017,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(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1)); } /* @@ -991,7 +1047,8 @@ void PF_findradius (void) ent = NEXT_EDICT(sv.edicts); for (i=1 ; ifree) + pr_xfunction->builtinsprofile++; + if (ent->e->free) continue; if (ent->v->solid == SOLID_NOT) continue; @@ -1019,21 +1076,12 @@ 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) @@ -1043,9 +1091,11 @@ void PF_ftos (void) v = G_FLOAT(OFS_PARM0); s = PR_GetTempString(); - // LordHavoc: ftos improvement - sprintf (s, "%g", v); - G_INT(OFS_RETURN) = s - pr_strings; + if ((float)((int)v) == v) + sprintf(s, "%i", (int)v); + else + sprintf(s, "%f", v); + G_INT(OFS_RETURN) = PR_SetString(s); } void PF_fabs (void) @@ -1060,7 +1110,7 @@ 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; + G_INT(OFS_RETURN) = PR_SetString(s); } void PF_etos (void) @@ -1068,12 +1118,13 @@ void PF_etos (void) char *s; s = PR_GetTempString(); sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0)); - G_INT(OFS_RETURN) = s - pr_strings; + G_INT(OFS_RETURN) = PR_SetString(s); } void PF_Spawn (void) { edict_t *ed; + pr_xfunction->builtinsprofile += 20; ed = ED_Alloc(); RETURN_EDICT(ed); } @@ -1081,12 +1132,16 @@ void PF_Spawn (void) void PF_Remove (void) { edict_t *ed; + pr_xfunction->builtinsprofile += 20; ed = G_EDICT(OFS_PARM0); if (ed == sv.edicts) - Host_Error("remove: tried to remove world\n"); + PF_WARNING("remove: tried to remove world\n"); if (NUM_FOR_EDICT(ed) <= svs.maxclients) - Host_Error("remove: tried to remove a client\n"); + PF_WARNING("remove: tried to remove a client\n"); + // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...) + if (ed->e->free && developer.integer) + PF_WARNING("remove: tried to remove an entity that was already removed\n"); ED_Free (ed); } @@ -1110,8 +1165,9 @@ void PF_Find (void) for (e++ ; e < sv.num_edicts ; e++) { + pr_xfunction->builtinsprofile++; ed = EDICT_NUM(e); - if (ed->free) + if (ed->e->free) continue; t = E_STRING(ed,f); if (!t) @@ -1140,8 +1196,9 @@ void PF_FindFloat (void) for (e++ ; e < sv.num_edicts ; e++) { + pr_xfunction->builtinsprofile++; ed = EDICT_NUM(e); - if (ed->free) + if (ed->e->free) continue; if (E_FLOAT(ed,f) == s) { @@ -1175,7 +1232,8 @@ void PF_findchain (void) ent = NEXT_EDICT(sv.edicts); for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) { - if (ent->free) + pr_xfunction->builtinsprofile++; + if (ent->e->free) continue; t = E_STRING(ent,f); if (!t) @@ -1207,7 +1265,8 @@ void PF_findchainfloat (void) ent = NEXT_EDICT(sv.edicts); for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) { - if (ent->free) + pr_xfunction->builtinsprofile++; + if (ent->e->free) continue; if (E_FLOAT(ent,f) != s) continue; @@ -1222,7 +1281,7 @@ void PF_findchainfloat (void) void PR_CheckEmptyString (char *s) { if (s[0] <= ' ') - Host_Error ("Bad string"); + PF_ERROR("Bad string"); } void PF_precache_file (void) @@ -1236,7 +1295,7 @@ void PF_precache_sound (void) int i; if (sv.state != ss_loading) - Host_Error ("PF_Precache_*: Precache can only be done in spawn functions"); + PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions"); s = G_STRING(OFS_PARM0); G_INT(OFS_RETURN) = G_INT(OFS_PARM0); @@ -1252,7 +1311,7 @@ void PF_precache_sound (void) if (!strcmp(sv.sound_precache[i], s)) return; } - Host_Error ("PF_precache_sound: overflow"); + PF_ERROR("PF_precache_sound: overflow"); } void PF_precache_model (void) @@ -1261,10 +1320,10 @@ void PF_precache_model (void) int i; if (sv.state != ss_loading) - Host_Error ("PF_Precache_*: Precache can only be done in spawn functions"); + PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions"); s = G_STRING(OFS_PARM0); - if (sv.worldmodel->ishlbsp && ((!s) || (!s[0]))) + if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0]))) return; G_INT(OFS_RETURN) = G_INT(OFS_PARM0); PR_CheckEmptyString (s); @@ -1280,7 +1339,7 @@ void PF_precache_model (void) if (!strcmp(sv.model_precache[i], s)) return; } - Host_Error ("PF_precache_model: overflow"); + PF_ERROR("PF_precache_model: overflow"); } @@ -1316,18 +1375,22 @@ void PF_walkmove (void) edict_t *ent; float yaw, dist; vec3_t move; - dfunction_t *oldf; + mfunction_t *oldf; int oldself; + // assume failure if it returns early + G_FLOAT(OFS_RETURN) = 0; + ent = PROG_TO_EDICT(pr_global_struct->self); + if (ent == sv.edicts) + PF_WARNING("walkmove: can not modify world entity\n"); + if (ent->e->free) + PF_WARNING("walkmove: can not modify free entity\n"); 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; return; - } yaw = yaw*M_PI*2 / 360; @@ -1360,16 +1423,21 @@ void PF_droptofloor (void) vec3_t end; trace_t trace; + // assume failure if it returns early + G_FLOAT(OFS_RETURN) = 0; + ent = PROG_TO_EDICT(pr_global_struct->self); + if (ent == sv.edicts) + PF_WARNING("droptofloor: can not modify world entity\n"); + if (ent->e->free) + PF_WARNING("droptofloor: can not modify free entity\n"); VectorCopy (ent->v->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 + if (trace.fraction != 1) { VectorCopy (trace.endpos, ent->v->origin); SV_LinkEdict (ent, false); @@ -1377,7 +1445,7 @@ void PF_droptofloor (void) ent->v->groundentity = EDICT_TO_PROG(trace.ent); G_FLOAT(OFS_RETURN) = 1; // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->suspendedinairflag = true; + ent->e->suspendedinairflag = true; } } @@ -1405,13 +1473,15 @@ void PF_lightstyle (void) 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->netconnection) { MSG_WriteChar (&client->message, svc_lightstyle); MSG_WriteChar (&client->message,style); MSG_WriteString (&client->message, val); } + } } void PF_rint (void) @@ -1450,7 +1520,7 @@ PF_pointcontents */ void PF_pointcontents (void) { - G_FLOAT(OFS_RETURN) = Mod_PointContents(G_VECTOR(OFS_PARM0), sv.worldmodel); + G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0)); } /* @@ -1468,6 +1538,7 @@ void PF_nextent (void) i = G_EDICTNUM(OFS_PARM0); while (1) { + pr_xfunction->builtinsprofile++; i++; if (i == sv.num_edicts) { @@ -1475,7 +1546,7 @@ void PF_nextent (void) return; } ent = EDICT_NUM(i); - if (!ent->free) + if (!ent->e->free) { RETURN_EDICT(ent); return; @@ -1500,7 +1571,14 @@ void PF_aim (void) float dist, bestdist; float speed; + // assume failure if it returns early + VectorClear(G_VECTOR(OFS_RETURN)); + ent = G_EDICT(OFS_PARM0); + if (ent == sv.edicts) + PF_WARNING("aim: can not use world entity\n"); + if (ent->e->free) + PF_WARNING("aim: can not use free entity\n"); speed = G_FLOAT(OFS_PARM1); VectorCopy (ent->v->origin, start); @@ -1526,6 +1604,7 @@ void PF_aim (void) check = NEXT_EDICT(sv.edicts); for (i=1 ; ibuiltinsprofile++; if (check->v->takedamage != DAMAGE_AIM) continue; if (check == ent) @@ -1576,6 +1655,10 @@ void PF_changeyaw (void) float ideal, current, move, speed; ent = PROG_TO_EDICT(pr_global_struct->self); + if (ent == sv.edicts) + PF_WARNING("changeyaw: can not modify world entity\n"); + if (ent->e->free) + PF_WARNING("changeyaw: can not modify free entity\n"); current = ANGLEMOD(ent->v->angles[1]); ideal = ent->v->ideal_yaw; speed = ent->v->yaw_speed; @@ -1619,19 +1702,23 @@ void PF_changepitch (void) eval_t *val; ent = G_EDICT(OFS_PARM0); + if (ent == sv.edicts) + PF_WARNING("changepitch: can not modify world entity\n"); + if (ent->e->free) + PF_WARNING("changepitch: can not modify free entity\n"); current = ANGLEMOD( ent->v->angles[0] ); if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch))) ideal = val->_float; else { - Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n"); return; } if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed))) speed = val->_float; else { - Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch"); + PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n"); return; } @@ -1690,8 +1777,8 @@ sizebuf_t *WriteDest (void) case MSG_ONE: ent = PROG_TO_EDICT(pr_global_struct->msg_entity); entnum = NUM_FOR_EDICT(ent); - if (entnum < 1 || entnum > svs.maxclients) - Host_Error ("WriteDest: not a client"); + 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: @@ -1701,7 +1788,7 @@ sizebuf_t *WriteDest (void) return &sv.signon; default: - Host_Error ("WriteDest: bad destination"); + Host_Error("WriteDest: bad destination"); break; } @@ -1757,6 +1844,10 @@ void PF_makestatic (void) int i, large; ent = G_EDICT(OFS_PARM0); + if (ent == sv.edicts) + PF_WARNING("makestatic: can not modify world entity\n"); + if (ent->e->free) + PF_WARNING("makestatic: can not modify free entity\n"); large = false; if (ent->v->modelindex >= 256 || ent->v->frame >= 256) @@ -1802,12 +1893,14 @@ void PF_setspawnparms (void) ent = G_EDICT(OFS_PARM0); i = NUM_FOR_EDICT(ent); - if (i < 1 || i > svs.maxclients) - Host_Error ("Entity is not a client"); + 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]; } @@ -1867,7 +1960,6 @@ void PF_randomvec (void) VectorCopy (temp, G_VECTOR(OFS_RETURN)); } -void SV_LightPoint (vec3_t color, vec3_t p); /* ================= PF_GetLight @@ -1882,11 +1974,15 @@ getlight(vector) */ void PF_GetLight (void) { - vec3_t color; - vec_t* p; + vec3_t ambientcolor, diffusecolor, diffusenormal; + vec_t *p; p = G_VECTOR(OFS_PARM0); - SV_LightPoint (color, p); - VectorCopy (color, G_VECTOR(OFS_RETURN)); + VectorClear(ambientcolor); + VectorClear(diffusecolor); + VectorClear(diffusenormal); + if (sv.worldmodel && sv.worldmodel->brush.LightPoint) + sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal); + VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN)); } #define MAX_QC_CVARS 128 @@ -1907,12 +2003,12 @@ void PF_registercvar (void) // check for overlap with a command if (Cmd_Exists (name)) { - Con_Printf ("PF_registercvar: %s is a command\n", name); + Con_Printf("PF_registercvar: %s is a command\n", name); return; } if (currentqc_cvar >= MAX_QC_CVARS) - Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS); + PF_ERROR("PF_registercvar: ran out of cvar slots\n"); // copy the name and value variable = &qc_cvar[currentqc_cvar++]; @@ -1950,7 +2046,10 @@ void PF_min (void) G_FLOAT(OFS_RETURN) = f; } else - Host_Error("min: must supply at least 2 floats\n"); + { + G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("min: must supply at least 2 floats\n"); + } } /* @@ -1977,7 +2076,10 @@ void PF_max (void) G_FLOAT(OFS_RETURN) = f; } else - Host_Error("max: must supply at least 2 floats\n"); + { + G_FLOAT(OFS_RETURN) = 0; + PF_WARNING("max: must supply at least 2 floats\n"); + } } /* @@ -2021,7 +2123,15 @@ void PF_copyentity (void) { edict_t *in, *out; in = G_EDICT(OFS_PARM0); + if (in == sv.edicts) + PF_WARNING("copyentity: can not read world entity\n"); + if (in->e->free) + PF_WARNING("copyentity: can not read free entity\n"); out = G_EDICT(OFS_PARM1); + if (out == sv.edicts) + PF_WARNING("copyentity: can not modify world entity\n"); + if (out->e->free) + PF_WARNING("copyentity: can not modify free entity\n"); memcpy(out->v, in->v, progs->entityfields * 4); } @@ -2036,20 +2146,24 @@ setcolor(clientent, value) */ void PF_setcolor (void) { - client_t *client; - int entnum, i; + client_t *client; + int entnum, i; + eval_t *val; entnum = G_EDICTNUM(OFS_PARM0); i = 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 ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors))) + val->_float = i; client->colors = i; + client->old_colors = i; client->edict->v->team = (i & 15) + 1; MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors); @@ -2069,7 +2183,7 @@ void PF_effect (void) char *s; s = G_STRING(OFS_PARM1); if (!s || !s[0]) - Host_Error("effect: no model specified\n"); + PF_WARNING("effect: no model specified\n"); SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4)); } @@ -2390,6 +2504,7 @@ void PF_te_explosion2 (void) MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // color MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1)); + MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2)); } void PF_te_lightning1 (void) @@ -2494,17 +2609,15 @@ static msurface_t *getsurface(edict_t *ed, int surfnum) { int modelindex; model_t *model; - if (!ed || ed->free) + if (!ed || ed->e->free) return NULL; modelindex = ed->v->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) return NULL; model = sv.models[modelindex]; - if (model->type != mod_brush) - return NULL; if (surfnum < 0 || surfnum >= model->nummodelsurfaces) return NULL; - return model->surfaces + surfnum + model->firstmodelsurface; + return model->brushq1.surfaces + surfnum + model->firstmodelsurface; } @@ -2529,7 +2642,7 @@ void PF_getsurfacepoint(void) int pointnum; VectorClear(G_VECTOR(OFS_RETURN)); ed = G_EDICT(OFS_PARM0); - if (!ed || ed->free) + if (!ed || ed->e->free) return; if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) return; @@ -2559,7 +2672,7 @@ void PF_getsurfacetexture(void) G_INT(OFS_RETURN) = 0; if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1)))) return; - G_INT(OFS_RETURN) = surf->texinfo->texture->name - pr_strings; + G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name); } //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; void PF_getsurfacenearpoint(void) @@ -2575,13 +2688,13 @@ void PF_getsurfacenearpoint(void) ed = G_EDICT(OFS_PARM0); point = G_VECTOR(OFS_PARM1); - if (!ed || ed->free) + if (!ed || ed->e->free) return; modelindex = ed->v->modelindex; if (modelindex < 1 || modelindex >= MAX_MODELS) return; model = sv.models[modelindex]; - if (model->type != mod_brush) + if (!model->brushq1.numsurfaces) return; // FIXME: implement rotation/scaling @@ -2590,7 +2703,7 @@ void PF_getsurfacenearpoint(void) bestdist = 1000000000; for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++) { - surf = model->surfaces + surfnum + model->firstmodelsurface; + surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface; dist = PlaneDiff(p, surf->plane); dist = dist * dist; if (dist < bestdist) @@ -2615,7 +2728,7 @@ void PF_getsurfaceclippedpoint(void) vec3_t p, out; VectorClear(G_VECTOR(OFS_RETURN)); ed = G_EDICT(OFS_PARM0); - if (!ed || ed->free) + if (!ed || ed->e->free) return; if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1)))) return; @@ -2626,172 +2739,698 @@ void PF_getsurfaceclippedpoint(void) VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN)); } -void PF_Fixme (void) +#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)); + 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, i; + char *modestring, *filename; + for (filenum = 0;filenum < MAX_PRFILES;filenum++) + if (pr_files[filenum] == NULL) + break; + if (filenum >= MAX_PRFILES) + { + Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES); + G_FLOAT(OFS_RETURN) = -2; + return; + } + mode = 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); + G_FLOAT(OFS_RETURN) = -3; + return; + } + filename = G_STRING(OFS_PARM0); + // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with + // ../ is parent directory on many platforms + // // is parent directory on Amiga + // / at the beginning of a path is root on unix, and parent directory on Amiga + // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea) + // \ is a windows-ism (so it's naughty to use it, / works on all platforms) + for (i = 0;filename[i];i++) + { + if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/') + { + Con_Printf("PF_fopen: dangerous/confusing/annoying/non-portable filename \"%s\" not allowed. (contains control characters or // or .. or : or \\ or begins with /)\n", filename); + G_FLOAT(OFS_RETURN) = -4; + return; + } + } + pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false); + + if (pr_files[filenum] == NULL && modestring == "rb") + pr_files[filenum] = FS_Open(filename, modestring, false); + + if (pr_files[filenum] == NULL) + G_FLOAT(OFS_RETURN) = -1; + else + G_FLOAT(OFS_RETURN) = filenum; +} + +//void(float fhandle) fclose = #111; // closes a file +void PF_fclose(void) +{ + int filenum = 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) { - Host_Error ("unimplemented QC builtin"); // LordHavoc: was misspelled (bulitin) + int c, end; + static char string[STRINGTEMP_LENGTH]; + int filenum = 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 (developer.integer) + Con_Printf("fgets: %s\n", string); + if (c >= 0) + G_INT(OFS_RETURN) = PR_SetString(string); + else + 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 = 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) +{ + char *s; + s = G_STRING(OFS_PARM0); + if (s) + G_FLOAT(OFS_RETURN) = strlen(s); + else + 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); + G_INT(OFS_RETURN) = PR_SetString(s); +} + +//string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring +void PF_substring(void) +{ + int i, start, length; + char *s, *string = PR_GetTempString(); + s = G_STRING(OFS_PARM0); + start = G_FLOAT(OFS_PARM1); + length = G_FLOAT(OFS_PARM2); + if (!s) + s = ""; + for (i = 0;i < start && *s;i++, s++); + for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++) + string[i] = *s; + string[i] = 0; + G_INT(OFS_RETURN) = PR_SetString(string); +} + +//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, G_VECTOR(OFS_RETURN)); +} + +//string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often) +void PF_strzone(void) +{ + char *in, *out; + in = G_STRING(OFS_PARM0); + out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1); + strcpy(out, in); + G_INT(OFS_RETURN) = PR_SetString(out); +} + +//void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!) +void PF_strunzone(void) +{ + Mem_Free(G_STRING(OFS_PARM0)); +} + +//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 = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1); + if (i < 0 || i >= svs.maxclients || !svs.clients[i].active) + { + Con_Print("PF_clientcommand: entity is not a client\n"); + return; + } + + temp_client = host_client; + host_client = svs.clients + i; + Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client); + host_client = 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 = 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; + } + + G_FLOAT(OFS_RETURN) = num_tokens; +} + +//string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index) +//this function originally written by KrimZon, made shorter by LordHavoc +void PF_argv (void) +{ + int token_num = G_FLOAT(OFS_PARM0); + if (token_num >= 0 && token_num < num_tokens) + G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]); + else + G_INT(OFS_RETURN) = PR_SetString(""); +} + +//void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag) +void PF_setattachment (void) +{ + edict_t *e = G_EDICT(OFS_PARM0); + edict_t *tagentity = G_EDICT(OFS_PARM1); + char *tagname = G_STRING(OFS_PARM2); + eval_t *v; + int i, modelindex; + model_t *model; + + if (e == sv.edicts) + PF_WARNING("setattachment: can not modify world entity\n"); + if (e->e->free) + PF_WARNING("setattachment: can not modify free entity\n"); + + if (tagentity == NULL) + tagentity = sv.edicts; + + v = GETEDICTFIELDVALUE(e, eval_tag_entity); + if (v) + v->edict = EDICT_TO_PROG(tagentity); + + v = GETEDICTFIELDVALUE(e, eval_tag_index); + if (v) + v->_float = 0; + if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0]) + { + modelindex = (int)tagentity->v->modelindex; + if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) + { + if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames) + for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++) + if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name)) + v->_float = i + 1; + if (v->_float == 0 && model->alias.aliasnum_tags) + for (i = 0;i < model->alias.aliasnum_tags;i++) + if (!strcmp(tagname, model->alias.aliasdata_tags[i].name)) + v->_float = i + 1; + if (v->_float == 0) + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name); + } + else + Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity)); + } +} + + +///////////////////////////////////////// +// 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; + char *pattern; + int caseinsens, quiet; + + pattern = G_STRING(OFS_PARM0); + + PR_CheckEmptyString(pattern); + + caseinsens = G_FLOAT(OFS_PARM1); + quiet = 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); + G_FLOAT(OFS_RETURN) = -2; + return; + } + + if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet))) + G_FLOAT(OFS_RETURN) = -1; + else + G_FLOAT(OFS_RETURN) = handle; +} + +/* +========= +VM_search_end + +void search_end(float handle) +========= +*/ +void PF_search_end(void) +{ + int handle; + + handle = 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 = 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; + } + + 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 = G_FLOAT(OFS_PARM0); + filenum = 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]); + + G_INT(OFS_RETURN) = PR_SetString(tmp); +} + +void PF_cvar_string (void) +{ + char *str; + cvar_t *var; + char *tmp; + + str = G_STRING(OFS_PARM0); + var = Cvar_FindVar (str); + + tmp = PR_GetTempString(); + strcpy(tmp, var->string); + + G_INT(OFS_RETURN) = PR_SetString(tmp); } builtin_t pr_builtin[] = { -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 -PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434; -PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435; -PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436; -PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437; -PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438; -PF_getsurfaceclippedpoint,// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439; +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 color) 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 +PF_search_end, // #445 +PF_search_getsize, // #446 +PF_search_getfilename, // #447 +PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING) +NULL, // #449 +a a a a a // #450-499 (LordHavoc) }; builtin_t *pr_builtins = pr_builtin; int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); +void PR_Cmd_Init(void) +{ + pr_strings_mempool = Mem_AllocPool("pr_stringszone"); + PR_Files_Init(); + PR_Search_Init(); +} + +void PR_Cmd_Reset(void) +{ + Mem_EmptyPool(pr_strings_mempool); + PR_Search_Reset(); + PR_Files_CloseAll(); +} +