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) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
43 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
44 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
48 ===============================================================================
52 ===============================================================================
56 void PF_VarString(int first, char *out, int outlength)
62 outend = out + outlength - 1;
63 for (i = first;i < pr_argc && out < outend;i++)
65 s = G_STRING((OFS_PARM0+i*3));
66 while (out < outend && *s)
72 char *ENGINE_EXTENSIONS =
83 "DP_ENT_CUSTOMCOLORMAP "
84 "DP_ENT_EXTERIORMODELTOCLIENT "
86 "DP_ENT_LOWPRECISION "
89 "DP_GFX_EXTERNALTEXTURES "
91 "DP_GFX_QUAKE3MODELTAGS "
95 "DP_HALFLIFE_MAP_CVAR "
99 "DP_MOVETYPEBOUNCEMISSILE "
106 "DP_QC_FINDCHAINFLOAT "
108 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
112 "DP_QC_MULTIPLETEMPSTRINGS "
114 "DP_QC_SINCOSSQRTPOW "
117 "DP_QC_TRACE_MOVETYPE_HITMODEL "
118 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
119 "DP_QC_VECTORVECTORS "
123 "DP_SND_DIRECTIONLESSATTNNONE "
128 "DP_SV_DRAWONLYTOCLIENT "
130 "DP_SV_EXTERIORMODELTOCLIENT "
131 "DP_SV_NODRAWTOCLIENT "
132 "DP_SV_PLAYERPHYSICS "
133 "DP_SV_ROTATINGBMODEL "
139 "DP_TE_EXPLOSIONRGB "
141 "DP_TE_PARTICLECUBE "
142 "DP_TE_PARTICLERAIN "
143 "DP_TE_PARTICLESNOW "
145 "DP_TE_QUADEFFECTS1 "
148 "DP_TE_STANDARDEFFECTBUILTINS "
151 "KRIMZON_SV_PARSECLIENTCOMMAND "
154 "TENEBRAE_GFX_DLIGHTS "
158 qboolean checkextension(char *name)
163 for (e = ENGINE_EXTENSIONS;*e;e++)
170 while (*e && *e != ' ')
172 if (e - start == len)
173 if (!strncasecmp(start, name, len))
183 returns true if the extension is supported by the server
185 checkextension(extensionname)
188 void PF_checkextension (void)
190 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
197 This is a TERMINAL error, which will kill off the entire server.
206 char string[STRINGTEMP_LENGTH];
208 PF_VarString(0, string, sizeof(string));
209 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
210 ed = PROG_TO_EDICT(pr_global_struct->self);
213 PF_ERROR("Program error");
220 Dumps out self, then an error message. The program is aborted and self is
221 removed, but the level can continue.
226 void PF_objerror (void)
229 char string[STRINGTEMP_LENGTH];
231 PF_VarString(0, string, sizeof(string));
232 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
233 ed = PROG_TO_EDICT(pr_global_struct->self);
243 Writes new values for v_forward, v_up, and v_right based on angles
247 void PF_makevectors (void)
249 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
256 Writes new values for v_forward, v_up, and v_right based on the given forward vector
257 vectorvectors(vector, vector)
260 void PF_vectorvectors (void)
262 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
263 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
270 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.
272 setorigin (entity, origin)
275 void PF_setorigin (void)
280 e = G_EDICT(OFS_PARM0);
282 PF_WARNING("setorigin: can not modify world entity\n");
284 PF_WARNING("setorigin: can not modify free entity\n");
285 org = G_VECTOR(OFS_PARM1);
286 VectorCopy (org, e->v->origin);
287 SV_LinkEdict (e, false);
291 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
295 for (i=0 ; i<3 ; i++)
297 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
299 // set derived values
300 VectorCopy (min, e->v->mins);
301 VectorCopy (max, e->v->maxs);
302 VectorSubtract (max, min, e->v->size);
304 SV_LinkEdict (e, false);
311 the size box is rotated by the current angle
312 LordHavoc: no it isn't...
314 setsize (entity, minvector, maxvector)
317 void PF_setsize (void)
322 e = G_EDICT(OFS_PARM0);
324 PF_WARNING("setsize: can not modify world entity\n");
326 PF_WARNING("setsize: can not modify free entity\n");
327 min = G_VECTOR(OFS_PARM1);
328 max = G_VECTOR(OFS_PARM2);
329 SetMinMaxSize (e, min, max, false);
337 setmodel(entity, model)
340 void PF_setmodel (void)
347 e = G_EDICT(OFS_PARM0);
349 PF_WARNING("setmodel: can not modify world entity\n");
351 PF_WARNING("setmodel: can not modify free entity\n");
352 m = G_STRING(OFS_PARM1);
354 // check to see if model was properly precached
355 for (i=0, check = sv.model_precache ; *check ; i++, check++)
356 if (!strcmp(*check, m))
360 PF_WARNING("setmodel: no precache\n");
363 e->v->model = PR_SetString(*check);
364 e->v->modelindex = i;
366 mod = sv.models[ (int)e->v->modelindex];
369 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
371 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
378 broadcast print to everyone on server
383 void PF_bprint (void)
385 char string[STRINGTEMP_LENGTH];
386 PF_VarString(0, string, sizeof(string));
387 SV_BroadcastPrint(string);
394 single print to a specific client
396 sprint(clientent, value)
399 void PF_sprint (void)
403 char string[STRINGTEMP_LENGTH];
405 entnum = G_EDICTNUM(OFS_PARM0);
407 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
409 Con_Print("tried to sprint to a non-client\n");
413 client = svs.clients + entnum-1;
414 if (!client->netconnection)
416 PF_VarString(1, string, sizeof(string));
417 MSG_WriteChar(&client->message,svc_print);
418 MSG_WriteString(&client->message, string);
426 single print to a specific client
428 centerprint(clientent, value)
431 void PF_centerprint (void)
435 char string[STRINGTEMP_LENGTH];
437 entnum = G_EDICTNUM(OFS_PARM0);
439 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
441 Con_Print("tried to sprint to a non-client\n");
445 client = svs.clients + entnum-1;
446 if (!client->netconnection)
448 PF_VarString(1, string, sizeof(string));
449 MSG_WriteChar(&client->message,svc_centerprint);
450 MSG_WriteString(&client->message, string);
458 vector normalize(vector)
461 void PF_normalize (void)
467 value1 = G_VECTOR(OFS_PARM0);
469 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
473 newvalue[0] = newvalue[1] = newvalue[2] = 0;
477 newvalue[0] = value1[0] * new;
478 newvalue[1] = value1[1] * new;
479 newvalue[2] = value1[2] * new;
482 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
497 value1 = G_VECTOR(OFS_PARM0);
499 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
502 G_FLOAT(OFS_RETURN) = new;
509 float vectoyaw(vector)
512 void PF_vectoyaw (void)
517 value1 = G_VECTOR(OFS_PARM0);
519 if (value1[1] == 0 && value1[0] == 0)
523 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
528 G_FLOAT(OFS_RETURN) = yaw;
536 vector vectoangles(vector)
539 void PF_vectoangles (void)
545 value1 = G_VECTOR(OFS_PARM0);
547 if (value1[1] == 0 && value1[0] == 0)
557 // LordHavoc: optimized a bit
560 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
564 else if (value1[1] > 0)
569 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
570 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
575 G_FLOAT(OFS_RETURN+0) = pitch;
576 G_FLOAT(OFS_RETURN+1) = yaw;
577 G_FLOAT(OFS_RETURN+2) = 0;
584 Returns a number from 0<= num < 1
589 void PF_random (void)
593 num = (rand ()&0x7fff) / ((float)0x7fff);
595 G_FLOAT(OFS_RETURN) = num;
602 particle(origin, color, count)
605 void PF_particle (void)
611 org = G_VECTOR(OFS_PARM0);
612 dir = G_VECTOR(OFS_PARM1);
613 color = G_FLOAT(OFS_PARM2);
614 count = G_FLOAT(OFS_PARM3);
615 SV_StartParticle (org, dir, color, count);
625 void PF_ambientsound (void)
630 float vol, attenuation;
631 int i, soundnum, large;
633 pos = G_VECTOR (OFS_PARM0);
634 samp = G_STRING(OFS_PARM1);
635 vol = G_FLOAT(OFS_PARM2);
636 attenuation = G_FLOAT(OFS_PARM3);
638 // check to see if samp was properly precached
639 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
640 if (!strcmp(*check,samp))
645 Con_Printf("no precache: %s\n", samp);
653 // add an svc_spawnambient command to the level signon packet
656 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
658 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
660 for (i=0 ; i<3 ; i++)
661 MSG_WriteDPCoord(&sv.signon, pos[i]);
664 MSG_WriteShort (&sv.signon, soundnum);
666 MSG_WriteByte (&sv.signon, soundnum);
668 MSG_WriteByte (&sv.signon, vol*255);
669 MSG_WriteByte (&sv.signon, attenuation*64);
677 Each entity can have eight independant sound sources, like voice,
680 Channel 0 is an auto-allocate channel, the others override anything
681 already running on that entity/channel pair.
683 An attenuation of 0 will play full volume everywhere in the level.
684 Larger attenuations will drop off.
696 entity = G_EDICT(OFS_PARM0);
697 channel = G_FLOAT(OFS_PARM1);
698 sample = G_STRING(OFS_PARM2);
699 volume = G_FLOAT(OFS_PARM3) * 255;
700 attenuation = G_FLOAT(OFS_PARM4);
702 if (volume < 0 || volume > 255)
703 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
705 if (attenuation < 0 || attenuation > 4)
706 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
708 if (channel < 0 || channel > 7)
709 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
711 SV_StartSound (entity, channel, sample, volume, attenuation);
723 PF_ERROR("break: break statement\n");
730 Used for use tracing and shot targeting
731 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
732 if the tryents flag is set.
734 traceline (vector1, vector2, tryents)
737 void PF_traceline (void)
744 pr_xfunction->builtinsprofile += 30;
746 v1 = G_VECTOR(OFS_PARM0);
747 v2 = G_VECTOR(OFS_PARM1);
748 move = G_FLOAT(OFS_PARM2);
749 ent = G_EDICT(OFS_PARM3);
751 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
753 pr_global_struct->trace_allsolid = trace.allsolid;
754 pr_global_struct->trace_startsolid = trace.startsolid;
755 pr_global_struct->trace_fraction = trace.fraction;
756 pr_global_struct->trace_inwater = trace.inwater;
757 pr_global_struct->trace_inopen = trace.inopen;
758 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
759 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
760 pr_global_struct->trace_plane_dist = trace.plane.dist;
762 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
764 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
765 // FIXME: add trace_endcontents
773 Used for use tracing and shot targeting
774 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
775 if the tryents flag is set.
777 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
780 // LordHavoc: added this for my own use, VERY useful, similar to traceline
781 void PF_tracebox (void)
783 float *v1, *v2, *m1, *m2;
788 pr_xfunction->builtinsprofile += 30;
790 v1 = G_VECTOR(OFS_PARM0);
791 m1 = G_VECTOR(OFS_PARM1);
792 m2 = G_VECTOR(OFS_PARM2);
793 v2 = G_VECTOR(OFS_PARM3);
794 move = G_FLOAT(OFS_PARM4);
795 ent = G_EDICT(OFS_PARM5);
797 trace = SV_Move (v1, m1, m2, v2, move, ent);
799 pr_global_struct->trace_allsolid = trace.allsolid;
800 pr_global_struct->trace_startsolid = trace.startsolid;
801 pr_global_struct->trace_fraction = trace.fraction;
802 pr_global_struct->trace_inwater = trace.inwater;
803 pr_global_struct->trace_inopen = trace.inopen;
804 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
805 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
806 pr_global_struct->trace_plane_dist = trace.plane.dist;
808 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
810 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
813 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
814 void PF_TraceToss (void)
820 pr_xfunction->builtinsprofile += 600;
822 ent = G_EDICT(OFS_PARM0);
823 if (ent == sv.edicts)
824 PF_WARNING("tracetoss: can not use world entity\n");
825 ignore = G_EDICT(OFS_PARM1);
827 trace = SV_Trace_Toss (ent, ignore);
829 pr_global_struct->trace_allsolid = trace.allsolid;
830 pr_global_struct->trace_startsolid = trace.startsolid;
831 pr_global_struct->trace_fraction = trace.fraction;
832 pr_global_struct->trace_inwater = trace.inwater;
833 pr_global_struct->trace_inopen = trace.inopen;
834 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
835 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
836 pr_global_struct->trace_plane_dist = trace.plane.dist;
838 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
840 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
848 Returns true if the given entity can move to the given position from it's
849 current position by walking or rolling.
851 scalar checkpos (entity, vector)
854 void PF_checkpos (void)
858 //============================================================================
861 qbyte checkpvs[MAX_MAP_LEAFS/8];
863 int PF_newcheckclient (int check)
869 // cycle to the next one
871 check = bound(1, check, svs.maxclients);
872 if (check == svs.maxclients)
880 pr_xfunction->builtinsprofile++;
882 if (i == svs.maxclients+1)
884 // look up the client's edict
886 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
887 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
889 // found a valid client (possibly the same one again)
893 // get the PVS for the entity
894 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
896 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
897 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
906 Returns a client (or object that has a client enemy) that would be a
909 If there is more than one valid option, they are cycled each frame
911 If (self.origin + self.viewofs) is not in the PVS of the current target,
912 it is not returned at all.
917 int c_invis, c_notvis;
918 void PF_checkclient (void)
923 // find a new check if on a new frame
924 if (sv.time - sv.lastchecktime >= 0.1)
926 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
927 sv.lastchecktime = sv.time;
930 // return check if it might be visible
931 ent = EDICT_NUM(sv.lastcheck);
932 if (ent->e->free || ent->v->health <= 0)
934 RETURN_EDICT(sv.edicts);
938 // if current entity can't possibly see the check entity, return 0
939 self = PROG_TO_EDICT(pr_global_struct->self);
940 VectorAdd(self->v->origin, self->v->view_ofs, view);
941 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
944 RETURN_EDICT(sv.edicts);
948 // might be able to see it
953 //============================================================================
960 Sends text over to the client's execution buffer
962 stuffcmd (clientent, value)
965 void PF_stuffcmd (void)
971 entnum = G_EDICTNUM(OFS_PARM0);
972 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
974 Con_Print("Can't stuffcmd to a non-client\n");
977 str = G_STRING(OFS_PARM1);
980 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
981 Host_ClientCommands ("%s", str);
989 Sends text to server console
994 void PF_localcmd (void)
996 Cbuf_AddText(G_STRING(OFS_PARM0));
1008 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1018 void PF_cvar_set (void)
1020 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1027 Returns a chain of entities that have origins within a spherical area
1029 findradius (origin, radius)
1032 void PF_findradius (void)
1034 edict_t *ent, *chain;
1041 chain = (edict_t *)sv.edicts;
1043 org = G_VECTOR(OFS_PARM0);
1044 radius = G_FLOAT(OFS_PARM1);
1045 radius2 = radius * radius;
1047 ent = NEXT_EDICT(sv.edicts);
1048 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1050 pr_xfunction->builtinsprofile++;
1053 if (ent->v->solid == SOLID_NOT)
1056 // LordHavoc: compare against bounding box rather than center,
1057 // and use DotProduct instead of Length, major speedup
1058 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1059 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1060 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1061 if (DotProduct(eorg, eorg) > radius2)
1064 ent->v->chain = EDICT_TO_PROG(chain);
1068 RETURN_EDICT(chain);
1077 void PF_dprint (void)
1079 char string[STRINGTEMP_LENGTH];
1080 if (developer.integer)
1082 PF_VarString(0, string, sizeof(string));
1091 v = G_FLOAT(OFS_PARM0);
1093 s = PR_GetTempString();
1094 if ((float)((int)v) == v)
1095 sprintf(s, "%i", (int)v);
1097 sprintf(s, "%f", v);
1098 G_INT(OFS_RETURN) = PR_SetString(s);
1104 v = G_FLOAT(OFS_PARM0);
1105 G_FLOAT(OFS_RETURN) = fabs(v);
1111 s = PR_GetTempString();
1112 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1113 G_INT(OFS_RETURN) = PR_SetString(s);
1119 s = PR_GetTempString();
1120 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1121 G_INT(OFS_RETURN) = PR_SetString(s);
1124 void PF_Spawn (void)
1127 pr_xfunction->builtinsprofile += 20;
1132 void PF_Remove (void)
1135 pr_xfunction->builtinsprofile += 20;
1137 ed = G_EDICT(OFS_PARM0);
1138 if (ed == sv.edicts)
1139 PF_WARNING("remove: tried to remove world\n");
1140 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1141 PF_WARNING("remove: tried to remove a client\n");
1142 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1143 if (ed->e->free && developer.integer)
1144 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1149 // entity (entity start, .string field, string match) find = #5;
1157 e = G_EDICTNUM(OFS_PARM0);
1158 f = G_INT(OFS_PARM1);
1159 s = G_STRING(OFS_PARM2);
1162 RETURN_EDICT(sv.edicts);
1166 for (e++ ; e < sv.num_edicts ; e++)
1168 pr_xfunction->builtinsprofile++;
1182 RETURN_EDICT(sv.edicts);
1185 // LordHavoc: added this for searching float, int, and entity reference fields
1186 void PF_FindFloat (void)
1193 e = G_EDICTNUM(OFS_PARM0);
1194 f = G_INT(OFS_PARM1);
1195 s = G_FLOAT(OFS_PARM2);
1197 for (e++ ; e < sv.num_edicts ; e++)
1199 pr_xfunction->builtinsprofile++;
1203 if (E_FLOAT(ed,f) == s)
1210 RETURN_EDICT(sv.edicts);
1213 // chained search for strings in entity fields
1214 // entity(.string field, string match) findchain = #402;
1215 void PF_findchain (void)
1220 edict_t *ent, *chain;
1222 chain = (edict_t *)sv.edicts;
1224 f = G_INT(OFS_PARM0);
1225 s = G_STRING(OFS_PARM1);
1228 RETURN_EDICT(sv.edicts);
1232 ent = NEXT_EDICT(sv.edicts);
1233 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1235 pr_xfunction->builtinsprofile++;
1238 t = E_STRING(ent,f);
1244 ent->v->chain = EDICT_TO_PROG(chain);
1248 RETURN_EDICT(chain);
1251 // LordHavoc: chained search for float, int, and entity reference fields
1252 // entity(.string field, float match) findchainfloat = #403;
1253 void PF_findchainfloat (void)
1258 edict_t *ent, *chain;
1260 chain = (edict_t *)sv.edicts;
1262 f = G_INT(OFS_PARM0);
1263 s = G_FLOAT(OFS_PARM1);
1265 ent = NEXT_EDICT(sv.edicts);
1266 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1268 pr_xfunction->builtinsprofile++;
1271 if (E_FLOAT(ent,f) != s)
1274 ent->v->chain = EDICT_TO_PROG(chain);
1278 RETURN_EDICT(chain);
1281 void PR_CheckEmptyString (char *s)
1284 PF_ERROR("Bad string");
1287 void PF_precache_file (void)
1288 { // precache_file is only used to copy files with qcc, it does nothing
1289 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1292 void PF_precache_sound (void)
1297 if (sv.state != ss_loading)
1298 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1300 s = G_STRING(OFS_PARM0);
1301 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1302 PR_CheckEmptyString (s);
1304 for (i=0 ; i<MAX_SOUNDS ; i++)
1306 if (!sv.sound_precache[i])
1308 sv.sound_precache[i] = s;
1311 if (!strcmp(sv.sound_precache[i], s))
1314 PF_ERROR("PF_precache_sound: overflow");
1317 void PF_precache_model (void)
1322 if (sv.state != ss_loading)
1323 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1325 s = G_STRING(OFS_PARM0);
1326 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1328 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1329 PR_CheckEmptyString (s);
1331 for (i=0 ; i<MAX_MODELS ; i++)
1333 if (!sv.model_precache[i])
1335 sv.model_precache[i] = s;
1336 sv.models[i] = Mod_ForName (s, true, false, false);
1339 if (!strcmp(sv.model_precache[i], s))
1342 PF_ERROR("PF_precache_model: overflow");
1346 void PF_coredump (void)
1351 void PF_traceon (void)
1356 void PF_traceoff (void)
1361 void PF_eprint (void)
1363 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1370 float(float yaw, float dist) walkmove
1373 void PF_walkmove (void)
1381 // assume failure if it returns early
1382 G_FLOAT(OFS_RETURN) = 0;
1384 ent = PROG_TO_EDICT(pr_global_struct->self);
1385 if (ent == sv.edicts)
1386 PF_WARNING("walkmove: can not modify world entity\n");
1388 PF_WARNING("walkmove: can not modify free entity\n");
1389 yaw = G_FLOAT(OFS_PARM0);
1390 dist = G_FLOAT(OFS_PARM1);
1392 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1395 yaw = yaw*M_PI*2 / 360;
1397 move[0] = cos(yaw)*dist;
1398 move[1] = sin(yaw)*dist;
1401 // save program state, because SV_movestep may call other progs
1402 oldf = pr_xfunction;
1403 oldself = pr_global_struct->self;
1405 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1408 // restore program state
1409 pr_xfunction = oldf;
1410 pr_global_struct->self = oldself;
1420 void PF_droptofloor (void)
1426 // assume failure if it returns early
1427 G_FLOAT(OFS_RETURN) = 0;
1429 ent = PROG_TO_EDICT(pr_global_struct->self);
1430 if (ent == sv.edicts)
1431 PF_WARNING("droptofloor: can not modify world entity\n");
1433 PF_WARNING("droptofloor: can not modify free entity\n");
1435 VectorCopy (ent->v->origin, end);
1438 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1440 if (trace.fraction != 1)
1442 VectorCopy (trace.endpos, ent->v->origin);
1443 SV_LinkEdict (ent, false);
1444 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1445 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1446 G_FLOAT(OFS_RETURN) = 1;
1447 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1448 ent->e->suspendedinairflag = true;
1456 void(float style, string value) lightstyle
1459 void PF_lightstyle (void)
1466 style = G_FLOAT(OFS_PARM0);
1467 val = G_STRING(OFS_PARM1);
1469 // change the string in sv
1470 sv.lightstyles[style] = val;
1472 // send message to all clients on this server
1473 if (sv.state != ss_active)
1476 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1478 if (client->netconnection)
1480 MSG_WriteChar (&client->message, svc_lightstyle);
1481 MSG_WriteChar (&client->message,style);
1482 MSG_WriteString (&client->message, val);
1490 f = G_FLOAT(OFS_PARM0);
1492 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1494 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1496 void PF_floor (void)
1498 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1502 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1511 void PF_checkbottom (void)
1513 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1521 void PF_pointcontents (void)
1523 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1530 entity nextent(entity)
1533 void PF_nextent (void)
1538 i = G_EDICTNUM(OFS_PARM0);
1541 pr_xfunction->builtinsprofile++;
1543 if (i == sv.num_edicts)
1545 RETURN_EDICT(sv.edicts);
1561 Pick a vector for the player to shoot along
1562 vector aim(entity, missilespeed)
1567 edict_t *ent, *check, *bestent;
1568 vec3_t start, dir, end, bestdir;
1571 float dist, bestdist;
1574 // assume failure if it returns early
1575 VectorClear(G_VECTOR(OFS_RETURN));
1577 ent = G_EDICT(OFS_PARM0);
1578 if (ent == sv.edicts)
1579 PF_WARNING("aim: can not use world entity\n");
1581 PF_WARNING("aim: can not use free entity\n");
1582 speed = G_FLOAT(OFS_PARM1);
1584 VectorCopy (ent->v->origin, start);
1587 // try sending a trace straight
1588 VectorCopy (pr_global_struct->v_forward, dir);
1589 VectorMA (start, 2048, dir, end);
1590 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1591 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1592 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1594 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1599 // try all possible entities
1600 VectorCopy (dir, bestdir);
1601 bestdist = sv_aim.value;
1604 check = NEXT_EDICT(sv.edicts);
1605 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1607 pr_xfunction->builtinsprofile++;
1608 if (check->v->takedamage != DAMAGE_AIM)
1612 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1613 continue; // don't aim at teammate
1614 for (j=0 ; j<3 ; j++)
1615 end[j] = check->v->origin[j]
1616 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1617 VectorSubtract (end, start, dir);
1618 VectorNormalize (dir);
1619 dist = DotProduct (dir, pr_global_struct->v_forward);
1620 if (dist < bestdist)
1621 continue; // to far to turn
1622 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1623 if (tr.ent == check)
1624 { // can shoot at this one
1632 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1633 dist = DotProduct (dir, pr_global_struct->v_forward);
1634 VectorScale (pr_global_struct->v_forward, dist, end);
1636 VectorNormalize (end);
1637 VectorCopy (end, G_VECTOR(OFS_RETURN));
1641 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1649 This was a major timewaster in progs, so it was converted to C
1652 void PF_changeyaw (void)
1655 float ideal, current, move, speed;
1657 ent = PROG_TO_EDICT(pr_global_struct->self);
1658 if (ent == sv.edicts)
1659 PF_WARNING("changeyaw: can not modify world entity\n");
1661 PF_WARNING("changeyaw: can not modify free entity\n");
1662 current = ANGLEMOD(ent->v->angles[1]);
1663 ideal = ent->v->ideal_yaw;
1664 speed = ent->v->yaw_speed;
1666 if (current == ideal)
1668 move = ideal - current;
1669 if (ideal > current)
1690 ent->v->angles[1] = ANGLEMOD (current + move);
1698 void PF_changepitch (void)
1701 float ideal, current, move, speed;
1704 ent = G_EDICT(OFS_PARM0);
1705 if (ent == sv.edicts)
1706 PF_WARNING("changepitch: can not modify world entity\n");
1708 PF_WARNING("changepitch: can not modify free entity\n");
1709 current = ANGLEMOD( ent->v->angles[0] );
1710 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1711 ideal = val->_float;
1714 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1717 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1718 speed = val->_float;
1721 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1725 if (current == ideal)
1727 move = ideal - current;
1728 if (ideal > current)
1749 ent->v->angles[0] = ANGLEMOD (current + move);
1753 ===============================================================================
1757 ===============================================================================
1760 #define MSG_BROADCAST 0 // unreliable to all
1761 #define MSG_ONE 1 // reliable to one (msg_entity)
1762 #define MSG_ALL 2 // reliable to all
1763 #define MSG_INIT 3 // write to the init string
1765 sizebuf_t *WriteDest (void)
1771 dest = G_FLOAT(OFS_PARM0);
1775 return &sv.datagram;
1778 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1779 entnum = NUM_FOR_EDICT(ent);
1780 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1781 Host_Error("WriteDest: tried to write to non-client\n");
1782 return &svs.clients[entnum-1].message;
1785 return &sv.reliable_datagram;
1791 Host_Error("WriteDest: bad destination");
1798 void PF_WriteByte (void)
1800 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1803 void PF_WriteChar (void)
1805 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1808 void PF_WriteShort (void)
1810 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1813 void PF_WriteLong (void)
1815 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1818 void PF_WriteAngle (void)
1820 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1823 void PF_WriteCoord (void)
1825 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1828 void PF_WriteString (void)
1830 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1834 void PF_WriteEntity (void)
1836 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1839 //=============================================================================
1841 void PF_makestatic (void)
1846 ent = G_EDICT(OFS_PARM0);
1847 if (ent == sv.edicts)
1848 PF_WARNING("makestatic: can not modify world entity\n");
1850 PF_WARNING("makestatic: can not modify free entity\n");
1853 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1858 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1859 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1860 MSG_WriteShort (&sv.signon, ent->v->frame);
1864 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1865 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1866 MSG_WriteByte (&sv.signon, ent->v->frame);
1869 MSG_WriteByte (&sv.signon, ent->v->colormap);
1870 MSG_WriteByte (&sv.signon, ent->v->skin);
1871 for (i=0 ; i<3 ; i++)
1873 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1874 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1877 // throw the entity away now
1881 //=============================================================================
1888 void PF_setspawnparms (void)
1894 ent = G_EDICT(OFS_PARM0);
1895 i = NUM_FOR_EDICT(ent);
1896 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1898 Con_Print("tried to setspawnparms on a non-client\n");
1902 // copy spawn parms out of the client_t
1903 client = svs.clients + i-1;
1904 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1905 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1913 void PF_changelevel (void)
1917 // make sure we don't issue two changelevels
1918 if (svs.changelevel_issued)
1920 svs.changelevel_issued = true;
1922 s = G_STRING(OFS_PARM0);
1923 Cbuf_AddText (va("changelevel %s\n",s));
1928 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1933 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1938 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1945 Returns a vector of length < 1
1950 void PF_randomvec (void)
1955 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1956 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1957 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1959 while (DotProduct(temp, temp) >= 1);
1960 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1967 Returns a color vector indicating the lighting at the requested point.
1969 (Internal Operation note: actually measures the light beneath the point, just like
1970 the model lighting on the client)
1975 void PF_GetLight (void)
1977 vec3_t ambientcolor, diffusecolor, diffusenormal;
1979 p = G_VECTOR(OFS_PARM0);
1980 VectorClear(ambientcolor);
1981 VectorClear(diffusecolor);
1982 VectorClear(diffusenormal);
1983 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1984 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1985 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1988 #define MAX_QC_CVARS 128
1989 cvar_t qc_cvar[MAX_QC_CVARS];
1992 void PF_registercvar (void)
1996 name = G_STRING(OFS_PARM0);
1997 value = G_STRING(OFS_PARM1);
1998 G_FLOAT(OFS_RETURN) = 0;
1999 // first check to see if it has already been defined
2000 if (Cvar_FindVar (name))
2003 // check for overlap with a command
2004 if (Cmd_Exists (name))
2006 Con_Printf("PF_registercvar: %s is a command\n", name);
2010 if (currentqc_cvar >= MAX_QC_CVARS)
2011 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2013 // copy the name and value
2014 variable = &qc_cvar[currentqc_cvar++];
2015 variable->name = Z_Malloc (strlen(name)+1);
2016 strcpy (variable->name, name);
2017 variable->string = Z_Malloc (strlen(value)+1);
2018 strcpy (variable->string, value);
2019 variable->value = atof (value);
2021 Cvar_RegisterVariable(variable);
2022 G_FLOAT(OFS_RETURN) = 1; // success
2029 returns the minimum of two supplied floats
2036 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2038 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2039 else if (pr_argc >= 3)
2042 float f = G_FLOAT(OFS_PARM0);
2043 for (i = 1;i < pr_argc;i++)
2044 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2045 f = G_FLOAT((OFS_PARM0+i*3));
2046 G_FLOAT(OFS_RETURN) = f;
2050 G_FLOAT(OFS_RETURN) = 0;
2051 PF_WARNING("min: must supply at least 2 floats\n");
2059 returns the maximum of two supplied floats
2066 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2068 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2069 else if (pr_argc >= 3)
2072 float f = G_FLOAT(OFS_PARM0);
2073 for (i = 1;i < pr_argc;i++)
2074 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2075 f = G_FLOAT((OFS_PARM0+i*3));
2076 G_FLOAT(OFS_RETURN) = f;
2080 G_FLOAT(OFS_RETURN) = 0;
2081 PF_WARNING("max: must supply at least 2 floats\n");
2089 returns number bounded by supplied range
2091 min(min, value, max)
2094 void PF_bound (void)
2096 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2103 returns a raised to power b
2110 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2117 copies data from one entity to another
2119 copyentity(src, dst)
2122 void PF_copyentity (void)
2125 in = G_EDICT(OFS_PARM0);
2126 if (in == sv.edicts)
2127 PF_WARNING("copyentity: can not read world entity\n");
2129 PF_WARNING("copyentity: can not read free entity\n");
2130 out = G_EDICT(OFS_PARM1);
2131 if (out == sv.edicts)
2132 PF_WARNING("copyentity: can not modify world entity\n");
2134 PF_WARNING("copyentity: can not modify free entity\n");
2135 memcpy(out->v, in->v, progs->entityfields * 4);
2142 sets the color of a client and broadcasts the update to all connected clients
2144 setcolor(clientent, value)
2147 void PF_setcolor (void)
2153 entnum = G_EDICTNUM(OFS_PARM0);
2154 i = G_FLOAT(OFS_PARM1);
2156 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2158 Con_Print("tried to setcolor a non-client\n");
2162 client = svs.clients + entnum-1;
2163 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2166 client->old_colors = i;
2167 client->edict->v->team = (i & 15) + 1;
2169 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2170 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2171 MSG_WriteByte (&sv.reliable_datagram, i);
2178 effect(origin, modelname, startframe, framecount, framerate)
2181 void PF_effect (void)
2184 s = G_STRING(OFS_PARM1);
2186 PF_WARNING("effect: no model specified\n");
2188 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2191 void PF_te_blood (void)
2193 if (G_FLOAT(OFS_PARM2) < 1)
2195 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2196 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2199 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2200 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2202 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2203 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2204 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2206 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2209 void PF_te_bloodshower (void)
2211 if (G_FLOAT(OFS_PARM3) < 1)
2213 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2214 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2217 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2218 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2220 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2221 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2222 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2224 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2226 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2229 void PF_te_explosionrgb (void)
2231 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2232 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2234 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2235 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2236 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2238 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2239 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2240 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2243 void PF_te_particlecube (void)
2245 if (G_FLOAT(OFS_PARM3) < 1)
2247 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2248 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2250 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2251 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2252 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2255 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2256 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2260 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2262 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2264 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2265 // gravity true/false
2266 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2268 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2271 void PF_te_particlerain (void)
2273 if (G_FLOAT(OFS_PARM3) < 1)
2275 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2276 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2286 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2287 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2288 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2290 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2292 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2295 void PF_te_particlesnow (void)
2297 if (G_FLOAT(OFS_PARM3) < 1)
2299 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2300 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2304 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2306 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2307 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2308 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2310 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2311 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2312 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2314 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2316 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2319 void PF_te_spark (void)
2321 if (G_FLOAT(OFS_PARM2) < 1)
2323 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2324 MSG_WriteByte(&sv.datagram, TE_SPARK);
2326 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2327 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2328 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2330 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2331 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2332 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2334 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2337 void PF_te_gunshotquad (void)
2339 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2340 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
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_spikequad (void)
2349 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2350 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
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_superspikequad (void)
2359 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2360 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
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_explosionquad (void)
2369 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2370 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2372 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2373 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2374 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2377 void PF_te_smallflash (void)
2379 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2380 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2382 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2383 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2384 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2387 void PF_te_customflash (void)
2389 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2391 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2392 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2394 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2395 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2396 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2398 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2400 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2402 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2403 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2404 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2407 void PF_te_gunshot (void)
2409 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2410 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
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_spike (void)
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_SPIKE);
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_superspike (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
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_explosion (void)
2439 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2440 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
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_tarexplosion (void)
2449 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2450 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
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_wizspike (void)
2459 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2460 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
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_knightspike (void)
2469 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2470 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
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_lavasplash (void)
2479 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2480 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
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]);
2487 void PF_te_teleport (void)
2489 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2490 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2494 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2497 void PF_te_explosion2 (void)
2499 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2500 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2504 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2506 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2509 void PF_te_lightning1 (void)
2511 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2512 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2514 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2518 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2520 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2521 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2522 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2525 void PF_te_lightning2 (void)
2527 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2528 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2530 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2534 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2536 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2537 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2538 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2541 void PF_te_lightning3 (void)
2543 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2544 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2546 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2548 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2549 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2550 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2552 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2553 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2554 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2557 void PF_te_beam (void)
2559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2560 MSG_WriteByte(&sv.datagram, TE_BEAM);
2562 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2564 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2565 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2566 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2568 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2569 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2570 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2573 void PF_te_plasmaburn (void)
2575 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2576 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2577 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2578 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2579 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2582 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2585 vec3_t v1, clipplanenormal, normal;
2586 vec_t clipplanedist, clipdist;
2588 if (surf->flags & SURF_PLANEBACK)
2589 VectorNegate(surf->plane->normal, normal);
2591 VectorCopy(surf->plane->normal, normal);
2592 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2594 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2595 VectorNormalizeFast(v1);
2596 CrossProduct(v1, normal, clipplanenormal);
2597 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2598 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2601 clipdist = -clipdist;
2602 VectorMA(out, clipdist, clipplanenormal, out);
2607 static msurface_t *getsurface(edict_t *ed, int surfnum)
2611 if (!ed || ed->e->free)
2613 modelindex = ed->v->modelindex;
2614 if (modelindex < 1 || modelindex >= MAX_MODELS)
2616 model = sv.models[modelindex];
2617 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2619 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2623 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2624 void PF_getsurfacenumpoints(void)
2627 // return 0 if no such surface
2628 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2630 G_FLOAT(OFS_RETURN) = 0;
2634 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2636 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2637 void PF_getsurfacepoint(void)
2642 VectorClear(G_VECTOR(OFS_RETURN));
2643 ed = G_EDICT(OFS_PARM0);
2644 if (!ed || ed->e->free)
2646 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2648 pointnum = G_FLOAT(OFS_PARM2);
2649 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2651 // FIXME: implement rotation/scaling
2652 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2654 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2655 void PF_getsurfacenormal(void)
2658 VectorClear(G_VECTOR(OFS_RETURN));
2659 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2661 // FIXME: implement rotation/scaling
2662 if (surf->flags & SURF_PLANEBACK)
2663 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2665 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2667 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2668 void PF_getsurfacetexture(void)
2671 G_INT(OFS_RETURN) = 0;
2672 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2674 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2676 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2677 void PF_getsurfacenearpoint(void)
2679 int surfnum, best, modelindex;
2681 vec_t dist, bestdist;
2686 G_FLOAT(OFS_RETURN) = -1;
2687 ed = G_EDICT(OFS_PARM0);
2688 point = G_VECTOR(OFS_PARM1);
2690 if (!ed || ed->e->free)
2692 modelindex = ed->v->modelindex;
2693 if (modelindex < 1 || modelindex >= MAX_MODELS)
2695 model = sv.models[modelindex];
2696 if (!model->brushq1.numsurfaces)
2699 // FIXME: implement rotation/scaling
2700 VectorSubtract(point, ed->v->origin, p);
2702 bestdist = 1000000000;
2703 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2705 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2706 dist = PlaneDiff(p, surf->plane);
2708 if (dist < bestdist)
2710 clippointtosurface(surf, p, clipped);
2711 VectorSubtract(clipped, p, clipped);
2712 dist += DotProduct(clipped, clipped);
2713 if (dist < bestdist)
2720 G_FLOAT(OFS_RETURN) = best;
2722 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2723 void PF_getsurfaceclippedpoint(void)
2728 VectorClear(G_VECTOR(OFS_RETURN));
2729 ed = G_EDICT(OFS_PARM0);
2730 if (!ed || ed->e->free)
2732 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2734 // FIXME: implement rotation/scaling
2735 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2736 clippointtosurface(surf, p, out);
2737 // FIXME: implement rotation/scaling
2738 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2741 #define MAX_PRFILES 256
2743 qfile_t *pr_files[MAX_PRFILES];
2745 void PR_Files_Init(void)
2747 memset(pr_files, 0, sizeof(pr_files));
2750 void PR_Files_CloseAll(void)
2753 for (i = 0;i < MAX_PRFILES;i++)
2756 FS_Close(pr_files[i]);
2761 //float(string s) stof = #81; // get numerical value from a string
2764 char string[STRINGTEMP_LENGTH];
2765 PF_VarString(0, string, sizeof(string));
2766 G_FLOAT(OFS_RETURN) = atof(string);
2769 //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
2772 int filenum, mode, i;
2773 char *modestring, *filename;
2774 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2775 if (pr_files[filenum] == NULL)
2777 if (filenum >= MAX_PRFILES)
2779 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2780 G_FLOAT(OFS_RETURN) = -2;
2783 mode = G_FLOAT(OFS_PARM1);
2786 case 0: // FILE_READ
2789 case 1: // FILE_APPEND
2792 case 2: // FILE_WRITE
2796 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2797 G_FLOAT(OFS_RETURN) = -3;
2800 filename = G_STRING(OFS_PARM0);
2801 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2802 // ../ is parent directory on many platforms
2803 // // is parent directory on Amiga
2804 // / at the beginning of a path is root on unix, and parent directory on Amiga
2805 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2806 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2807 for (i = 0;filename[i];i++)
2809 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2811 Con_Printf("PF_fopen: dangerous/confusing/annoying/non-portable filename \"%s\" not allowed. (contains control characters or // or .. or : or \\ or begins with /)\n", filename);
2812 G_FLOAT(OFS_RETURN) = -4;
2816 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2818 if (pr_files[filenum] == NULL && modestring == "rb")
2819 pr_files[filenum] = FS_Open(filename, modestring, false);
2821 if (pr_files[filenum] == NULL)
2822 G_FLOAT(OFS_RETURN) = -1;
2824 G_FLOAT(OFS_RETURN) = filenum;
2827 //void(float fhandle) fclose = #111; // closes a file
2828 void PF_fclose(void)
2830 int filenum = G_FLOAT(OFS_PARM0);
2831 if (filenum < 0 || filenum >= MAX_PRFILES)
2833 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2836 if (pr_files[filenum] == NULL)
2838 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2841 FS_Close(pr_files[filenum]);
2842 pr_files[filenum] = NULL;
2845 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2849 static char string[STRINGTEMP_LENGTH];
2850 int filenum = G_FLOAT(OFS_PARM0);
2851 if (filenum < 0 || filenum >= MAX_PRFILES)
2853 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2856 if (pr_files[filenum] == NULL)
2858 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2864 c = FS_Getc(pr_files[filenum]);
2865 if (c == '\r' || c == '\n' || c < 0)
2867 if (end < STRINGTEMP_LENGTH - 1)
2871 // remove \n following \r
2873 c = FS_Getc(pr_files[filenum]);
2874 if (developer.integer)
2875 Con_Printf("fgets: %s\n", string);
2877 G_INT(OFS_RETURN) = PR_SetString(string);
2879 G_INT(OFS_RETURN) = 0;
2882 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2886 char string[STRINGTEMP_LENGTH];
2887 int filenum = G_FLOAT(OFS_PARM0);
2888 if (filenum < 0 || filenum >= MAX_PRFILES)
2890 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2893 if (pr_files[filenum] == NULL)
2895 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2898 PF_VarString(1, string, sizeof(string));
2899 if ((stringlength = strlen(string)))
2900 FS_Write(pr_files[filenum], string, stringlength);
2901 if (developer.integer)
2902 Con_Printf("fputs: %s\n", string);
2905 //float(string s) strlen = #114; // returns how many characters are in a string
2906 void PF_strlen(void)
2909 s = G_STRING(OFS_PARM0);
2911 G_FLOAT(OFS_RETURN) = strlen(s);
2913 G_FLOAT(OFS_RETURN) = 0;
2916 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2917 void PF_strcat(void)
2919 char *s = PR_GetTempString();
2920 PF_VarString(0, s, STRINGTEMP_LENGTH);
2921 G_INT(OFS_RETURN) = PR_SetString(s);
2924 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2925 void PF_substring(void)
2927 int i, start, length;
2928 char *s, *string = PR_GetTempString();
2929 s = G_STRING(OFS_PARM0);
2930 start = G_FLOAT(OFS_PARM1);
2931 length = G_FLOAT(OFS_PARM2);
2934 for (i = 0;i < start && *s;i++, s++);
2935 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2938 G_INT(OFS_RETURN) = PR_SetString(string);
2941 //vector(string s) stov = #117; // returns vector value from a string
2944 char string[STRINGTEMP_LENGTH];
2945 PF_VarString(0, string, sizeof(string));
2946 Math_atov(string, G_VECTOR(OFS_RETURN));
2949 //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)
2950 void PF_strzone(void)
2953 in = G_STRING(OFS_PARM0);
2954 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2956 G_INT(OFS_RETURN) = PR_SetString(out);
2959 //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!!!)
2960 void PF_strunzone(void)
2962 Mem_Free(G_STRING(OFS_PARM0));
2965 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2966 //this function originally written by KrimZon, made shorter by LordHavoc
2967 void PF_clientcommand (void)
2969 client_t *temp_client;
2972 //find client for this entity
2973 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2974 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2976 Con_Print("PF_clientcommand: entity is not a client\n");
2980 temp_client = host_client;
2981 host_client = svs.clients + i;
2982 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2983 host_client = temp_client;
2986 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2987 //this function originally written by KrimZon, made shorter by LordHavoc
2988 //20040203: rewritten by LordHavoc (no longer uses allocations)
2990 char *tokens[256], tokenbuf[4096];
2991 void PF_tokenize (void)
2995 p = G_STRING(OFS_PARM0);
2999 while(COM_ParseToken(&p, false))
3001 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3003 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3005 tokens[num_tokens++] = tokenbuf + pos;
3006 strcpy(tokenbuf + pos, com_token);
3007 pos += strlen(com_token) + 1;
3010 G_FLOAT(OFS_RETURN) = num_tokens;
3013 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3014 //this function originally written by KrimZon, made shorter by LordHavoc
3017 int token_num = G_FLOAT(OFS_PARM0);
3018 if (token_num >= 0 && token_num < num_tokens)
3019 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3021 G_INT(OFS_RETURN) = PR_SetString("");
3024 //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)
3025 void PF_setattachment (void)
3027 edict_t *e = G_EDICT(OFS_PARM0);
3028 edict_t *tagentity = G_EDICT(OFS_PARM1);
3029 char *tagname = G_STRING(OFS_PARM2);
3035 PF_WARNING("setattachment: can not modify world entity\n");
3037 PF_WARNING("setattachment: can not modify free entity\n");
3039 if (tagentity == NULL)
3040 tagentity = sv.edicts;
3042 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3044 v->edict = EDICT_TO_PROG(tagentity);
3046 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3049 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3051 modelindex = (int)tagentity->v->modelindex;
3052 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3054 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3055 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3056 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3058 if (v->_float == 0 && model->alias.aliasnum_tags)
3059 for (i = 0;i < model->alias.aliasnum_tags;i++)
3060 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3063 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);
3066 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));
3071 /////////////////////////////////////////
3072 // DP_QC_FS_SEARCH extension
3074 // qc fs search handling
3075 #define MAX_SEARCHES 128
3077 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3079 void PR_Search_Init(void)
3081 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3084 void PR_Search_Reset(void)
3087 // reset the fssearch list
3088 for(i = 0; i < MAX_SEARCHES; i++)
3089 if(pr_fssearchlist[i])
3090 FS_FreeSearch(pr_fssearchlist[i]);
3091 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3098 float search_begin(string pattern, float caseinsensitive, float quiet)
3101 void PF_search_begin(void)
3105 int caseinsens, quiet;
3107 pattern = G_STRING(OFS_PARM0);
3109 PR_CheckEmptyString(pattern);
3111 caseinsens = G_FLOAT(OFS_PARM1);
3112 quiet = G_FLOAT(OFS_PARM2);
3114 for(handle = 0; handle < MAX_SEARCHES; handle++)
3115 if(!pr_fssearchlist[handle])
3118 if(handle >= MAX_SEARCHES)
3120 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3121 G_FLOAT(OFS_RETURN) = -2;
3125 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3126 G_FLOAT(OFS_RETURN) = -1;
3128 G_FLOAT(OFS_RETURN) = handle;
3135 void search_end(float handle)
3138 void PF_search_end(void)
3142 handle = G_FLOAT(OFS_PARM0);
3144 if(handle < 0 || handle >= MAX_SEARCHES)
3146 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3149 if(pr_fssearchlist[handle] == NULL)
3151 Con_Printf("PF_search_end: no such handle %i\n", handle);
3155 FS_FreeSearch(pr_fssearchlist[handle]);
3156 pr_fssearchlist[handle] = NULL;
3163 float search_getsize(float handle)
3166 void PF_search_getsize(void)
3170 handle = G_FLOAT(OFS_PARM0);
3172 if(handle < 0 || handle >= MAX_SEARCHES)
3174 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3177 if(pr_fssearchlist[handle] == NULL)
3179 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3183 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3188 VM_search_getfilename
3190 string search_getfilename(float handle, float num)
3193 void PF_search_getfilename(void)
3195 int handle, filenum;
3198 handle = G_FLOAT(OFS_PARM0);
3199 filenum = G_FLOAT(OFS_PARM1);
3201 if(handle < 0 || handle >= MAX_SEARCHES)
3203 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3206 if(pr_fssearchlist[handle] == NULL)
3208 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3211 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3213 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3217 tmp = PR_GetTempString();
3218 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3220 G_INT(OFS_RETURN) = PR_SetString(tmp);
3223 void PF_cvar_string (void)
3229 str = G_STRING(OFS_PARM0);
3230 var = Cvar_FindVar (str);
3232 tmp = PR_GetTempString();
3233 strcpy(tmp, var->string);
3235 G_INT(OFS_RETURN) = PR_SetString(tmp);
3240 builtin_t pr_builtin[] =
3243 PF_makevectors, // #1 void(entity e) makevectors
3244 PF_setorigin, // #2 void(entity e, vector o) setorigin
3245 PF_setmodel, // #3 void(entity e, string m) setmodel
3246 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3247 NULL, // #5 void(entity e, vector min, vector max) setabssize
3248 PF_break, // #6 void() break
3249 PF_random, // #7 float() random
3250 PF_sound, // #8 void(entity e, float chan, string samp) sound
3251 PF_normalize, // #9 vector(vector v) normalize
3252 PF_error, // #10 void(string e) error
3253 PF_objerror, // #11 void(string e) objerror
3254 PF_vlen, // #12 float(vector v) vlen
3255 PF_vectoyaw, // #13 float(vector v) vectoyaw
3256 PF_Spawn, // #14 entity() spawn
3257 PF_Remove, // #15 void(entity e) remove
3258 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3259 PF_checkclient, // #17 entity() clientlist
3260 PF_Find, // #18 entity(entity start, .string fld, string match) find
3261 PF_precache_sound, // #19 void(string s) precache_sound
3262 PF_precache_model, // #20 void(string s) precache_model
3263 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3264 PF_findradius, // #22 entity(vector org, float rad) findradius
3265 PF_bprint, // #23 void(string s) bprint
3266 PF_sprint, // #24 void(entity client, string s) sprint
3267 PF_dprint, // #25 void(string s) dprint
3268 PF_ftos, // #26 void(string s) ftos
3269 PF_vtos, // #27 void(string s) vtos
3270 PF_coredump, // #28 void() coredump
3271 PF_traceon, // #29 void() traceon
3272 PF_traceoff, // #30 void() traceoff
3273 PF_eprint, // #31 void(entity e) eprint
3274 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3276 PF_droptofloor, // #34 float() droptofloor
3277 PF_lightstyle, // #35 void(float style, string value) lightstyle
3278 PF_rint, // #36 float(float v) rint
3279 PF_floor, // #37 float(float v) floor
3280 PF_ceil, // #38 float(float v) ceil
3282 PF_checkbottom, // #40 float(entity e) checkbottom
3283 PF_pointcontents , // #41 float(vector v) pointcontents
3285 PF_fabs, // #43 float(float f) fabs
3286 PF_aim, // #44 vector(entity e, float speed) aim
3287 PF_cvar, // #45 float(string s) cvar
3288 PF_localcmd, // #46 void(string s) localcmd
3289 PF_nextent, // #47 entity(entity e) nextent
3290 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3291 PF_changeyaw, // #49 void() ChangeYaw
3293 PF_vectoangles, // #51 vector(vector v) vectoangles
3294 PF_WriteByte, // #52 void(float to, float f) WriteByte
3295 PF_WriteChar, // #53 void(float to, float f) WriteChar
3296 PF_WriteShort, // #54 void(float to, float f) WriteShort
3297 PF_WriteLong, // #55 void(float to, float f) WriteLong
3298 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3299 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3300 PF_WriteString, // #58 void(float to, string s) WriteString
3301 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3302 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3303 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3304 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3305 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3306 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3307 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3309 SV_MoveToGoal, // #67 void(float step) movetogoal
3310 PF_precache_file, // #68 string(string s) precache_file
3311 PF_makestatic, // #69 void(entity e) makestatic
3312 PF_changelevel, // #70 void(string s) changelevel
3314 PF_cvar_set, // #72 void(string var, string val) cvar_set
3315 PF_centerprint, // #73 void(entity client, strings) centerprint
3316 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3317 PF_precache_model, // #75 string(string s) precache_model2
3318 PF_precache_sound, // #76 string(string s) precache_sound2
3319 PF_precache_file, // #77 string(string s) precache_file2
3320 PF_setspawnparms, // #78 void(entity e) setspawnparms
3323 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3332 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3333 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3334 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3335 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3336 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3337 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3338 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3339 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3340 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3341 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3352 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3353 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3354 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3355 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3356 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3357 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3358 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3359 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3360 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3361 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3362 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3363 a a a a a a a a // #120-199
3364 a a a a a a a a a a // #200-299
3365 a a a a a a a a a a // #300-399
3366 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3367 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3368 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3369 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3370 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3371 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3372 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3373 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3374 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3375 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3376 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3377 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3378 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3379 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3380 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3381 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3382 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3383 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3384 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3385 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3386 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3387 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3388 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3389 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3390 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3391 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3392 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3393 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3394 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3395 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3396 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3397 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3398 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3399 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3400 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3401 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3402 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3403 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3404 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3405 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3406 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3407 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3408 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3409 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3410 PF_search_begin, // #444
3411 PF_search_end, // #445
3412 PF_search_getsize, // #446
3413 PF_search_getfilename, // #447
3414 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3416 a a a a a // #450-499 (LordHavoc)
3419 builtin_t *pr_builtins = pr_builtin;
3420 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3422 void PR_Cmd_Init(void)
3424 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3429 void PR_Cmd_Reset(void)
3431 Mem_EmptyPool(pr_strings_mempool);
3433 PR_Files_CloseAll();