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 "
82 "DP_ENT_LOWPRECISION "
86 "DP_GFX_EXTERNALTEXTURES "
88 "DP_GFX_QUAKE3MODELTAGS "
92 "DP_HALFLIFE_MAP_CVAR "
96 "DP_MOVETYPEBOUNCEMISSILE "
102 "DP_QC_FINDCHAINFLOAT "
108 "DP_QC_SINCOSSQRTPOW "
111 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
112 "DP_QC_TRACE_MOVETYPE_HITMODEL "
113 "DP_QC_VECTORVECTORS "
119 "DP_SV_DRAWONLYTOCLIENT "
121 "DP_SV_EXTERIORMODELTOCLIENT "
122 "DP_SV_NODRAWTOCLIENT "
123 "DP_SV_PLAYERPHYSICS "
129 "DP_TE_EXPLOSIONRGB "
131 "DP_TE_PARTICLECUBE "
132 "DP_TE_PARTICLERAIN "
133 "DP_TE_PARTICLESNOW "
135 "DP_TE_QUADEFFECTS1 "
138 "DP_TE_STANDARDEFFECTBUILTINS "
141 "KRIMZON_SV_PARSECLIENTCOMMAND "
145 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
148 qboolean checkextension(char *name)
153 for (e = ENGINE_EXTENSIONS;*e;e++)
160 while (*e && *e != ' ')
162 if (e - start == len)
163 if (!strncasecmp(start, name, len))
173 returns true if the extension is supported by the server
175 checkextension(extensionname)
178 void PF_checkextension (void)
180 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
187 This is a TERMINAL error, which will kill off the entire server.
196 char string[STRINGTEMP_LENGTH];
198 PF_VarString(0, string, sizeof(string));
199 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
200 ed = PROG_TO_EDICT(pr_global_struct->self);
203 Host_Error ("Program error");
210 Dumps out self, then an error message. The program is aborted and self is
211 removed, but the level can continue.
216 void PF_objerror (void)
219 char string[STRINGTEMP_LENGTH];
221 PF_VarString(0, string, sizeof(string));
222 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
223 ed = PROG_TO_EDICT(pr_global_struct->self);
233 Writes new values for v_forward, v_up, and v_right based on angles
237 void PF_makevectors (void)
239 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
246 Writes new values for v_forward, v_up, and v_right based on the given forward vector
247 vectorvectors(vector, vector)
250 void PF_vectorvectors (void)
252 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
253 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
260 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.
262 setorigin (entity, origin)
265 void PF_setorigin (void)
270 e = G_EDICT(OFS_PARM0);
272 Host_Error("setorigin: can not modify world entity\n");
274 Host_Error("setorigin: can not modify free entity\n");
275 org = G_VECTOR(OFS_PARM1);
276 VectorCopy (org, e->v->origin);
277 SV_LinkEdict (e, false);
281 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
285 for (i=0 ; i<3 ; i++)
287 Host_Error ("backwards mins/maxs");
289 // set derived values
290 VectorCopy (min, e->v->mins);
291 VectorCopy (max, e->v->maxs);
292 VectorSubtract (max, min, e->v->size);
294 SV_LinkEdict (e, false);
301 the size box is rotated by the current angle
302 LordHavoc: no it isn't...
304 setsize (entity, minvector, maxvector)
307 void PF_setsize (void)
312 e = G_EDICT(OFS_PARM0);
314 Host_Error("setsize: can not modify world entity\n");
316 Host_Error("setsize: can not modify free entity\n");
317 min = G_VECTOR(OFS_PARM1);
318 max = G_VECTOR(OFS_PARM2);
319 SetMinMaxSize (e, min, max, false);
327 setmodel(entity, model)
330 void PF_setmodel (void)
337 e = G_EDICT(OFS_PARM0);
339 Host_Error("setmodel: can not modify world entity\n");
341 Host_Error("setmodel: can not modify free entity\n");
342 m = G_STRING(OFS_PARM1);
344 // check to see if model was properly precached
345 for (i=0, check = sv.model_precache ; *check ; i++, check++)
346 if (!strcmp(*check, m))
350 Host_Error ("no precache: %s\n", m);
353 e->v->model = PR_SetString(*check);
354 e->v->modelindex = i;
356 mod = sv.models[ (int)e->v->modelindex];
359 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
361 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
368 broadcast print to everyone on server
373 void PF_bprint (void)
375 char string[STRINGTEMP_LENGTH];
376 PF_VarString(0, string, sizeof(string));
377 SV_BroadcastPrintf("%s", string);
384 single print to a specific client
386 sprint(clientent, value)
389 void PF_sprint (void)
393 char string[STRINGTEMP_LENGTH];
395 entnum = G_EDICTNUM(OFS_PARM0);
397 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
399 Con_Printf ("tried to sprint to a non-client\n");
403 client = svs.clients + entnum-1;
404 if (!client->netconnection)
406 PF_VarString(1, string, sizeof(string));
407 MSG_WriteChar(&client->message,svc_print);
408 MSG_WriteString(&client->message, string);
416 single print to a specific client
418 centerprint(clientent, value)
421 void PF_centerprint (void)
425 char string[STRINGTEMP_LENGTH];
427 entnum = G_EDICTNUM(OFS_PARM0);
429 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
431 Con_Printf ("tried to sprint to a non-client\n");
435 client = svs.clients + entnum-1;
436 if (!client->netconnection)
438 PF_VarString(1, string, sizeof(string));
439 MSG_WriteChar(&client->message,svc_centerprint);
440 MSG_WriteString(&client->message, string);
448 vector normalize(vector)
451 void PF_normalize (void)
457 value1 = G_VECTOR(OFS_PARM0);
459 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
463 newvalue[0] = newvalue[1] = newvalue[2] = 0;
467 newvalue[0] = value1[0] * new;
468 newvalue[1] = value1[1] * new;
469 newvalue[2] = value1[2] * new;
472 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
487 value1 = G_VECTOR(OFS_PARM0);
489 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
492 G_FLOAT(OFS_RETURN) = new;
499 float vectoyaw(vector)
502 void PF_vectoyaw (void)
507 value1 = G_VECTOR(OFS_PARM0);
509 if (value1[1] == 0 && value1[0] == 0)
513 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
518 G_FLOAT(OFS_RETURN) = yaw;
526 vector vectoangles(vector)
529 void PF_vectoangles (void)
535 value1 = G_VECTOR(OFS_PARM0);
537 if (value1[1] == 0 && value1[0] == 0)
547 // LordHavoc: optimized a bit
550 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
554 else if (value1[1] > 0)
559 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
560 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
565 G_FLOAT(OFS_RETURN+0) = pitch;
566 G_FLOAT(OFS_RETURN+1) = yaw;
567 G_FLOAT(OFS_RETURN+2) = 0;
574 Returns a number from 0<= num < 1
579 void PF_random (void)
583 num = (rand ()&0x7fff) / ((float)0x7fff);
585 G_FLOAT(OFS_RETURN) = num;
592 particle(origin, color, count)
595 void PF_particle (void)
601 org = G_VECTOR(OFS_PARM0);
602 dir = G_VECTOR(OFS_PARM1);
603 color = G_FLOAT(OFS_PARM2);
604 count = G_FLOAT(OFS_PARM3);
605 SV_StartParticle (org, dir, color, count);
615 void PF_ambientsound (void)
620 float vol, attenuation;
621 int i, soundnum, large;
623 pos = G_VECTOR (OFS_PARM0);
624 samp = G_STRING(OFS_PARM1);
625 vol = G_FLOAT(OFS_PARM2);
626 attenuation = G_FLOAT(OFS_PARM3);
628 // check to see if samp was properly precached
629 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
630 if (!strcmp(*check,samp))
635 Con_Printf ("no precache: %s\n", samp);
643 // add an svc_spawnambient command to the level signon packet
646 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
648 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
650 for (i=0 ; i<3 ; i++)
651 MSG_WriteDPCoord(&sv.signon, pos[i]);
654 MSG_WriteShort (&sv.signon, soundnum);
656 MSG_WriteByte (&sv.signon, soundnum);
658 MSG_WriteByte (&sv.signon, vol*255);
659 MSG_WriteByte (&sv.signon, attenuation*64);
667 Each entity can have eight independant sound sources, like voice,
670 Channel 0 is an auto-allocate channel, the others override anything
671 already running on that entity/channel pair.
673 An attenuation of 0 will play full volume everywhere in the level.
674 Larger attenuations will drop off.
686 entity = G_EDICT(OFS_PARM0);
687 channel = G_FLOAT(OFS_PARM1);
688 sample = G_STRING(OFS_PARM2);
689 volume = G_FLOAT(OFS_PARM3) * 255;
690 attenuation = G_FLOAT(OFS_PARM4);
692 if (volume < 0 || volume > 255)
693 Host_Error ("SV_StartSound: volume = %i", volume);
695 if (attenuation < 0 || attenuation > 4)
696 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
698 if (channel < 0 || channel > 7)
699 Host_Error ("SV_StartSound: channel = %i", channel);
701 SV_StartSound (entity, channel, sample, volume, attenuation);
713 Host_Error ("break statement");
720 Used for use tracing and shot targeting
721 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
722 if the tryents flag is set.
724 traceline (vector1, vector2, tryents)
727 void PF_traceline (void)
734 pr_xfunction->builtinsprofile += 30;
736 v1 = G_VECTOR(OFS_PARM0);
737 v2 = G_VECTOR(OFS_PARM1);
738 nomonsters = G_FLOAT(OFS_PARM2);
739 ent = G_EDICT(OFS_PARM3);
741 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
743 pr_global_struct->trace_allsolid = trace.allsolid;
744 pr_global_struct->trace_startsolid = trace.startsolid;
745 pr_global_struct->trace_fraction = trace.fraction;
746 pr_global_struct->trace_inwater = trace.inwater;
747 pr_global_struct->trace_inopen = trace.inopen;
748 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
749 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
750 pr_global_struct->trace_plane_dist = trace.plane.dist;
752 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
754 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
755 // FIXME: add trace_endcontents
763 Used for use tracing and shot targeting
764 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
765 if the tryents flag is set.
767 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
770 // LordHavoc: added this for my own use, VERY useful, similar to traceline
771 void PF_tracebox (void)
773 float *v1, *v2, *m1, *m2;
778 pr_xfunction->builtinsprofile += 30;
780 v1 = G_VECTOR(OFS_PARM0);
781 m1 = G_VECTOR(OFS_PARM1);
782 m2 = G_VECTOR(OFS_PARM2);
783 v2 = G_VECTOR(OFS_PARM3);
784 nomonsters = G_FLOAT(OFS_PARM4);
785 ent = G_EDICT(OFS_PARM5);
787 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
789 pr_global_struct->trace_allsolid = trace.allsolid;
790 pr_global_struct->trace_startsolid = trace.startsolid;
791 pr_global_struct->trace_fraction = trace.fraction;
792 pr_global_struct->trace_inwater = trace.inwater;
793 pr_global_struct->trace_inopen = trace.inopen;
794 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
795 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
796 pr_global_struct->trace_plane_dist = trace.plane.dist;
798 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
800 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
803 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
804 void PF_TraceToss (void)
810 pr_xfunction->builtinsprofile += 600;
812 ent = G_EDICT(OFS_PARM0);
813 if (ent == sv.edicts)
814 Host_Error("tracetoss: can not use world entity\n");
815 ignore = G_EDICT(OFS_PARM1);
817 trace = SV_Trace_Toss (ent, ignore);
819 pr_global_struct->trace_allsolid = trace.allsolid;
820 pr_global_struct->trace_startsolid = trace.startsolid;
821 pr_global_struct->trace_fraction = trace.fraction;
822 pr_global_struct->trace_inwater = trace.inwater;
823 pr_global_struct->trace_inopen = trace.inopen;
824 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
825 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
826 pr_global_struct->trace_plane_dist = trace.plane.dist;
828 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
830 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
838 Returns true if the given entity can move to the given position from it's
839 current position by walking or rolling.
841 scalar checkpos (entity, vector)
844 void PF_checkpos (void)
848 //============================================================================
851 qbyte checkpvs[MAX_MAP_LEAFS/8];
853 int PF_newcheckclient (int check)
859 // cycle to the next one
861 check = bound(1, check, svs.maxclients);
862 if (check == svs.maxclients)
870 pr_xfunction->builtinsprofile++;
872 if (i == svs.maxclients+1)
874 // look up the client's edict
876 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
877 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
879 // found a valid client (possibly the same one again)
883 // get the PVS for the entity
884 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
886 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
887 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
896 Returns a client (or object that has a client enemy) that would be a
899 If there is more than one valid option, they are cycled each frame
901 If (self.origin + self.viewofs) is not in the PVS of the current target,
902 it is not returned at all.
907 int c_invis, c_notvis;
908 void PF_checkclient (void)
913 // find a new check if on a new frame
914 if (sv.time - sv.lastchecktime >= 0.1)
916 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
917 sv.lastchecktime = sv.time;
920 // return check if it might be visible
921 ent = EDICT_NUM(sv.lastcheck);
922 if (ent->e->free || ent->v->health <= 0)
924 RETURN_EDICT(sv.edicts);
928 // if current entity can't possibly see the check entity, return 0
929 self = PROG_TO_EDICT(pr_global_struct->self);
930 VectorAdd(self->v->origin, self->v->view_ofs, view);
931 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
934 RETURN_EDICT(sv.edicts);
938 // might be able to see it
943 //============================================================================
950 Sends text over to the client's execution buffer
952 stuffcmd (clientent, value)
955 void PF_stuffcmd (void)
961 entnum = G_EDICTNUM(OFS_PARM0);
962 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
964 Con_Printf("Can't stuffcmd to a non-client");
967 str = G_STRING(OFS_PARM1);
970 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
971 Host_ClientCommands ("%s", str);
979 Sends text to server console
984 void PF_localcmd (void)
986 Cbuf_AddText(G_STRING(OFS_PARM0));
998 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1008 void PF_cvar_set (void)
1010 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1017 Returns a chain of entities that have origins within a spherical area
1019 findradius (origin, radius)
1022 void PF_findradius (void)
1024 edict_t *ent, *chain;
1031 chain = (edict_t *)sv.edicts;
1033 org = G_VECTOR(OFS_PARM0);
1034 radius = G_FLOAT(OFS_PARM1);
1035 radius2 = radius * radius;
1037 ent = NEXT_EDICT(sv.edicts);
1038 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1040 pr_xfunction->builtinsprofile++;
1043 if (ent->v->solid == SOLID_NOT)
1046 // LordHavoc: compare against bounding box rather than center,
1047 // and use DotProduct instead of Length, major speedup
1048 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1049 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1050 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1051 if (DotProduct(eorg, eorg) > radius2)
1054 ent->v->chain = EDICT_TO_PROG(chain);
1058 RETURN_EDICT(chain);
1067 void PF_dprint (void)
1069 char string[STRINGTEMP_LENGTH];
1070 if (developer.integer)
1072 PF_VarString(0, string, sizeof(string));
1073 Con_Printf("%s",string);
1081 v = G_FLOAT(OFS_PARM0);
1083 s = PR_GetTempString();
1084 if ((float)((int)v) == v)
1085 sprintf(s, "%i", (int)v);
1087 sprintf(s, "%f", v);
1088 G_INT(OFS_RETURN) = PR_SetString(s);
1094 v = G_FLOAT(OFS_PARM0);
1095 G_FLOAT(OFS_RETURN) = fabs(v);
1101 s = PR_GetTempString();
1102 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1103 G_INT(OFS_RETURN) = PR_SetString(s);
1109 s = PR_GetTempString();
1110 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1111 G_INT(OFS_RETURN) = PR_SetString(s);
1114 void PF_Spawn (void)
1117 pr_xfunction->builtinsprofile += 20;
1122 void PF_Remove (void)
1125 pr_xfunction->builtinsprofile += 20;
1127 ed = G_EDICT(OFS_PARM0);
1128 if (ed == sv.edicts)
1129 Host_Error("remove: tried to remove world\n");
1130 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1131 Host_Error("remove: tried to remove a client\n");
1132 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1133 if (ed->e->free && developer.integer)
1134 Con_Printf("remove: tried to remove an entity that was already removed\n");
1139 // entity (entity start, .string field, string match) find = #5;
1147 e = G_EDICTNUM(OFS_PARM0);
1148 f = G_INT(OFS_PARM1);
1149 s = G_STRING(OFS_PARM2);
1152 RETURN_EDICT(sv.edicts);
1156 for (e++ ; e < sv.num_edicts ; e++)
1158 pr_xfunction->builtinsprofile++;
1172 RETURN_EDICT(sv.edicts);
1175 // LordHavoc: added this for searching float, int, and entity reference fields
1176 void PF_FindFloat (void)
1183 e = G_EDICTNUM(OFS_PARM0);
1184 f = G_INT(OFS_PARM1);
1185 s = G_FLOAT(OFS_PARM2);
1187 for (e++ ; e < sv.num_edicts ; e++)
1189 pr_xfunction->builtinsprofile++;
1193 if (E_FLOAT(ed,f) == s)
1200 RETURN_EDICT(sv.edicts);
1203 // chained search for strings in entity fields
1204 // entity(.string field, string match) findchain = #402;
1205 void PF_findchain (void)
1210 edict_t *ent, *chain;
1212 chain = (edict_t *)sv.edicts;
1214 f = G_INT(OFS_PARM0);
1215 s = G_STRING(OFS_PARM1);
1218 RETURN_EDICT(sv.edicts);
1222 ent = NEXT_EDICT(sv.edicts);
1223 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1225 pr_xfunction->builtinsprofile++;
1228 t = E_STRING(ent,f);
1234 ent->v->chain = EDICT_TO_PROG(chain);
1238 RETURN_EDICT(chain);
1241 // LordHavoc: chained search for float, int, and entity reference fields
1242 // entity(.string field, float match) findchainfloat = #403;
1243 void PF_findchainfloat (void)
1248 edict_t *ent, *chain;
1250 chain = (edict_t *)sv.edicts;
1252 f = G_INT(OFS_PARM0);
1253 s = G_FLOAT(OFS_PARM1);
1255 ent = NEXT_EDICT(sv.edicts);
1256 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1258 pr_xfunction->builtinsprofile++;
1261 if (E_FLOAT(ent,f) != s)
1264 ent->v->chain = EDICT_TO_PROG(chain);
1268 RETURN_EDICT(chain);
1271 void PR_CheckEmptyString (char *s)
1274 Host_Error ("Bad string");
1277 void PF_precache_file (void)
1278 { // precache_file is only used to copy files with qcc, it does nothing
1279 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1282 void PF_precache_sound (void)
1287 if (sv.state != ss_loading)
1288 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1290 s = G_STRING(OFS_PARM0);
1291 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1292 PR_CheckEmptyString (s);
1294 for (i=0 ; i<MAX_SOUNDS ; i++)
1296 if (!sv.sound_precache[i])
1298 sv.sound_precache[i] = s;
1301 if (!strcmp(sv.sound_precache[i], s))
1304 Host_Error ("PF_precache_sound: overflow");
1307 void PF_precache_model (void)
1312 if (sv.state != ss_loading)
1313 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1315 s = G_STRING(OFS_PARM0);
1316 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1318 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1319 PR_CheckEmptyString (s);
1321 for (i=0 ; i<MAX_MODELS ; i++)
1323 if (!sv.model_precache[i])
1325 sv.model_precache[i] = s;
1326 sv.models[i] = Mod_ForName (s, true, false, false);
1329 if (!strcmp(sv.model_precache[i], s))
1332 Host_Error ("PF_precache_model: overflow");
1336 void PF_coredump (void)
1341 void PF_traceon (void)
1346 void PF_traceoff (void)
1351 void PF_eprint (void)
1353 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1360 float(float yaw, float dist) walkmove
1363 void PF_walkmove (void)
1371 ent = PROG_TO_EDICT(pr_global_struct->self);
1372 if (ent == sv.edicts)
1373 Host_Error("walkmove: can not modify world entity\n");
1375 Host_Error("walkmove: can not modify free entity\n");
1376 yaw = G_FLOAT(OFS_PARM0);
1377 dist = G_FLOAT(OFS_PARM1);
1379 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1381 G_FLOAT(OFS_RETURN) = 0;
1385 yaw = yaw*M_PI*2 / 360;
1387 move[0] = cos(yaw)*dist;
1388 move[1] = sin(yaw)*dist;
1391 // save program state, because SV_movestep may call other progs
1392 oldf = pr_xfunction;
1393 oldself = pr_global_struct->self;
1395 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1398 // restore program state
1399 pr_xfunction = oldf;
1400 pr_global_struct->self = oldself;
1410 void PF_droptofloor (void)
1416 ent = PROG_TO_EDICT(pr_global_struct->self);
1417 if (ent == sv.edicts)
1418 Host_Error("droptofloor: can not modify world entity\n");
1420 Host_Error("droptofloor: can not modify free entity\n");
1422 VectorCopy (ent->v->origin, end);
1425 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1427 if (trace.fraction == 1)
1428 G_FLOAT(OFS_RETURN) = 0;
1431 VectorCopy (trace.endpos, ent->v->origin);
1432 SV_LinkEdict (ent, false);
1433 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1434 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1435 G_FLOAT(OFS_RETURN) = 1;
1436 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1437 ent->e->suspendedinairflag = true;
1445 void(float style, string value) lightstyle
1448 void PF_lightstyle (void)
1455 style = G_FLOAT(OFS_PARM0);
1456 val = G_STRING(OFS_PARM1);
1458 // change the string in sv
1459 sv.lightstyles[style] = val;
1461 // send message to all clients on this server
1462 if (sv.state != ss_active)
1465 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1467 if (client->netconnection)
1469 MSG_WriteChar (&client->message, svc_lightstyle);
1470 MSG_WriteChar (&client->message,style);
1471 MSG_WriteString (&client->message, val);
1479 f = G_FLOAT(OFS_PARM0);
1481 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1483 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1485 void PF_floor (void)
1487 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1491 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1500 void PF_checkbottom (void)
1502 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1510 void PF_pointcontents (void)
1512 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1519 entity nextent(entity)
1522 void PF_nextent (void)
1527 i = G_EDICTNUM(OFS_PARM0);
1530 pr_xfunction->builtinsprofile++;
1532 if (i == sv.num_edicts)
1534 RETURN_EDICT(sv.edicts);
1550 Pick a vector for the player to shoot along
1551 vector aim(entity, missilespeed)
1556 edict_t *ent, *check, *bestent;
1557 vec3_t start, dir, end, bestdir;
1560 float dist, bestdist;
1563 ent = G_EDICT(OFS_PARM0);
1564 if (ent == sv.edicts)
1565 Host_Error("aim: can not use world entity\n");
1567 Host_Error("aim: can not use free entity\n");
1568 speed = G_FLOAT(OFS_PARM1);
1570 VectorCopy (ent->v->origin, start);
1573 // try sending a trace straight
1574 VectorCopy (pr_global_struct->v_forward, dir);
1575 VectorMA (start, 2048, dir, end);
1576 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1577 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1578 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1580 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1585 // try all possible entities
1586 VectorCopy (dir, bestdir);
1587 bestdist = sv_aim.value;
1590 check = NEXT_EDICT(sv.edicts);
1591 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1593 pr_xfunction->builtinsprofile++;
1594 if (check->v->takedamage != DAMAGE_AIM)
1598 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1599 continue; // don't aim at teammate
1600 for (j=0 ; j<3 ; j++)
1601 end[j] = check->v->origin[j]
1602 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1603 VectorSubtract (end, start, dir);
1604 VectorNormalize (dir);
1605 dist = DotProduct (dir, pr_global_struct->v_forward);
1606 if (dist < bestdist)
1607 continue; // to far to turn
1608 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1609 if (tr.ent == check)
1610 { // can shoot at this one
1618 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1619 dist = DotProduct (dir, pr_global_struct->v_forward);
1620 VectorScale (pr_global_struct->v_forward, dist, end);
1622 VectorNormalize (end);
1623 VectorCopy (end, G_VECTOR(OFS_RETURN));
1627 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1635 This was a major timewaster in progs, so it was converted to C
1638 void PF_changeyaw (void)
1641 float ideal, current, move, speed;
1643 ent = PROG_TO_EDICT(pr_global_struct->self);
1644 if (ent == sv.edicts)
1645 Host_Error("changeyaw: can not modify world entity\n");
1647 Host_Error("changeyaw: can not modify free entity\n");
1648 current = ANGLEMOD(ent->v->angles[1]);
1649 ideal = ent->v->ideal_yaw;
1650 speed = ent->v->yaw_speed;
1652 if (current == ideal)
1654 move = ideal - current;
1655 if (ideal > current)
1676 ent->v->angles[1] = ANGLEMOD (current + move);
1684 void PF_changepitch (void)
1687 float ideal, current, move, speed;
1690 ent = G_EDICT(OFS_PARM0);
1691 if (ent == sv.edicts)
1692 Host_Error("changepitch: can not modify world entity\n");
1694 Host_Error("changepitch: can not modify free entity\n");
1695 current = ANGLEMOD( ent->v->angles[0] );
1696 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1697 ideal = val->_float;
1700 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1703 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1704 speed = val->_float;
1707 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1711 if (current == ideal)
1713 move = ideal - current;
1714 if (ideal > current)
1735 ent->v->angles[0] = ANGLEMOD (current + move);
1739 ===============================================================================
1743 ===============================================================================
1746 #define MSG_BROADCAST 0 // unreliable to all
1747 #define MSG_ONE 1 // reliable to one (msg_entity)
1748 #define MSG_ALL 2 // reliable to all
1749 #define MSG_INIT 3 // write to the init string
1751 sizebuf_t *WriteDest (void)
1757 dest = G_FLOAT(OFS_PARM0);
1761 return &sv.datagram;
1764 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1765 entnum = NUM_FOR_EDICT(ent);
1766 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1767 Host_Error("WriteDest: tried to write to non-client\n");
1768 return &svs.clients[entnum-1].message;
1771 return &sv.reliable_datagram;
1777 Host_Error ("WriteDest: bad destination");
1784 void PF_WriteByte (void)
1786 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1789 void PF_WriteChar (void)
1791 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1794 void PF_WriteShort (void)
1796 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1799 void PF_WriteLong (void)
1801 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1804 void PF_WriteAngle (void)
1806 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1809 void PF_WriteCoord (void)
1811 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1814 void PF_WriteString (void)
1816 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1820 void PF_WriteEntity (void)
1822 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1825 //=============================================================================
1827 void PF_makestatic (void)
1832 ent = G_EDICT(OFS_PARM0);
1833 if (ent == sv.edicts)
1834 Host_Error("makestatic: can not modify world entity\n");
1836 Host_Error("makestatic: can not modify free entity\n");
1839 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1844 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1845 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1846 MSG_WriteShort (&sv.signon, ent->v->frame);
1850 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1851 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1852 MSG_WriteByte (&sv.signon, ent->v->frame);
1855 MSG_WriteByte (&sv.signon, ent->v->colormap);
1856 MSG_WriteByte (&sv.signon, ent->v->skin);
1857 for (i=0 ; i<3 ; i++)
1859 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1860 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1863 // throw the entity away now
1867 //=============================================================================
1874 void PF_setspawnparms (void)
1880 ent = G_EDICT(OFS_PARM0);
1881 i = NUM_FOR_EDICT(ent);
1882 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1884 Con_Printf("tried to setspawnparms on a non-client\n");
1888 // copy spawn parms out of the client_t
1889 client = svs.clients + i-1;
1890 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1891 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1899 void PF_changelevel (void)
1903 // make sure we don't issue two changelevels
1904 if (svs.changelevel_issued)
1906 svs.changelevel_issued = true;
1908 s = G_STRING(OFS_PARM0);
1909 Cbuf_AddText (va("changelevel %s\n",s));
1914 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1919 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1924 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1931 Returns a vector of length < 1
1936 void PF_randomvec (void)
1941 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1942 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1943 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1945 while (DotProduct(temp, temp) >= 1);
1946 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1953 Returns a color vector indicating the lighting at the requested point.
1955 (Internal Operation note: actually measures the light beneath the point, just like
1956 the model lighting on the client)
1961 void PF_GetLight (void)
1963 vec3_t ambientcolor, diffusecolor, diffusenormal;
1965 p = G_VECTOR(OFS_PARM0);
1966 VectorClear(ambientcolor);
1967 VectorClear(diffusecolor);
1968 VectorClear(diffusenormal);
1969 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1970 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1971 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1974 #define MAX_QC_CVARS 128
1975 cvar_t qc_cvar[MAX_QC_CVARS];
1978 void PF_registercvar (void)
1982 name = G_STRING(OFS_PARM0);
1983 value = G_STRING(OFS_PARM1);
1984 G_FLOAT(OFS_RETURN) = 0;
1985 // first check to see if it has already been defined
1986 if (Cvar_FindVar (name))
1989 // check for overlap with a command
1990 if (Cmd_Exists (name))
1992 Con_Printf ("PF_registercvar: %s is a command\n", name);
1996 if (currentqc_cvar >= MAX_QC_CVARS)
1997 Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1999 // copy the name and value
2000 variable = &qc_cvar[currentqc_cvar++];
2001 variable->name = Z_Malloc (strlen(name)+1);
2002 strcpy (variable->name, name);
2003 variable->string = Z_Malloc (strlen(value)+1);
2004 strcpy (variable->string, value);
2005 variable->value = atof (value);
2007 Cvar_RegisterVariable(variable);
2008 G_FLOAT(OFS_RETURN) = 1; // success
2015 returns the minimum of two supplied floats
2022 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2024 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2025 else if (pr_argc >= 3)
2028 float f = G_FLOAT(OFS_PARM0);
2029 for (i = 1;i < pr_argc;i++)
2030 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2031 f = G_FLOAT((OFS_PARM0+i*3));
2032 G_FLOAT(OFS_RETURN) = f;
2035 Host_Error("min: must supply at least 2 floats\n");
2042 returns the maximum of two supplied floats
2049 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2051 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2052 else if (pr_argc >= 3)
2055 float f = G_FLOAT(OFS_PARM0);
2056 for (i = 1;i < pr_argc;i++)
2057 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2058 f = G_FLOAT((OFS_PARM0+i*3));
2059 G_FLOAT(OFS_RETURN) = f;
2062 Host_Error("max: must supply at least 2 floats\n");
2069 returns number bounded by supplied range
2071 min(min, value, max)
2074 void PF_bound (void)
2076 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2083 returns a raised to power b
2090 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2097 copies data from one entity to another
2099 copyentity(src, dst)
2102 void PF_copyentity (void)
2105 in = G_EDICT(OFS_PARM0);
2106 if (in == sv.edicts)
2107 Host_Error("copyentity: can not read world entity\n");
2109 Host_Error("copyentity: can not read free entity\n");
2110 out = G_EDICT(OFS_PARM1);
2111 if (out == sv.edicts)
2112 Host_Error("copyentity: can not modify world entity\n");
2114 Host_Error("copyentity: can not modify free entity\n");
2115 memcpy(out->v, in->v, progs->entityfields * 4);
2122 sets the color of a client and broadcasts the update to all connected clients
2124 setcolor(clientent, value)
2127 void PF_setcolor (void)
2133 entnum = G_EDICTNUM(OFS_PARM0);
2134 i = G_FLOAT(OFS_PARM1);
2136 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2138 Con_Printf ("tried to setcolor a non-client\n");
2142 client = svs.clients + entnum-1;
2143 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2146 client->old_colors = i;
2147 client->edict->v->team = (i & 15) + 1;
2149 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2150 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2151 MSG_WriteByte (&sv.reliable_datagram, i);
2158 effect(origin, modelname, startframe, framecount, framerate)
2161 void PF_effect (void)
2164 s = G_STRING(OFS_PARM1);
2166 Host_Error("effect: no model specified\n");
2168 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2171 void PF_te_blood (void)
2173 if (G_FLOAT(OFS_PARM2) < 1)
2175 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2176 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2178 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2179 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2180 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2182 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2183 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2184 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2186 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2189 void PF_te_bloodshower (void)
2191 if (G_FLOAT(OFS_PARM3) < 1)
2193 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2194 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2196 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2197 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2200 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2201 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2202 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2204 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2206 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2209 void PF_te_explosionrgb (void)
2211 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2212 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2214 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2215 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2218 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2219 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2220 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2223 void PF_te_particlecube (void)
2225 if (G_FLOAT(OFS_PARM3) < 1)
2227 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2228 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2230 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2231 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2232 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2234 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2235 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2236 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2238 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2239 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2240 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2242 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2244 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2245 // gravity true/false
2246 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2248 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2251 void PF_te_particlerain (void)
2253 if (G_FLOAT(OFS_PARM3) < 1)
2255 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2256 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2260 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2262 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2263 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2264 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2266 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2267 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2268 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2270 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2272 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2275 void PF_te_particlesnow (void)
2277 if (G_FLOAT(OFS_PARM3) < 1)
2279 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2280 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2286 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2287 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2288 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2290 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2291 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2292 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2294 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2296 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2299 void PF_te_spark (void)
2301 if (G_FLOAT(OFS_PARM2) < 1)
2303 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2304 MSG_WriteByte(&sv.datagram, TE_SPARK);
2306 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2307 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2308 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2310 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2311 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2312 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2314 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2317 void PF_te_gunshotquad (void)
2319 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2320 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2322 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2323 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2324 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2327 void PF_te_spikequad (void)
2329 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2330 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2332 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2333 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2334 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2337 void PF_te_superspikequad (void)
2339 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2340 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2342 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2343 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2344 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2347 void PF_te_explosionquad (void)
2349 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2350 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2352 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2353 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2354 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2357 void PF_te_smallflash (void)
2359 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2360 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2362 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2364 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2367 void PF_te_customflash (void)
2369 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2371 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2372 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2374 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2375 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2376 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2378 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2380 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2382 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2383 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2384 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2387 void PF_te_gunshot (void)
2389 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2390 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2392 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2393 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2394 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2397 void PF_te_spike (void)
2399 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2400 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2402 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2403 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2404 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2407 void PF_te_superspike (void)
2409 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2410 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2412 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2414 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2417 void PF_te_explosion (void)
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2424 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2427 void PF_te_tarexplosion (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2432 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2434 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2437 void PF_te_wizspike (void)
2439 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2440 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2442 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2444 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2447 void PF_te_knightspike (void)
2449 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2450 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2452 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2453 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2454 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2457 void PF_te_lavasplash (void)
2459 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2460 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2462 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2463 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2464 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2467 void PF_te_teleport (void)
2469 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2470 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2474 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2477 void PF_te_explosion2 (void)
2479 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2480 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2482 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2483 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2484 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2486 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2489 void PF_te_lightning1 (void)
2491 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2492 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2494 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2496 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2497 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2498 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2500 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2501 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2505 void PF_te_lightning2 (void)
2507 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2508 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2510 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2518 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2521 void PF_te_lightning3 (void)
2523 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2524 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2526 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2528 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2529 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2534 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2537 void PF_te_beam (void)
2539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2540 MSG_WriteByte(&sv.datagram, TE_BEAM);
2542 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2544 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2545 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2548 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2549 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2550 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2553 void PF_te_plasmaburn (void)
2555 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2556 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2557 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2558 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2559 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2562 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2565 vec3_t v1, clipplanenormal, normal;
2566 vec_t clipplanedist, clipdist;
2568 if (surf->flags & SURF_PLANEBACK)
2569 VectorNegate(surf->plane->normal, normal);
2571 VectorCopy(surf->plane->normal, normal);
2572 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2574 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2575 VectorNormalizeFast(v1);
2576 CrossProduct(v1, normal, clipplanenormal);
2577 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2578 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2581 clipdist = -clipdist;
2582 VectorMA(out, clipdist, clipplanenormal, out);
2587 static msurface_t *getsurface(edict_t *ed, int surfnum)
2591 if (!ed || ed->e->free)
2593 modelindex = ed->v->modelindex;
2594 if (modelindex < 1 || modelindex >= MAX_MODELS)
2596 model = sv.models[modelindex];
2597 if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
2599 return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2603 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2604 void PF_getsurfacenumpoints(void)
2607 // return 0 if no such surface
2608 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2610 G_FLOAT(OFS_RETURN) = 0;
2614 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2616 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2617 void PF_getsurfacepoint(void)
2622 VectorClear(G_VECTOR(OFS_RETURN));
2623 ed = G_EDICT(OFS_PARM0);
2624 if (!ed || ed->e->free)
2626 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2628 pointnum = G_FLOAT(OFS_PARM2);
2629 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2631 // FIXME: implement rotation/scaling
2632 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2634 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2635 void PF_getsurfacenormal(void)
2638 VectorClear(G_VECTOR(OFS_RETURN));
2639 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2641 // FIXME: implement rotation/scaling
2642 if (surf->flags & SURF_PLANEBACK)
2643 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2645 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2647 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2648 void PF_getsurfacetexture(void)
2651 G_INT(OFS_RETURN) = 0;
2652 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2654 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2656 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2657 void PF_getsurfacenearpoint(void)
2659 int surfnum, best, modelindex;
2661 vec_t dist, bestdist;
2666 G_FLOAT(OFS_RETURN) = -1;
2667 ed = G_EDICT(OFS_PARM0);
2668 point = G_VECTOR(OFS_PARM1);
2670 if (!ed || ed->e->free)
2672 modelindex = ed->v->modelindex;
2673 if (modelindex < 1 || modelindex >= MAX_MODELS)
2675 model = sv.models[modelindex];
2676 if (!model->brushq1.numsurfaces)
2679 // FIXME: implement rotation/scaling
2680 VectorSubtract(point, ed->v->origin, p);
2682 bestdist = 1000000000;
2683 for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++)
2685 surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2686 dist = PlaneDiff(p, surf->plane);
2688 if (dist < bestdist)
2690 clippointtosurface(surf, p, clipped);
2691 VectorSubtract(clipped, p, clipped);
2692 dist += DotProduct(clipped, clipped);
2693 if (dist < bestdist)
2700 G_FLOAT(OFS_RETURN) = best;
2702 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2703 void PF_getsurfaceclippedpoint(void)
2708 VectorClear(G_VECTOR(OFS_RETURN));
2709 ed = G_EDICT(OFS_PARM0);
2710 if (!ed || ed->e->free)
2712 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2714 // FIXME: implement rotation/scaling
2715 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2716 clippointtosurface(surf, p, out);
2717 // FIXME: implement rotation/scaling
2718 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2721 #define MAX_PRFILES 256
2723 qfile_t *pr_files[MAX_PRFILES];
2725 void PR_Files_Init(void)
2727 memset(pr_files, 0, sizeof(pr_files));
2730 void PR_Files_CloseAll(void)
2733 for (i = 0;i < MAX_PRFILES;i++)
2736 FS_Close(pr_files[i]);
2741 //float(string s) stof = #81; // get numerical value from a string
2744 char string[STRINGTEMP_LENGTH];
2745 PF_VarString(0, string, sizeof(string));
2746 G_FLOAT(OFS_RETURN) = atof(string);
2749 //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
2753 char *modestring, *filename;
2754 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2755 if (pr_files[filenum] == NULL)
2757 if (filenum >= MAX_PRFILES)
2759 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2760 G_FLOAT(OFS_RETURN) = -2;
2763 mode = G_FLOAT(OFS_PARM1);
2766 case 0: // FILE_READ
2769 case 1: // FILE_APPEND
2772 case 2: // FILE_WRITE
2776 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2777 G_FLOAT(OFS_RETURN) = -3;
2780 filename = G_STRING(OFS_PARM0);
2781 // .. is parent directory on many platforms
2782 // / is parent directory on Amiga
2783 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2784 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2785 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2787 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2788 G_FLOAT(OFS_RETURN) = -4;
2791 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2792 if (pr_files[filenum] == NULL)
2793 G_FLOAT(OFS_RETURN) = -1;
2795 G_FLOAT(OFS_RETURN) = filenum;
2798 //void(float fhandle) fclose = #111; // closes a file
2799 void PF_fclose(void)
2801 int filenum = G_FLOAT(OFS_PARM0);
2802 if (filenum < 0 || filenum >= MAX_PRFILES)
2804 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2807 if (pr_files[filenum] == NULL)
2809 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2812 FS_Close(pr_files[filenum]);
2813 pr_files[filenum] = NULL;
2816 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2820 static char string[STRINGTEMP_LENGTH];
2821 int filenum = G_FLOAT(OFS_PARM0);
2822 if (filenum < 0 || filenum >= MAX_PRFILES)
2824 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2827 if (pr_files[filenum] == NULL)
2829 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2835 c = FS_Getc(pr_files[filenum]);
2836 if (c == '\r' || c == '\n' || c < 0)
2838 if (end < STRINGTEMP_LENGTH - 1)
2842 // remove \n following \r
2844 c = FS_Getc(pr_files[filenum]);
2845 if (developer.integer)
2846 Con_Printf("fgets: %s\n", string);
2848 G_INT(OFS_RETURN) = PR_SetString(string);
2850 G_INT(OFS_RETURN) = 0;
2853 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2857 char string[STRINGTEMP_LENGTH];
2858 int filenum = G_FLOAT(OFS_PARM0);
2859 if (filenum < 0 || filenum >= MAX_PRFILES)
2861 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2864 if (pr_files[filenum] == NULL)
2866 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2869 PF_VarString(1, string, sizeof(string));
2870 if ((stringlength = strlen(string)))
2871 FS_Write(pr_files[filenum], string, stringlength);
2872 if (developer.integer)
2873 Con_Printf("fputs: %s\n", string);
2876 //float(string s) strlen = #114; // returns how many characters are in a string
2877 void PF_strlen(void)
2880 s = G_STRING(OFS_PARM0);
2882 G_FLOAT(OFS_RETURN) = strlen(s);
2884 G_FLOAT(OFS_RETURN) = 0;
2887 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2888 void PF_strcat(void)
2890 char *s = PR_GetTempString();
2891 PF_VarString(0, s, STRINGTEMP_LENGTH);
2892 G_INT(OFS_RETURN) = PR_SetString(s);
2895 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2896 void PF_substring(void)
2898 int i, start, length;
2899 char *s, *string = PR_GetTempString();
2900 s = G_STRING(OFS_PARM0);
2901 start = G_FLOAT(OFS_PARM1);
2902 length = G_FLOAT(OFS_PARM2);
2905 for (i = 0;i < start && *s;i++, s++);
2906 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2909 G_INT(OFS_RETURN) = PR_SetString(string);
2912 //vector(string s) stov = #117; // returns vector value from a string
2915 char string[STRINGTEMP_LENGTH];
2916 PF_VarString(0, string, sizeof(string));
2917 Math_atov(string, G_VECTOR(OFS_RETURN));
2920 //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)
2921 void PF_strzone(void)
2924 in = G_STRING(OFS_PARM0);
2925 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2927 G_INT(OFS_RETURN) = PR_SetString(out);
2930 //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!!!)
2931 void PF_strunzone(void)
2933 Mem_Free(G_STRING(OFS_PARM0));
2936 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2937 //this function originally written by KrimZon, made shorter by LordHavoc
2938 void PF_clientcommand (void)
2940 client_t *temp_client;
2943 //find client for this entity
2944 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2945 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2947 Con_Printf("PF_clientcommand: entity is not a client");
2951 temp_client = host_client;
2952 host_client = svs.clients + i;
2953 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2954 host_client = temp_client;
2957 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2958 //this function originally written by KrimZon, made shorter by LordHavoc
2959 char **tokens = NULL;
2960 int max_tokens, num_tokens = 0;
2961 void PF_tokenize (void)
2965 str = G_STRING(OFS_PARM0);
2970 for (i=0;i<num_tokens;i++)
2976 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2977 max_tokens = strlen(str);
2979 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2981 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2982 strcpy(tokens[num_tokens], com_token);
2985 G_FLOAT(OFS_RETURN) = num_tokens;
2988 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
2989 //this function originally written by KrimZon, made shorter by LordHavoc
2992 int token_num = G_FLOAT(OFS_PARM0);
2993 if (token_num >= 0 && token_num < num_tokens)
2994 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
2996 G_INT(OFS_RETURN) = PR_SetString("");
2999 //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)
3000 void PF_setattachment (void)
3002 edict_t *e = G_EDICT(OFS_PARM0);
3003 edict_t *tagentity = G_EDICT(OFS_PARM1);
3004 char *tagname = G_STRING(OFS_PARM2);
3010 Host_Error("setattachment: can not modify world entity\n");
3012 Host_Error("setattachment: can not modify free entity\n");
3014 if (tagentity == NULL)
3015 tagentity = sv.edicts;
3017 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3019 v->edict = EDICT_TO_PROG(tagentity);
3021 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3024 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3026 modelindex = (int)tagentity->v->modelindex;
3027 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3029 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3030 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3031 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3033 if (v->_float == 0 && model->alias.aliasnum_tags)
3034 for (i = 0;i < model->alias.aliasnum_tags;i++)
3035 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3038 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);
3041 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));
3046 /////////////////////////////////////////
3047 // DP_QC_FS_SEARCH extension
3049 // qc fs search handling
3050 #define MAX_SEARCHES 128
3052 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3054 void PR_Search_Init(void)
3056 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3059 void PR_Search_Reset(void)
3062 // reset the fssearch list
3063 for(i = 0; i < MAX_SEARCHES; i++)
3064 if(pr_fssearchlist[i])
3065 FS_FreeSearch(pr_fssearchlist[i]);
3066 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3073 float search_begin(string pattern, float caseinsensitive, float quiet)
3076 void PF_search_begin(void)
3080 int caseinsens, quiet;
3082 pattern = G_STRING(OFS_PARM0);
3084 PR_CheckEmptyString(pattern);
3086 caseinsens = G_FLOAT(OFS_PARM1);
3087 quiet = G_FLOAT(OFS_PARM2);
3089 for(handle = 0; handle < MAX_SEARCHES; handle++)
3090 if(!pr_fssearchlist[handle])
3093 if(handle >= MAX_SEARCHES)
3095 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3096 G_FLOAT(OFS_RETURN) = -2;
3100 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3101 G_FLOAT(OFS_RETURN) = -1;
3103 G_FLOAT(OFS_RETURN) = handle;
3110 void search_end(float handle)
3113 void PF_search_end(void)
3117 handle = G_FLOAT(OFS_PARM0);
3119 if(handle < 0 || handle >= MAX_SEARCHES)
3121 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3124 if(pr_fssearchlist[handle] == NULL)
3126 Con_Printf("PF_search_end: no such handle %i\n", handle);
3130 FS_FreeSearch(pr_fssearchlist[handle]);
3131 pr_fssearchlist[handle] = NULL;
3138 float search_getsize(float handle)
3141 void PF_search_getsize(void)
3145 handle = G_FLOAT(OFS_PARM0);
3147 if(handle < 0 || handle >= MAX_SEARCHES)
3149 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3152 if(pr_fssearchlist[handle] == NULL)
3154 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3158 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3163 VM_search_getfilename
3165 string search_getfilename(float handle, float num)
3168 void PF_search_getfilename(void)
3170 int handle, filenum;
3173 handle = G_FLOAT(OFS_PARM0);
3174 filenum = G_FLOAT(OFS_PARM1);
3176 if(handle < 0 || handle >= MAX_SEARCHES)
3178 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3181 if(pr_fssearchlist[handle] == NULL)
3183 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3186 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3188 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3192 tmp = PR_GetTempString();
3193 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3195 G_INT(OFS_RETURN) = PR_SetString(tmp);
3199 builtin_t pr_builtin[] =
3202 PF_makevectors, // #1 void(entity e) makevectors
3203 PF_setorigin, // #2 void(entity e, vector o) setorigin
3204 PF_setmodel, // #3 void(entity e, string m) setmodel
3205 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3206 NULL, // #5 void(entity e, vector min, vector max) setabssize
3207 PF_break, // #6 void() break
3208 PF_random, // #7 float() random
3209 PF_sound, // #8 void(entity e, float chan, string samp) sound
3210 PF_normalize, // #9 vector(vector v) normalize
3211 PF_error, // #10 void(string e) error
3212 PF_objerror, // #11 void(string e) objerror
3213 PF_vlen, // #12 float(vector v) vlen
3214 PF_vectoyaw, // #13 float(vector v) vectoyaw
3215 PF_Spawn, // #14 entity() spawn
3216 PF_Remove, // #15 void(entity e) remove
3217 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3218 PF_checkclient, // #17 entity() clientlist
3219 PF_Find, // #18 entity(entity start, .string fld, string match) find
3220 PF_precache_sound, // #19 void(string s) precache_sound
3221 PF_precache_model, // #20 void(string s) precache_model
3222 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3223 PF_findradius, // #22 entity(vector org, float rad) findradius
3224 PF_bprint, // #23 void(string s) bprint
3225 PF_sprint, // #24 void(entity client, string s) sprint
3226 PF_dprint, // #25 void(string s) dprint
3227 PF_ftos, // #26 void(string s) ftos
3228 PF_vtos, // #27 void(string s) vtos
3229 PF_coredump, // #28 void() coredump
3230 PF_traceon, // #29 void() traceon
3231 PF_traceoff, // #30 void() traceoff
3232 PF_eprint, // #31 void(entity e) eprint
3233 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3235 PF_droptofloor, // #34 float() droptofloor
3236 PF_lightstyle, // #35 void(float style, string value) lightstyle
3237 PF_rint, // #36 float(float v) rint
3238 PF_floor, // #37 float(float v) floor
3239 PF_ceil, // #38 float(float v) ceil
3241 PF_checkbottom, // #40 float(entity e) checkbottom
3242 PF_pointcontents , // #41 float(vector v) pointcontents
3244 PF_fabs, // #43 float(float f) fabs
3245 PF_aim, // #44 vector(entity e, float speed) aim
3246 PF_cvar, // #45 float(string s) cvar
3247 PF_localcmd, // #46 void(string s) localcmd
3248 PF_nextent, // #47 entity(entity e) nextent
3249 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3250 PF_changeyaw, // #49 void() ChangeYaw
3252 PF_vectoangles, // #51 vector(vector v) vectoangles
3253 PF_WriteByte, // #52 void(float to, float f) WriteByte
3254 PF_WriteChar, // #53 void(float to, float f) WriteChar
3255 PF_WriteShort, // #54 void(float to, float f) WriteShort
3256 PF_WriteLong, // #55 void(float to, float f) WriteLong
3257 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3258 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3259 PF_WriteString, // #58 void(float to, string s) WriteString
3260 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3261 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3262 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3263 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3264 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3265 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3266 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3268 SV_MoveToGoal, // #67 void(float step) movetogoal
3269 PF_precache_file, // #68 string(string s) precache_file
3270 PF_makestatic, // #69 void(entity e) makestatic
3271 PF_changelevel, // #70 void(string s) changelevel
3273 PF_cvar_set, // #72 void(string var, string val) cvar_set
3274 PF_centerprint, // #73 void(entity client, strings) centerprint
3275 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3276 PF_precache_model, // #75 string(string s) precache_model2
3277 PF_precache_sound, // #76 string(string s) precache_sound2
3278 PF_precache_file, // #77 string(string s) precache_file2
3279 PF_setspawnparms, // #78 void(entity e) setspawnparms
3282 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3291 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3292 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3293 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3294 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3295 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3296 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3297 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3298 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3299 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3300 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3311 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3312 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3313 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3314 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3315 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3316 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3317 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3318 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3319 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3320 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3321 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3322 a a a a a a a a // #120-199
3323 a a a a a a a a a a // #200-299
3324 a a a a a a a a a a // #300-399
3325 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3326 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3327 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3328 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3329 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3330 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3331 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3332 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3333 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3334 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3335 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3336 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3337 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3338 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3339 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3340 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3341 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3342 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3343 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3344 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3345 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3346 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3347 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3348 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3349 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3350 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3351 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3352 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3353 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3354 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3355 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3356 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3357 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3358 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3359 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3360 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3361 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3362 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3363 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3364 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3365 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3366 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3367 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3368 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3369 PF_search_begin, // #444
3370 PF_search_end, // #445
3371 PF_search_getsize, // #446
3372 PF_search_getfilename, // #447
3375 a a a a a // #450-499 (LordHavoc)
3378 builtin_t *pr_builtins = pr_builtin;
3379 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3381 void PR_Cmd_Init(void)
3383 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3388 void PR_Cmd_Reset(void)
3390 Mem_EmptyPool(pr_strings_mempool);
3392 PR_Files_CloseAll();