2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
24 cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
26 mempool_t *pr_strings_mempool;
28 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
29 #define STRINGTEMP_BUFFERS 16
30 #define STRINGTEMP_LENGTH 4096
31 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
32 static int pr_string_tempindex = 0;
34 static char *PR_GetTempString(void)
37 s = pr_string_temp[pr_string_tempindex];
38 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
42 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
46 ===============================================================================
50 ===============================================================================
54 void PF_VarString(int first, char *out, int outlength)
60 outend = out + outlength - 1;
61 for (i = first;i < pr_argc && out < outend;i++)
63 s = G_STRING((OFS_PARM0+i*3));
64 while (out < outend && *s)
70 char *ENGINE_EXTENSIONS =
80 "DP_ENT_CUSTOMCOLORMAP "
81 "DP_ENT_EXTERIORMODELTOCLIENT "
83 "DP_ENT_LOWPRECISION "
86 "DP_GFX_EXTERNALTEXTURES "
88 "DP_GFX_QUAKE3MODELTAGS "
92 "DP_HALFLIFE_MAP_CVAR "
96 "DP_MOVETYPEBOUNCEMISSILE "
103 "DP_QC_FINDCHAINFLOAT "
105 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
110 "DP_QC_SINCOSSQRTPOW "
113 "DP_QC_TRACE_MOVETYPE_HITMODEL "
114 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
115 "DP_QC_VECTORVECTORS "
121 "DP_SV_DRAWONLYTOCLIENT "
123 "DP_SV_EXTERIORMODELTOCLIENT "
124 "DP_SV_NODRAWTOCLIENT "
125 "DP_SV_PLAYERPHYSICS "
131 "DP_TE_EXPLOSIONRGB "
133 "DP_TE_PARTICLECUBE "
134 "DP_TE_PARTICLERAIN "
135 "DP_TE_PARTICLESNOW "
137 "DP_TE_QUADEFFECTS1 "
140 "DP_TE_STANDARDEFFECTBUILTINS "
143 "KRIMZON_SV_PARSECLIENTCOMMAND "
149 qboolean checkextension(char *name)
154 for (e = ENGINE_EXTENSIONS;*e;e++)
161 while (*e && *e != ' ')
163 if (e - start == len)
164 if (!strncasecmp(start, name, len))
174 returns true if the extension is supported by the server
176 checkextension(extensionname)
179 void PF_checkextension (void)
181 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
188 This is a TERMINAL error, which will kill off the entire server.
197 char string[STRINGTEMP_LENGTH];
199 PF_VarString(0, string, sizeof(string));
200 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
201 ed = PROG_TO_EDICT(pr_global_struct->self);
204 Host_Error ("Program error");
211 Dumps out self, then an error message. The program is aborted and self is
212 removed, but the level can continue.
217 void PF_objerror (void)
220 char string[STRINGTEMP_LENGTH];
222 PF_VarString(0, string, sizeof(string));
223 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
224 ed = PROG_TO_EDICT(pr_global_struct->self);
234 Writes new values for v_forward, v_up, and v_right based on angles
238 void PF_makevectors (void)
240 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
247 Writes new values for v_forward, v_up, and v_right based on the given forward vector
248 vectorvectors(vector, vector)
251 void PF_vectorvectors (void)
253 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
254 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
261 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
263 setorigin (entity, origin)
266 void PF_setorigin (void)
271 e = G_EDICT(OFS_PARM0);
273 Host_Error("setorigin: can not modify world entity\n");
275 Host_Error("setorigin: can not modify free entity\n");
276 org = G_VECTOR(OFS_PARM1);
277 VectorCopy (org, e->v->origin);
278 SV_LinkEdict (e, false);
282 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
286 for (i=0 ; i<3 ; i++)
288 Host_Error ("backwards mins/maxs");
290 // set derived values
291 VectorCopy (min, e->v->mins);
292 VectorCopy (max, e->v->maxs);
293 VectorSubtract (max, min, e->v->size);
295 SV_LinkEdict (e, false);
302 the size box is rotated by the current angle
303 LordHavoc: no it isn't...
305 setsize (entity, minvector, maxvector)
308 void PF_setsize (void)
313 e = G_EDICT(OFS_PARM0);
315 Host_Error("setsize: can not modify world entity\n");
317 Host_Error("setsize: can not modify free entity\n");
318 min = G_VECTOR(OFS_PARM1);
319 max = G_VECTOR(OFS_PARM2);
320 SetMinMaxSize (e, min, max, false);
328 setmodel(entity, model)
331 void PF_setmodel (void)
338 e = G_EDICT(OFS_PARM0);
340 Host_Error("setmodel: can not modify world entity\n");
342 Host_Error("setmodel: can not modify free entity\n");
343 m = G_STRING(OFS_PARM1);
345 // check to see if model was properly precached
346 for (i=0, check = sv.model_precache ; *check ; i++, check++)
347 if (!strcmp(*check, m))
351 Host_Error ("no precache: %s\n", m);
354 e->v->model = PR_SetString(*check);
355 e->v->modelindex = i;
357 mod = sv.models[ (int)e->v->modelindex];
360 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
362 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
369 broadcast print to everyone on server
374 void PF_bprint (void)
376 char string[STRINGTEMP_LENGTH];
377 PF_VarString(0, string, sizeof(string));
378 SV_BroadcastPrintf("%s", string);
385 single print to a specific client
387 sprint(clientent, value)
390 void PF_sprint (void)
394 char string[STRINGTEMP_LENGTH];
396 entnum = G_EDICTNUM(OFS_PARM0);
398 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
400 Con_Printf ("tried to sprint to a non-client\n");
404 client = svs.clients + entnum-1;
405 if (!client->netconnection)
407 PF_VarString(1, string, sizeof(string));
408 MSG_WriteChar(&client->message,svc_print);
409 MSG_WriteString(&client->message, string);
417 single print to a specific client
419 centerprint(clientent, value)
422 void PF_centerprint (void)
426 char string[STRINGTEMP_LENGTH];
428 entnum = G_EDICTNUM(OFS_PARM0);
430 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
432 Con_Printf ("tried to sprint to a non-client\n");
436 client = svs.clients + entnum-1;
437 if (!client->netconnection)
439 PF_VarString(1, string, sizeof(string));
440 MSG_WriteChar(&client->message,svc_centerprint);
441 MSG_WriteString(&client->message, string);
449 vector normalize(vector)
452 void PF_normalize (void)
458 value1 = G_VECTOR(OFS_PARM0);
460 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
464 newvalue[0] = newvalue[1] = newvalue[2] = 0;
468 newvalue[0] = value1[0] * new;
469 newvalue[1] = value1[1] * new;
470 newvalue[2] = value1[2] * new;
473 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
488 value1 = G_VECTOR(OFS_PARM0);
490 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
493 G_FLOAT(OFS_RETURN) = new;
500 float vectoyaw(vector)
503 void PF_vectoyaw (void)
508 value1 = G_VECTOR(OFS_PARM0);
510 if (value1[1] == 0 && value1[0] == 0)
514 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
519 G_FLOAT(OFS_RETURN) = yaw;
527 vector vectoangles(vector)
530 void PF_vectoangles (void)
536 value1 = G_VECTOR(OFS_PARM0);
538 if (value1[1] == 0 && value1[0] == 0)
548 // LordHavoc: optimized a bit
551 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
555 else if (value1[1] > 0)
560 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
561 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
566 G_FLOAT(OFS_RETURN+0) = pitch;
567 G_FLOAT(OFS_RETURN+1) = yaw;
568 G_FLOAT(OFS_RETURN+2) = 0;
575 Returns a number from 0<= num < 1
580 void PF_random (void)
584 num = (rand ()&0x7fff) / ((float)0x7fff);
586 G_FLOAT(OFS_RETURN) = num;
593 particle(origin, color, count)
596 void PF_particle (void)
602 org = G_VECTOR(OFS_PARM0);
603 dir = G_VECTOR(OFS_PARM1);
604 color = G_FLOAT(OFS_PARM2);
605 count = G_FLOAT(OFS_PARM3);
606 SV_StartParticle (org, dir, color, count);
616 void PF_ambientsound (void)
621 float vol, attenuation;
622 int i, soundnum, large;
624 pos = G_VECTOR (OFS_PARM0);
625 samp = G_STRING(OFS_PARM1);
626 vol = G_FLOAT(OFS_PARM2);
627 attenuation = G_FLOAT(OFS_PARM3);
629 // check to see if samp was properly precached
630 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
631 if (!strcmp(*check,samp))
636 Con_Printf ("no precache: %s\n", samp);
644 // add an svc_spawnambient command to the level signon packet
647 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
649 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
651 for (i=0 ; i<3 ; i++)
652 MSG_WriteDPCoord(&sv.signon, pos[i]);
655 MSG_WriteShort (&sv.signon, soundnum);
657 MSG_WriteByte (&sv.signon, soundnum);
659 MSG_WriteByte (&sv.signon, vol*255);
660 MSG_WriteByte (&sv.signon, attenuation*64);
668 Each entity can have eight independant sound sources, like voice,
671 Channel 0 is an auto-allocate channel, the others override anything
672 already running on that entity/channel pair.
674 An attenuation of 0 will play full volume everywhere in the level.
675 Larger attenuations will drop off.
687 entity = G_EDICT(OFS_PARM0);
688 channel = G_FLOAT(OFS_PARM1);
689 sample = G_STRING(OFS_PARM2);
690 volume = G_FLOAT(OFS_PARM3) * 255;
691 attenuation = G_FLOAT(OFS_PARM4);
693 if (volume < 0 || volume > 255)
694 Host_Error ("SV_StartSound: volume = %i", volume);
696 if (attenuation < 0 || attenuation > 4)
697 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
699 if (channel < 0 || channel > 7)
700 Host_Error ("SV_StartSound: channel = %i", channel);
702 SV_StartSound (entity, channel, sample, volume, attenuation);
714 Host_Error ("break statement");
721 Used for use tracing and shot targeting
722 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
723 if the tryents flag is set.
725 traceline (vector1, vector2, tryents)
728 void PF_traceline (void)
735 pr_xfunction->builtinsprofile += 30;
737 v1 = G_VECTOR(OFS_PARM0);
738 v2 = G_VECTOR(OFS_PARM1);
739 nomonsters = G_FLOAT(OFS_PARM2);
740 ent = G_EDICT(OFS_PARM3);
742 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
744 pr_global_struct->trace_allsolid = trace.allsolid;
745 pr_global_struct->trace_startsolid = trace.startsolid;
746 pr_global_struct->trace_fraction = trace.fraction;
747 pr_global_struct->trace_inwater = trace.inwater;
748 pr_global_struct->trace_inopen = trace.inopen;
749 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
750 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
751 pr_global_struct->trace_plane_dist = trace.plane.dist;
753 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
755 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
756 // FIXME: add trace_endcontents
764 Used for use tracing and shot targeting
765 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
766 if the tryents flag is set.
768 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
771 // LordHavoc: added this for my own use, VERY useful, similar to traceline
772 void PF_tracebox (void)
774 float *v1, *v2, *m1, *m2;
779 pr_xfunction->builtinsprofile += 30;
781 v1 = G_VECTOR(OFS_PARM0);
782 m1 = G_VECTOR(OFS_PARM1);
783 m2 = G_VECTOR(OFS_PARM2);
784 v2 = G_VECTOR(OFS_PARM3);
785 nomonsters = G_FLOAT(OFS_PARM4);
786 ent = G_EDICT(OFS_PARM5);
788 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
790 pr_global_struct->trace_allsolid = trace.allsolid;
791 pr_global_struct->trace_startsolid = trace.startsolid;
792 pr_global_struct->trace_fraction = trace.fraction;
793 pr_global_struct->trace_inwater = trace.inwater;
794 pr_global_struct->trace_inopen = trace.inopen;
795 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
796 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
797 pr_global_struct->trace_plane_dist = trace.plane.dist;
799 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
801 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
804 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
805 void PF_TraceToss (void)
811 pr_xfunction->builtinsprofile += 600;
813 ent = G_EDICT(OFS_PARM0);
814 if (ent == sv.edicts)
815 Host_Error("tracetoss: can not use world entity\n");
816 ignore = G_EDICT(OFS_PARM1);
818 trace = SV_Trace_Toss (ent, ignore);
820 pr_global_struct->trace_allsolid = trace.allsolid;
821 pr_global_struct->trace_startsolid = trace.startsolid;
822 pr_global_struct->trace_fraction = trace.fraction;
823 pr_global_struct->trace_inwater = trace.inwater;
824 pr_global_struct->trace_inopen = trace.inopen;
825 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
826 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
827 pr_global_struct->trace_plane_dist = trace.plane.dist;
829 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
831 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
839 Returns true if the given entity can move to the given position from it's
840 current position by walking or rolling.
842 scalar checkpos (entity, vector)
845 void PF_checkpos (void)
849 //============================================================================
852 qbyte checkpvs[MAX_MAP_LEAFS/8];
854 int PF_newcheckclient (int check)
860 // cycle to the next one
862 check = bound(1, check, svs.maxclients);
863 if (check == svs.maxclients)
871 pr_xfunction->builtinsprofile++;
873 if (i == svs.maxclients+1)
875 // look up the client's edict
877 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
878 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
880 // found a valid client (possibly the same one again)
884 // get the PVS for the entity
885 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
887 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
888 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
897 Returns a client (or object that has a client enemy) that would be a
900 If there is more than one valid option, they are cycled each frame
902 If (self.origin + self.viewofs) is not in the PVS of the current target,
903 it is not returned at all.
908 int c_invis, c_notvis;
909 void PF_checkclient (void)
914 // find a new check if on a new frame
915 if (sv.time - sv.lastchecktime >= 0.1)
917 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
918 sv.lastchecktime = sv.time;
921 // return check if it might be visible
922 ent = EDICT_NUM(sv.lastcheck);
923 if (ent->e->free || ent->v->health <= 0)
925 RETURN_EDICT(sv.edicts);
929 // if current entity can't possibly see the check entity, return 0
930 self = PROG_TO_EDICT(pr_global_struct->self);
931 VectorAdd(self->v->origin, self->v->view_ofs, view);
932 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
935 RETURN_EDICT(sv.edicts);
939 // might be able to see it
944 //============================================================================
951 Sends text over to the client's execution buffer
953 stuffcmd (clientent, value)
956 void PF_stuffcmd (void)
962 entnum = G_EDICTNUM(OFS_PARM0);
963 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
965 Con_Printf("Can't stuffcmd to a non-client");
968 str = G_STRING(OFS_PARM1);
971 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
972 Host_ClientCommands ("%s", str);
980 Sends text to server console
985 void PF_localcmd (void)
987 Cbuf_AddText(G_STRING(OFS_PARM0));
999 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1009 void PF_cvar_set (void)
1011 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1018 Returns a chain of entities that have origins within a spherical area
1020 findradius (origin, radius)
1023 void PF_findradius (void)
1025 edict_t *ent, *chain;
1032 chain = (edict_t *)sv.edicts;
1034 org = G_VECTOR(OFS_PARM0);
1035 radius = G_FLOAT(OFS_PARM1);
1036 radius2 = radius * radius;
1038 ent = NEXT_EDICT(sv.edicts);
1039 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1041 pr_xfunction->builtinsprofile++;
1044 if (ent->v->solid == SOLID_NOT)
1047 // LordHavoc: compare against bounding box rather than center,
1048 // and use DotProduct instead of Length, major speedup
1049 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1050 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1051 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1052 if (DotProduct(eorg, eorg) > radius2)
1055 ent->v->chain = EDICT_TO_PROG(chain);
1059 RETURN_EDICT(chain);
1068 void PF_dprint (void)
1070 char string[STRINGTEMP_LENGTH];
1071 if (developer.integer)
1073 PF_VarString(0, string, sizeof(string));
1074 Con_Printf("%s",string);
1082 v = G_FLOAT(OFS_PARM0);
1084 s = PR_GetTempString();
1085 if ((float)((int)v) == v)
1086 sprintf(s, "%i", (int)v);
1088 sprintf(s, "%f", v);
1089 G_INT(OFS_RETURN) = PR_SetString(s);
1095 v = G_FLOAT(OFS_PARM0);
1096 G_FLOAT(OFS_RETURN) = fabs(v);
1102 s = PR_GetTempString();
1103 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1104 G_INT(OFS_RETURN) = PR_SetString(s);
1110 s = PR_GetTempString();
1111 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1112 G_INT(OFS_RETURN) = PR_SetString(s);
1115 void PF_Spawn (void)
1118 pr_xfunction->builtinsprofile += 20;
1123 void PF_Remove (void)
1126 pr_xfunction->builtinsprofile += 20;
1128 ed = G_EDICT(OFS_PARM0);
1129 if (ed == sv.edicts)
1130 Host_Error("remove: tried to remove world\n");
1131 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1132 Host_Error("remove: tried to remove a client\n");
1133 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1134 if (ed->e->free && developer.integer)
1135 Con_Printf("remove: tried to remove an entity that was already removed\n");
1140 // entity (entity start, .string field, string match) find = #5;
1148 e = G_EDICTNUM(OFS_PARM0);
1149 f = G_INT(OFS_PARM1);
1150 s = G_STRING(OFS_PARM2);
1153 RETURN_EDICT(sv.edicts);
1157 for (e++ ; e < sv.num_edicts ; e++)
1159 pr_xfunction->builtinsprofile++;
1173 RETURN_EDICT(sv.edicts);
1176 // LordHavoc: added this for searching float, int, and entity reference fields
1177 void PF_FindFloat (void)
1184 e = G_EDICTNUM(OFS_PARM0);
1185 f = G_INT(OFS_PARM1);
1186 s = G_FLOAT(OFS_PARM2);
1188 for (e++ ; e < sv.num_edicts ; e++)
1190 pr_xfunction->builtinsprofile++;
1194 if (E_FLOAT(ed,f) == s)
1201 RETURN_EDICT(sv.edicts);
1204 // chained search for strings in entity fields
1205 // entity(.string field, string match) findchain = #402;
1206 void PF_findchain (void)
1211 edict_t *ent, *chain;
1213 chain = (edict_t *)sv.edicts;
1215 f = G_INT(OFS_PARM0);
1216 s = G_STRING(OFS_PARM1);
1219 RETURN_EDICT(sv.edicts);
1223 ent = NEXT_EDICT(sv.edicts);
1224 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1226 pr_xfunction->builtinsprofile++;
1229 t = E_STRING(ent,f);
1235 ent->v->chain = EDICT_TO_PROG(chain);
1239 RETURN_EDICT(chain);
1242 // LordHavoc: chained search for float, int, and entity reference fields
1243 // entity(.string field, float match) findchainfloat = #403;
1244 void PF_findchainfloat (void)
1249 edict_t *ent, *chain;
1251 chain = (edict_t *)sv.edicts;
1253 f = G_INT(OFS_PARM0);
1254 s = G_FLOAT(OFS_PARM1);
1256 ent = NEXT_EDICT(sv.edicts);
1257 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1259 pr_xfunction->builtinsprofile++;
1262 if (E_FLOAT(ent,f) != s)
1265 ent->v->chain = EDICT_TO_PROG(chain);
1269 RETURN_EDICT(chain);
1272 void PR_CheckEmptyString (char *s)
1275 Host_Error ("Bad string");
1278 void PF_precache_file (void)
1279 { // precache_file is only used to copy files with qcc, it does nothing
1280 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1283 void PF_precache_sound (void)
1288 if (sv.state != ss_loading)
1289 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1291 s = G_STRING(OFS_PARM0);
1292 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1293 PR_CheckEmptyString (s);
1295 for (i=0 ; i<MAX_SOUNDS ; i++)
1297 if (!sv.sound_precache[i])
1299 sv.sound_precache[i] = s;
1302 if (!strcmp(sv.sound_precache[i], s))
1305 Host_Error ("PF_precache_sound: overflow");
1308 void PF_precache_model (void)
1313 if (sv.state != ss_loading)
1314 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1316 s = G_STRING(OFS_PARM0);
1317 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1319 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1320 PR_CheckEmptyString (s);
1322 for (i=0 ; i<MAX_MODELS ; i++)
1324 if (!sv.model_precache[i])
1326 sv.model_precache[i] = s;
1327 sv.models[i] = Mod_ForName (s, true, false, false);
1330 if (!strcmp(sv.model_precache[i], s))
1333 Host_Error ("PF_precache_model: overflow");
1337 void PF_coredump (void)
1342 void PF_traceon (void)
1347 void PF_traceoff (void)
1352 void PF_eprint (void)
1354 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1361 float(float yaw, float dist) walkmove
1364 void PF_walkmove (void)
1372 ent = PROG_TO_EDICT(pr_global_struct->self);
1373 if (ent == sv.edicts)
1374 Host_Error("walkmove: can not modify world entity\n");
1376 Host_Error("walkmove: can not modify free entity\n");
1377 yaw = G_FLOAT(OFS_PARM0);
1378 dist = G_FLOAT(OFS_PARM1);
1380 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1382 G_FLOAT(OFS_RETURN) = 0;
1386 yaw = yaw*M_PI*2 / 360;
1388 move[0] = cos(yaw)*dist;
1389 move[1] = sin(yaw)*dist;
1392 // save program state, because SV_movestep may call other progs
1393 oldf = pr_xfunction;
1394 oldself = pr_global_struct->self;
1396 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1399 // restore program state
1400 pr_xfunction = oldf;
1401 pr_global_struct->self = oldself;
1411 void PF_droptofloor (void)
1417 ent = PROG_TO_EDICT(pr_global_struct->self);
1418 if (ent == sv.edicts)
1419 Host_Error("droptofloor: can not modify world entity\n");
1421 Host_Error("droptofloor: can not modify free entity\n");
1423 VectorCopy (ent->v->origin, end);
1426 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1428 if (trace.fraction == 1)
1429 G_FLOAT(OFS_RETURN) = 0;
1432 VectorCopy (trace.endpos, ent->v->origin);
1433 SV_LinkEdict (ent, false);
1434 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1435 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1436 G_FLOAT(OFS_RETURN) = 1;
1437 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1438 ent->e->suspendedinairflag = true;
1446 void(float style, string value) lightstyle
1449 void PF_lightstyle (void)
1456 style = G_FLOAT(OFS_PARM0);
1457 val = G_STRING(OFS_PARM1);
1459 // change the string in sv
1460 sv.lightstyles[style] = val;
1462 // send message to all clients on this server
1463 if (sv.state != ss_active)
1466 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1468 if (client->netconnection)
1470 MSG_WriteChar (&client->message, svc_lightstyle);
1471 MSG_WriteChar (&client->message,style);
1472 MSG_WriteString (&client->message, val);
1480 f = G_FLOAT(OFS_PARM0);
1482 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1484 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1486 void PF_floor (void)
1488 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1492 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1501 void PF_checkbottom (void)
1503 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1511 void PF_pointcontents (void)
1513 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1520 entity nextent(entity)
1523 void PF_nextent (void)
1528 i = G_EDICTNUM(OFS_PARM0);
1531 pr_xfunction->builtinsprofile++;
1533 if (i == sv.num_edicts)
1535 RETURN_EDICT(sv.edicts);
1551 Pick a vector for the player to shoot along
1552 vector aim(entity, missilespeed)
1557 edict_t *ent, *check, *bestent;
1558 vec3_t start, dir, end, bestdir;
1561 float dist, bestdist;
1564 ent = G_EDICT(OFS_PARM0);
1565 if (ent == sv.edicts)
1566 Host_Error("aim: can not use world entity\n");
1568 Host_Error("aim: can not use free entity\n");
1569 speed = G_FLOAT(OFS_PARM1);
1571 VectorCopy (ent->v->origin, start);
1574 // try sending a trace straight
1575 VectorCopy (pr_global_struct->v_forward, dir);
1576 VectorMA (start, 2048, dir, end);
1577 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1578 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1579 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1581 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1586 // try all possible entities
1587 VectorCopy (dir, bestdir);
1588 bestdist = sv_aim.value;
1591 check = NEXT_EDICT(sv.edicts);
1592 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1594 pr_xfunction->builtinsprofile++;
1595 if (check->v->takedamage != DAMAGE_AIM)
1599 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1600 continue; // don't aim at teammate
1601 for (j=0 ; j<3 ; j++)
1602 end[j] = check->v->origin[j]
1603 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1604 VectorSubtract (end, start, dir);
1605 VectorNormalize (dir);
1606 dist = DotProduct (dir, pr_global_struct->v_forward);
1607 if (dist < bestdist)
1608 continue; // to far to turn
1609 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1610 if (tr.ent == check)
1611 { // can shoot at this one
1619 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1620 dist = DotProduct (dir, pr_global_struct->v_forward);
1621 VectorScale (pr_global_struct->v_forward, dist, end);
1623 VectorNormalize (end);
1624 VectorCopy (end, G_VECTOR(OFS_RETURN));
1628 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1636 This was a major timewaster in progs, so it was converted to C
1639 void PF_changeyaw (void)
1642 float ideal, current, move, speed;
1644 ent = PROG_TO_EDICT(pr_global_struct->self);
1645 if (ent == sv.edicts)
1646 Host_Error("changeyaw: can not modify world entity\n");
1648 Host_Error("changeyaw: can not modify free entity\n");
1649 current = ANGLEMOD(ent->v->angles[1]);
1650 ideal = ent->v->ideal_yaw;
1651 speed = ent->v->yaw_speed;
1653 if (current == ideal)
1655 move = ideal - current;
1656 if (ideal > current)
1677 ent->v->angles[1] = ANGLEMOD (current + move);
1685 void PF_changepitch (void)
1688 float ideal, current, move, speed;
1691 ent = G_EDICT(OFS_PARM0);
1692 if (ent == sv.edicts)
1693 Host_Error("changepitch: can not modify world entity\n");
1695 Host_Error("changepitch: can not modify free entity\n");
1696 current = ANGLEMOD( ent->v->angles[0] );
1697 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1698 ideal = val->_float;
1701 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1704 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1705 speed = val->_float;
1708 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1712 if (current == ideal)
1714 move = ideal - current;
1715 if (ideal > current)
1736 ent->v->angles[0] = ANGLEMOD (current + move);
1740 ===============================================================================
1744 ===============================================================================
1747 #define MSG_BROADCAST 0 // unreliable to all
1748 #define MSG_ONE 1 // reliable to one (msg_entity)
1749 #define MSG_ALL 2 // reliable to all
1750 #define MSG_INIT 3 // write to the init string
1752 sizebuf_t *WriteDest (void)
1758 dest = G_FLOAT(OFS_PARM0);
1762 return &sv.datagram;
1765 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1766 entnum = NUM_FOR_EDICT(ent);
1767 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1768 Host_Error("WriteDest: tried to write to non-client\n");
1769 return &svs.clients[entnum-1].message;
1772 return &sv.reliable_datagram;
1778 Host_Error ("WriteDest: bad destination");
1785 void PF_WriteByte (void)
1787 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1790 void PF_WriteChar (void)
1792 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1795 void PF_WriteShort (void)
1797 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1800 void PF_WriteLong (void)
1802 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1805 void PF_WriteAngle (void)
1807 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1810 void PF_WriteCoord (void)
1812 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1815 void PF_WriteString (void)
1817 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1821 void PF_WriteEntity (void)
1823 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1826 //=============================================================================
1828 void PF_makestatic (void)
1833 ent = G_EDICT(OFS_PARM0);
1834 if (ent == sv.edicts)
1835 Host_Error("makestatic: can not modify world entity\n");
1837 Host_Error("makestatic: can not modify free entity\n");
1840 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1845 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1846 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1847 MSG_WriteShort (&sv.signon, ent->v->frame);
1851 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1852 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1853 MSG_WriteByte (&sv.signon, ent->v->frame);
1856 MSG_WriteByte (&sv.signon, ent->v->colormap);
1857 MSG_WriteByte (&sv.signon, ent->v->skin);
1858 for (i=0 ; i<3 ; i++)
1860 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1861 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1864 // throw the entity away now
1868 //=============================================================================
1875 void PF_setspawnparms (void)
1881 ent = G_EDICT(OFS_PARM0);
1882 i = NUM_FOR_EDICT(ent);
1883 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1885 Con_Printf("tried to setspawnparms on a non-client\n");
1889 // copy spawn parms out of the client_t
1890 client = svs.clients + i-1;
1891 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1892 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1900 void PF_changelevel (void)
1904 // make sure we don't issue two changelevels
1905 if (svs.changelevel_issued)
1907 svs.changelevel_issued = true;
1909 s = G_STRING(OFS_PARM0);
1910 Cbuf_AddText (va("changelevel %s\n",s));
1915 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1920 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1925 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1932 Returns a vector of length < 1
1937 void PF_randomvec (void)
1942 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1943 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1944 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1946 while (DotProduct(temp, temp) >= 1);
1947 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1954 Returns a color vector indicating the lighting at the requested point.
1956 (Internal Operation note: actually measures the light beneath the point, just like
1957 the model lighting on the client)
1962 void PF_GetLight (void)
1964 vec3_t ambientcolor, diffusecolor, diffusenormal;
1966 p = G_VECTOR(OFS_PARM0);
1967 VectorClear(ambientcolor);
1968 VectorClear(diffusecolor);
1969 VectorClear(diffusenormal);
1970 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1971 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1972 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1975 #define MAX_QC_CVARS 128
1976 cvar_t qc_cvar[MAX_QC_CVARS];
1979 void PF_registercvar (void)
1983 name = G_STRING(OFS_PARM0);
1984 value = G_STRING(OFS_PARM1);
1985 G_FLOAT(OFS_RETURN) = 0;
1986 // first check to see if it has already been defined
1987 if (Cvar_FindVar (name))
1990 // check for overlap with a command
1991 if (Cmd_Exists (name))
1993 Con_Printf ("PF_registercvar: %s is a command\n", name);
1997 if (currentqc_cvar >= MAX_QC_CVARS)
1998 Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
2000 // copy the name and value
2001 variable = &qc_cvar[currentqc_cvar++];
2002 variable->name = Z_Malloc (strlen(name)+1);
2003 strcpy (variable->name, name);
2004 variable->string = Z_Malloc (strlen(value)+1);
2005 strcpy (variable->string, value);
2006 variable->value = atof (value);
2008 Cvar_RegisterVariable(variable);
2009 G_FLOAT(OFS_RETURN) = 1; // success
2016 returns the minimum of two supplied floats
2023 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2025 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2026 else if (pr_argc >= 3)
2029 float f = G_FLOAT(OFS_PARM0);
2030 for (i = 1;i < pr_argc;i++)
2031 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2032 f = G_FLOAT((OFS_PARM0+i*3));
2033 G_FLOAT(OFS_RETURN) = f;
2036 Host_Error("min: must supply at least 2 floats\n");
2043 returns the maximum of two supplied floats
2050 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2052 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2053 else if (pr_argc >= 3)
2056 float f = G_FLOAT(OFS_PARM0);
2057 for (i = 1;i < pr_argc;i++)
2058 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2059 f = G_FLOAT((OFS_PARM0+i*3));
2060 G_FLOAT(OFS_RETURN) = f;
2063 Host_Error("max: must supply at least 2 floats\n");
2070 returns number bounded by supplied range
2072 min(min, value, max)
2075 void PF_bound (void)
2077 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2084 returns a raised to power b
2091 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2098 copies data from one entity to another
2100 copyentity(src, dst)
2103 void PF_copyentity (void)
2106 in = G_EDICT(OFS_PARM0);
2107 if (in == sv.edicts)
2108 Host_Error("copyentity: can not read world entity\n");
2110 Host_Error("copyentity: can not read free entity\n");
2111 out = G_EDICT(OFS_PARM1);
2112 if (out == sv.edicts)
2113 Host_Error("copyentity: can not modify world entity\n");
2115 Host_Error("copyentity: can not modify free entity\n");
2116 memcpy(out->v, in->v, progs->entityfields * 4);
2123 sets the color of a client and broadcasts the update to all connected clients
2125 setcolor(clientent, value)
2128 void PF_setcolor (void)
2134 entnum = G_EDICTNUM(OFS_PARM0);
2135 i = G_FLOAT(OFS_PARM1);
2137 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2139 Con_Printf ("tried to setcolor a non-client\n");
2143 client = svs.clients + entnum-1;
2144 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2147 client->old_colors = i;
2148 client->edict->v->team = (i & 15) + 1;
2150 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2151 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2152 MSG_WriteByte (&sv.reliable_datagram, i);
2159 effect(origin, modelname, startframe, framecount, framerate)
2162 void PF_effect (void)
2165 s = G_STRING(OFS_PARM1);
2167 Host_Error("effect: no model specified\n");
2169 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2172 void PF_te_blood (void)
2174 if (G_FLOAT(OFS_PARM2) < 1)
2176 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2179 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2180 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2181 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2183 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2184 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2185 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2187 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2190 void PF_te_bloodshower (void)
2192 if (G_FLOAT(OFS_PARM3) < 1)
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2197 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2199 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2201 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2202 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2203 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2205 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2207 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2210 void PF_te_explosionrgb (void)
2212 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2213 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2215 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2217 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2219 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2220 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2221 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2224 void PF_te_particlecube (void)
2226 if (G_FLOAT(OFS_PARM3) < 1)
2228 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2229 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2231 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2232 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2233 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2235 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2236 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2237 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2239 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2240 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2241 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2243 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2245 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2246 // gravity true/false
2247 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2249 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2252 void PF_te_particlerain (void)
2254 if (G_FLOAT(OFS_PARM3) < 1)
2256 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2257 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2260 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2261 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2263 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2264 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2265 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2267 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2268 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2269 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2271 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2273 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2276 void PF_te_particlesnow (void)
2278 if (G_FLOAT(OFS_PARM3) < 1)
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2285 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2287 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2288 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2289 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2291 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2292 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2293 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2295 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2297 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2300 void PF_te_spark (void)
2302 if (G_FLOAT(OFS_PARM2) < 1)
2304 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2305 MSG_WriteByte(&sv.datagram, TE_SPARK);
2307 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2308 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2309 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2311 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2312 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2313 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2315 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2318 void PF_te_gunshotquad (void)
2320 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2321 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2323 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2324 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2325 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2328 void PF_te_spikequad (void)
2330 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2331 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2333 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2334 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2335 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2338 void PF_te_superspikequad (void)
2340 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2341 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2343 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2344 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2345 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2348 void PF_te_explosionquad (void)
2350 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2351 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2353 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2354 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2355 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2358 void PF_te_smallflash (void)
2360 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2361 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2364 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2365 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2368 void PF_te_customflash (void)
2370 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2372 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2373 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2375 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2376 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2377 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2379 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2381 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2383 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2384 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2385 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2388 void PF_te_gunshot (void)
2390 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2391 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2393 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2394 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2395 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2398 void PF_te_spike (void)
2400 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2401 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2403 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2404 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2405 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2408 void PF_te_superspike (void)
2410 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2411 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2414 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2415 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2418 void PF_te_explosion (void)
2420 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2421 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2424 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2425 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2428 void PF_te_tarexplosion (void)
2430 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2431 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2434 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2435 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2438 void PF_te_wizspike (void)
2440 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2441 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2444 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2445 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2448 void PF_te_knightspike (void)
2450 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2451 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2453 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2454 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2458 void PF_te_lavasplash (void)
2460 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2461 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2463 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2464 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2465 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2468 void PF_te_teleport (void)
2470 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2471 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2474 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2475 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2478 void PF_te_explosion2 (void)
2480 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2481 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2483 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2484 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2485 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2487 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2490 void PF_te_lightning1 (void)
2492 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2493 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2495 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2497 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2498 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2499 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2501 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2506 void PF_te_lightning2 (void)
2508 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2509 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2511 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2515 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2518 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2519 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2522 void PF_te_lightning3 (void)
2524 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2525 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2527 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2529 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2531 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2534 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2535 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2538 void PF_te_beam (void)
2540 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2541 MSG_WriteByte(&sv.datagram, TE_BEAM);
2543 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2545 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2547 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2549 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2550 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2551 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2554 void PF_te_plasmaburn (void)
2556 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2557 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2558 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2559 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2560 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2563 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2566 vec3_t v1, clipplanenormal, normal;
2567 vec_t clipplanedist, clipdist;
2569 if (surf->flags & SURF_PLANEBACK)
2570 VectorNegate(surf->plane->normal, normal);
2572 VectorCopy(surf->plane->normal, normal);
2573 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2575 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2576 VectorNormalizeFast(v1);
2577 CrossProduct(v1, normal, clipplanenormal);
2578 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2579 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2582 clipdist = -clipdist;
2583 VectorMA(out, clipdist, clipplanenormal, out);
2588 static msurface_t *getsurface(edict_t *ed, int surfnum)
2592 if (!ed || ed->e->free)
2594 modelindex = ed->v->modelindex;
2595 if (modelindex < 1 || modelindex >= MAX_MODELS)
2597 model = sv.models[modelindex];
2598 if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
2600 return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2604 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2605 void PF_getsurfacenumpoints(void)
2608 // return 0 if no such surface
2609 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2611 G_FLOAT(OFS_RETURN) = 0;
2615 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2617 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2618 void PF_getsurfacepoint(void)
2623 VectorClear(G_VECTOR(OFS_RETURN));
2624 ed = G_EDICT(OFS_PARM0);
2625 if (!ed || ed->e->free)
2627 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2629 pointnum = G_FLOAT(OFS_PARM2);
2630 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2632 // FIXME: implement rotation/scaling
2633 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2635 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2636 void PF_getsurfacenormal(void)
2639 VectorClear(G_VECTOR(OFS_RETURN));
2640 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2642 // FIXME: implement rotation/scaling
2643 if (surf->flags & SURF_PLANEBACK)
2644 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2646 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2648 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2649 void PF_getsurfacetexture(void)
2652 G_INT(OFS_RETURN) = 0;
2653 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2655 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2657 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2658 void PF_getsurfacenearpoint(void)
2660 int surfnum, best, modelindex;
2662 vec_t dist, bestdist;
2667 G_FLOAT(OFS_RETURN) = -1;
2668 ed = G_EDICT(OFS_PARM0);
2669 point = G_VECTOR(OFS_PARM1);
2671 if (!ed || ed->e->free)
2673 modelindex = ed->v->modelindex;
2674 if (modelindex < 1 || modelindex >= MAX_MODELS)
2676 model = sv.models[modelindex];
2677 if (!model->brushq1.numsurfaces)
2680 // FIXME: implement rotation/scaling
2681 VectorSubtract(point, ed->v->origin, p);
2683 bestdist = 1000000000;
2684 for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++)
2686 surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2687 dist = PlaneDiff(p, surf->plane);
2689 if (dist < bestdist)
2691 clippointtosurface(surf, p, clipped);
2692 VectorSubtract(clipped, p, clipped);
2693 dist += DotProduct(clipped, clipped);
2694 if (dist < bestdist)
2701 G_FLOAT(OFS_RETURN) = best;
2703 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2704 void PF_getsurfaceclippedpoint(void)
2709 VectorClear(G_VECTOR(OFS_RETURN));
2710 ed = G_EDICT(OFS_PARM0);
2711 if (!ed || ed->e->free)
2713 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2715 // FIXME: implement rotation/scaling
2716 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2717 clippointtosurface(surf, p, out);
2718 // FIXME: implement rotation/scaling
2719 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2722 #define MAX_PRFILES 256
2724 qfile_t *pr_files[MAX_PRFILES];
2726 void PR_Files_Init(void)
2728 memset(pr_files, 0, sizeof(pr_files));
2731 void PR_Files_CloseAll(void)
2734 for (i = 0;i < MAX_PRFILES;i++)
2737 FS_Close(pr_files[i]);
2742 //float(string s) stof = #81; // get numerical value from a string
2745 char string[STRINGTEMP_LENGTH];
2746 PF_VarString(0, string, sizeof(string));
2747 G_FLOAT(OFS_RETURN) = atof(string);
2750 //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
2754 char *modestring, *filename;
2755 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2756 if (pr_files[filenum] == NULL)
2758 if (filenum >= MAX_PRFILES)
2760 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2761 G_FLOAT(OFS_RETURN) = -2;
2764 mode = G_FLOAT(OFS_PARM1);
2767 case 0: // FILE_READ
2770 case 1: // FILE_APPEND
2773 case 2: // FILE_WRITE
2777 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2778 G_FLOAT(OFS_RETURN) = -3;
2781 filename = G_STRING(OFS_PARM0);
2782 // .. is parent directory on many platforms
2783 // / is parent directory on Amiga
2784 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2785 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2786 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2788 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2789 G_FLOAT(OFS_RETURN) = -4;
2792 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2793 if (pr_files[filenum] == NULL)
2794 G_FLOAT(OFS_RETURN) = -1;
2796 G_FLOAT(OFS_RETURN) = filenum;
2799 //void(float fhandle) fclose = #111; // closes a file
2800 void PF_fclose(void)
2802 int filenum = G_FLOAT(OFS_PARM0);
2803 if (filenum < 0 || filenum >= MAX_PRFILES)
2805 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2808 if (pr_files[filenum] == NULL)
2810 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2813 FS_Close(pr_files[filenum]);
2814 pr_files[filenum] = NULL;
2817 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2821 static char string[STRINGTEMP_LENGTH];
2822 int filenum = G_FLOAT(OFS_PARM0);
2823 if (filenum < 0 || filenum >= MAX_PRFILES)
2825 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2828 if (pr_files[filenum] == NULL)
2830 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2836 c = FS_Getc(pr_files[filenum]);
2837 if (c == '\r' || c == '\n' || c < 0)
2839 if (end < STRINGTEMP_LENGTH - 1)
2843 // remove \n following \r
2845 c = FS_Getc(pr_files[filenum]);
2846 if (developer.integer)
2847 Con_Printf("fgets: %s\n", string);
2849 G_INT(OFS_RETURN) = PR_SetString(string);
2851 G_INT(OFS_RETURN) = 0;
2854 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2858 char string[STRINGTEMP_LENGTH];
2859 int filenum = G_FLOAT(OFS_PARM0);
2860 if (filenum < 0 || filenum >= MAX_PRFILES)
2862 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2865 if (pr_files[filenum] == NULL)
2867 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2870 PF_VarString(1, string, sizeof(string));
2871 if ((stringlength = strlen(string)))
2872 FS_Write(pr_files[filenum], string, stringlength);
2873 if (developer.integer)
2874 Con_Printf("fputs: %s\n", string);
2877 //float(string s) strlen = #114; // returns how many characters are in a string
2878 void PF_strlen(void)
2881 s = G_STRING(OFS_PARM0);
2883 G_FLOAT(OFS_RETURN) = strlen(s);
2885 G_FLOAT(OFS_RETURN) = 0;
2888 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2889 void PF_strcat(void)
2891 char *s = PR_GetTempString();
2892 PF_VarString(0, s, STRINGTEMP_LENGTH);
2893 G_INT(OFS_RETURN) = PR_SetString(s);
2896 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2897 void PF_substring(void)
2899 int i, start, length;
2900 char *s, *string = PR_GetTempString();
2901 s = G_STRING(OFS_PARM0);
2902 start = G_FLOAT(OFS_PARM1);
2903 length = G_FLOAT(OFS_PARM2);
2906 for (i = 0;i < start && *s;i++, s++);
2907 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2910 G_INT(OFS_RETURN) = PR_SetString(string);
2913 //vector(string s) stov = #117; // returns vector value from a string
2916 char string[STRINGTEMP_LENGTH];
2917 PF_VarString(0, string, sizeof(string));
2918 Math_atov(string, G_VECTOR(OFS_RETURN));
2921 //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)
2922 void PF_strzone(void)
2925 in = G_STRING(OFS_PARM0);
2926 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2928 G_INT(OFS_RETURN) = PR_SetString(out);
2931 //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!!!)
2932 void PF_strunzone(void)
2934 Mem_Free(G_STRING(OFS_PARM0));
2937 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2938 //this function originally written by KrimZon, made shorter by LordHavoc
2939 void PF_clientcommand (void)
2941 client_t *temp_client;
2944 //find client for this entity
2945 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2946 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2948 Con_Printf("PF_clientcommand: entity is not a client");
2952 temp_client = host_client;
2953 host_client = svs.clients + i;
2954 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2955 host_client = temp_client;
2958 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2959 //this function originally written by KrimZon, made shorter by LordHavoc
2960 char **tokens = NULL;
2961 int max_tokens, num_tokens = 0;
2962 void PF_tokenize (void)
2966 str = G_STRING(OFS_PARM0);
2971 for (i=0;i<num_tokens;i++)
2977 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2978 max_tokens = strlen(str);
2980 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2982 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2983 strcpy(tokens[num_tokens], com_token);
2986 G_FLOAT(OFS_RETURN) = num_tokens;
2989 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
2990 //this function originally written by KrimZon, made shorter by LordHavoc
2993 int token_num = G_FLOAT(OFS_PARM0);
2994 if (token_num >= 0 && token_num < num_tokens)
2995 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
2997 G_INT(OFS_RETURN) = PR_SetString("");
3000 //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)
3001 void PF_setattachment (void)
3003 edict_t *e = G_EDICT(OFS_PARM0);
3004 edict_t *tagentity = G_EDICT(OFS_PARM1);
3005 char *tagname = G_STRING(OFS_PARM2);
3011 Host_Error("setattachment: can not modify world entity\n");
3013 Host_Error("setattachment: can not modify free entity\n");
3015 if (tagentity == NULL)
3016 tagentity = sv.edicts;
3018 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3020 v->edict = EDICT_TO_PROG(tagentity);
3022 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3025 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3027 modelindex = (int)tagentity->v->modelindex;
3028 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3030 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3031 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3032 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3034 if (v->_float == 0 && model->alias.aliasnum_tags)
3035 for (i = 0;i < model->alias.aliasnum_tags;i++)
3036 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3039 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);
3042 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));
3047 /////////////////////////////////////////
3048 // DP_QC_FS_SEARCH extension
3050 // qc fs search handling
3051 #define MAX_SEARCHES 128
3053 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3055 void PR_Search_Init(void)
3057 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3060 void PR_Search_Reset(void)
3063 // reset the fssearch list
3064 for(i = 0; i < MAX_SEARCHES; i++)
3065 if(pr_fssearchlist[i])
3066 FS_FreeSearch(pr_fssearchlist[i]);
3067 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3074 float search_begin(string pattern, float caseinsensitive, float quiet)
3077 void PF_search_begin(void)
3081 int caseinsens, quiet;
3083 pattern = G_STRING(OFS_PARM0);
3085 PR_CheckEmptyString(pattern);
3087 caseinsens = G_FLOAT(OFS_PARM1);
3088 quiet = G_FLOAT(OFS_PARM2);
3090 for(handle = 0; handle < MAX_SEARCHES; handle++)
3091 if(!pr_fssearchlist[handle])
3094 if(handle >= MAX_SEARCHES)
3096 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3097 G_FLOAT(OFS_RETURN) = -2;
3101 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3102 G_FLOAT(OFS_RETURN) = -1;
3104 G_FLOAT(OFS_RETURN) = handle;
3111 void search_end(float handle)
3114 void PF_search_end(void)
3118 handle = G_FLOAT(OFS_PARM0);
3120 if(handle < 0 || handle >= MAX_SEARCHES)
3122 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3125 if(pr_fssearchlist[handle] == NULL)
3127 Con_Printf("PF_search_end: no such handle %i\n", handle);
3131 FS_FreeSearch(pr_fssearchlist[handle]);
3132 pr_fssearchlist[handle] = NULL;
3139 float search_getsize(float handle)
3142 void PF_search_getsize(void)
3146 handle = G_FLOAT(OFS_PARM0);
3148 if(handle < 0 || handle >= MAX_SEARCHES)
3150 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3153 if(pr_fssearchlist[handle] == NULL)
3155 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3159 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3164 VM_search_getfilename
3166 string search_getfilename(float handle, float num)
3169 void PF_search_getfilename(void)
3171 int handle, filenum;
3174 handle = G_FLOAT(OFS_PARM0);
3175 filenum = G_FLOAT(OFS_PARM1);
3177 if(handle < 0 || handle >= MAX_SEARCHES)
3179 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3182 if(pr_fssearchlist[handle] == NULL)
3184 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3187 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3189 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3193 tmp = PR_GetTempString();
3194 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3196 G_INT(OFS_RETURN) = PR_SetString(tmp);
3199 void PF_cvar_string (void)
3205 str = G_STRING(OFS_PARM0);
3206 var = Cvar_FindVar (str);
3208 tmp = PR_GetTempString();
3209 strcpy(tmp, var->string);
3211 G_INT(OFS_RETURN) = PR_SetString(tmp);
3216 builtin_t pr_builtin[] =
3219 PF_makevectors, // #1 void(entity e) makevectors
3220 PF_setorigin, // #2 void(entity e, vector o) setorigin
3221 PF_setmodel, // #3 void(entity e, string m) setmodel
3222 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3223 NULL, // #5 void(entity e, vector min, vector max) setabssize
3224 PF_break, // #6 void() break
3225 PF_random, // #7 float() random
3226 PF_sound, // #8 void(entity e, float chan, string samp) sound
3227 PF_normalize, // #9 vector(vector v) normalize
3228 PF_error, // #10 void(string e) error
3229 PF_objerror, // #11 void(string e) objerror
3230 PF_vlen, // #12 float(vector v) vlen
3231 PF_vectoyaw, // #13 float(vector v) vectoyaw
3232 PF_Spawn, // #14 entity() spawn
3233 PF_Remove, // #15 void(entity e) remove
3234 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3235 PF_checkclient, // #17 entity() clientlist
3236 PF_Find, // #18 entity(entity start, .string fld, string match) find
3237 PF_precache_sound, // #19 void(string s) precache_sound
3238 PF_precache_model, // #20 void(string s) precache_model
3239 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3240 PF_findradius, // #22 entity(vector org, float rad) findradius
3241 PF_bprint, // #23 void(string s) bprint
3242 PF_sprint, // #24 void(entity client, string s) sprint
3243 PF_dprint, // #25 void(string s) dprint
3244 PF_ftos, // #26 void(string s) ftos
3245 PF_vtos, // #27 void(string s) vtos
3246 PF_coredump, // #28 void() coredump
3247 PF_traceon, // #29 void() traceon
3248 PF_traceoff, // #30 void() traceoff
3249 PF_eprint, // #31 void(entity e) eprint
3250 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3252 PF_droptofloor, // #34 float() droptofloor
3253 PF_lightstyle, // #35 void(float style, string value) lightstyle
3254 PF_rint, // #36 float(float v) rint
3255 PF_floor, // #37 float(float v) floor
3256 PF_ceil, // #38 float(float v) ceil
3258 PF_checkbottom, // #40 float(entity e) checkbottom
3259 PF_pointcontents , // #41 float(vector v) pointcontents
3261 PF_fabs, // #43 float(float f) fabs
3262 PF_aim, // #44 vector(entity e, float speed) aim
3263 PF_cvar, // #45 float(string s) cvar
3264 PF_localcmd, // #46 void(string s) localcmd
3265 PF_nextent, // #47 entity(entity e) nextent
3266 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3267 PF_changeyaw, // #49 void() ChangeYaw
3269 PF_vectoangles, // #51 vector(vector v) vectoangles
3270 PF_WriteByte, // #52 void(float to, float f) WriteByte
3271 PF_WriteChar, // #53 void(float to, float f) WriteChar
3272 PF_WriteShort, // #54 void(float to, float f) WriteShort
3273 PF_WriteLong, // #55 void(float to, float f) WriteLong
3274 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3275 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3276 PF_WriteString, // #58 void(float to, string s) WriteString
3277 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3278 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3279 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3280 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3281 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3282 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3283 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3285 SV_MoveToGoal, // #67 void(float step) movetogoal
3286 PF_precache_file, // #68 string(string s) precache_file
3287 PF_makestatic, // #69 void(entity e) makestatic
3288 PF_changelevel, // #70 void(string s) changelevel
3290 PF_cvar_set, // #72 void(string var, string val) cvar_set
3291 PF_centerprint, // #73 void(entity client, strings) centerprint
3292 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3293 PF_precache_model, // #75 string(string s) precache_model2
3294 PF_precache_sound, // #76 string(string s) precache_sound2
3295 PF_precache_file, // #77 string(string s) precache_file2
3296 PF_setspawnparms, // #78 void(entity e) setspawnparms
3299 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3308 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3309 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3310 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3311 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3312 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3313 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3314 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3315 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3316 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3317 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3328 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3329 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3330 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3331 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3332 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3333 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3334 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3335 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3336 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3337 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3338 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3339 a a a a a a a a // #120-199
3340 a a a a a a a a a a // #200-299
3341 a a a a a a a a a a // #300-399
3342 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3343 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3344 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3345 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3346 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3347 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3348 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3349 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3350 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3351 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3352 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3353 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3354 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3355 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3356 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3357 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3358 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3359 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3360 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3361 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3362 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3363 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3364 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3365 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3366 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3367 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3368 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3369 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3370 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3371 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3372 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3373 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3374 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3375 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3376 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3377 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3378 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3379 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3380 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3381 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3382 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3383 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3384 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3385 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3386 PF_search_begin, // #444
3387 PF_search_end, // #445
3388 PF_search_getsize, // #446
3389 PF_search_getfilename, // #447
3390 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3392 a a a a a // #450-499 (LordHavoc)
3395 builtin_t *pr_builtins = pr_builtin;
3396 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3398 void PR_Cmd_Init(void)
3400 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3405 void PR_Cmd_Reset(void)
3407 Mem_EmptyPool(pr_strings_mempool);
3409 PR_Files_CloseAll();