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
113 "DP_QC_SINCOSSQRTPOW "
116 "DP_QC_TRACE_MOVETYPE_HITMODEL "
117 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
118 "DP_QC_VECTORVECTORS "
122 "DP_SND_DIRECTIONLESSATTNNONE "
127 "DP_SV_DRAWONLYTOCLIENT "
129 "DP_SV_EXTERIORMODELTOCLIENT "
130 "DP_SV_NODRAWTOCLIENT "
131 "DP_SV_PLAYERPHYSICS "
132 "DP_SV_ROTATINGBMODEL "
138 "DP_TE_EXPLOSIONRGB "
140 "DP_TE_PARTICLECUBE "
141 "DP_TE_PARTICLERAIN "
142 "DP_TE_PARTICLESNOW "
144 "DP_TE_QUADEFFECTS1 "
147 "DP_TE_STANDARDEFFECTBUILTINS "
150 "KRIMZON_SV_PARSECLIENTCOMMAND "
153 "TENEBRAE_GFX_DLIGHTS "
157 qboolean checkextension(char *name)
162 for (e = ENGINE_EXTENSIONS;*e;e++)
169 while (*e && *e != ' ')
171 if (e - start == len)
172 if (!strncasecmp(start, name, len))
182 returns true if the extension is supported by the server
184 checkextension(extensionname)
187 void PF_checkextension (void)
189 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
196 This is a TERMINAL error, which will kill off the entire server.
205 char string[STRINGTEMP_LENGTH];
207 PF_VarString(0, string, sizeof(string));
208 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
209 ed = PROG_TO_EDICT(pr_global_struct->self);
212 PF_ERROR("Program error");
219 Dumps out self, then an error message. The program is aborted and self is
220 removed, but the level can continue.
225 void PF_objerror (void)
228 char string[STRINGTEMP_LENGTH];
230 PF_VarString(0, string, sizeof(string));
231 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
232 ed = PROG_TO_EDICT(pr_global_struct->self);
242 Writes new values for v_forward, v_up, and v_right based on angles
246 void PF_makevectors (void)
248 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
255 Writes new values for v_forward, v_up, and v_right based on the given forward vector
256 vectorvectors(vector, vector)
259 void PF_vectorvectors (void)
261 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
262 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
269 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.
271 setorigin (entity, origin)
274 void PF_setorigin (void)
279 e = G_EDICT(OFS_PARM0);
281 PF_WARNING("setorigin: can not modify world entity\n");
283 PF_WARNING("setorigin: can not modify free entity\n");
284 org = G_VECTOR(OFS_PARM1);
285 VectorCopy (org, e->v->origin);
286 SV_LinkEdict (e, false);
290 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
294 for (i=0 ; i<3 ; i++)
296 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
298 // set derived values
299 VectorCopy (min, e->v->mins);
300 VectorCopy (max, e->v->maxs);
301 VectorSubtract (max, min, e->v->size);
303 SV_LinkEdict (e, false);
310 the size box is rotated by the current angle
311 LordHavoc: no it isn't...
313 setsize (entity, minvector, maxvector)
316 void PF_setsize (void)
321 e = G_EDICT(OFS_PARM0);
323 PF_WARNING("setsize: can not modify world entity\n");
325 PF_WARNING("setsize: can not modify free entity\n");
326 min = G_VECTOR(OFS_PARM1);
327 max = G_VECTOR(OFS_PARM2);
328 SetMinMaxSize (e, min, max, false);
336 setmodel(entity, model)
339 void PF_setmodel (void)
346 e = G_EDICT(OFS_PARM0);
348 PF_WARNING("setmodel: can not modify world entity\n");
350 PF_WARNING("setmodel: can not modify free entity\n");
351 m = G_STRING(OFS_PARM1);
353 // check to see if model was properly precached
354 for (i=0, check = sv.model_precache ; *check ; i++, check++)
355 if (!strcmp(*check, m))
359 PF_WARNING("setmodel: no precache\n");
362 e->v->model = PR_SetString(*check);
363 e->v->modelindex = i;
365 mod = sv.models[ (int)e->v->modelindex];
368 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
370 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
377 broadcast print to everyone on server
382 void PF_bprint (void)
384 char string[STRINGTEMP_LENGTH];
385 PF_VarString(0, string, sizeof(string));
386 SV_BroadcastPrint(string);
393 single print to a specific client
395 sprint(clientent, value)
398 void PF_sprint (void)
402 char string[STRINGTEMP_LENGTH];
404 entnum = G_EDICTNUM(OFS_PARM0);
406 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
408 Con_Print("tried to sprint to a non-client\n");
412 client = svs.clients + entnum-1;
413 if (!client->netconnection)
415 PF_VarString(1, string, sizeof(string));
416 MSG_WriteChar(&client->message,svc_print);
417 MSG_WriteString(&client->message, string);
425 single print to a specific client
427 centerprint(clientent, value)
430 void PF_centerprint (void)
434 char string[STRINGTEMP_LENGTH];
436 entnum = G_EDICTNUM(OFS_PARM0);
438 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
440 Con_Print("tried to sprint to a non-client\n");
444 client = svs.clients + entnum-1;
445 if (!client->netconnection)
447 PF_VarString(1, string, sizeof(string));
448 MSG_WriteChar(&client->message,svc_centerprint);
449 MSG_WriteString(&client->message, string);
457 vector normalize(vector)
460 void PF_normalize (void)
466 value1 = G_VECTOR(OFS_PARM0);
468 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
472 newvalue[0] = newvalue[1] = newvalue[2] = 0;
476 newvalue[0] = value1[0] * new;
477 newvalue[1] = value1[1] * new;
478 newvalue[2] = value1[2] * new;
481 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
496 value1 = G_VECTOR(OFS_PARM0);
498 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
501 G_FLOAT(OFS_RETURN) = new;
508 float vectoyaw(vector)
511 void PF_vectoyaw (void)
516 value1 = G_VECTOR(OFS_PARM0);
518 if (value1[1] == 0 && value1[0] == 0)
522 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
527 G_FLOAT(OFS_RETURN) = yaw;
535 vector vectoangles(vector)
538 void PF_vectoangles (void)
544 value1 = G_VECTOR(OFS_PARM0);
546 if (value1[1] == 0 && value1[0] == 0)
556 // LordHavoc: optimized a bit
559 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
563 else if (value1[1] > 0)
568 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
569 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
574 G_FLOAT(OFS_RETURN+0) = pitch;
575 G_FLOAT(OFS_RETURN+1) = yaw;
576 G_FLOAT(OFS_RETURN+2) = 0;
583 Returns a number from 0<= num < 1
588 void PF_random (void)
592 num = (rand ()&0x7fff) / ((float)0x7fff);
594 G_FLOAT(OFS_RETURN) = num;
601 particle(origin, color, count)
604 void PF_particle (void)
610 org = G_VECTOR(OFS_PARM0);
611 dir = G_VECTOR(OFS_PARM1);
612 color = G_FLOAT(OFS_PARM2);
613 count = G_FLOAT(OFS_PARM3);
614 SV_StartParticle (org, dir, color, count);
624 void PF_ambientsound (void)
629 float vol, attenuation;
630 int i, soundnum, large;
632 pos = G_VECTOR (OFS_PARM0);
633 samp = G_STRING(OFS_PARM1);
634 vol = G_FLOAT(OFS_PARM2);
635 attenuation = G_FLOAT(OFS_PARM3);
637 // check to see if samp was properly precached
638 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
639 if (!strcmp(*check,samp))
644 Con_Printf("no precache: %s\n", samp);
652 // add an svc_spawnambient command to the level signon packet
655 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
657 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
659 for (i=0 ; i<3 ; i++)
660 MSG_WriteDPCoord(&sv.signon, pos[i]);
663 MSG_WriteShort (&sv.signon, soundnum);
665 MSG_WriteByte (&sv.signon, soundnum);
667 MSG_WriteByte (&sv.signon, vol*255);
668 MSG_WriteByte (&sv.signon, attenuation*64);
676 Each entity can have eight independant sound sources, like voice,
679 Channel 0 is an auto-allocate channel, the others override anything
680 already running on that entity/channel pair.
682 An attenuation of 0 will play full volume everywhere in the level.
683 Larger attenuations will drop off.
695 entity = G_EDICT(OFS_PARM0);
696 channel = G_FLOAT(OFS_PARM1);
697 sample = G_STRING(OFS_PARM2);
698 volume = G_FLOAT(OFS_PARM3) * 255;
699 attenuation = G_FLOAT(OFS_PARM4);
701 if (volume < 0 || volume > 255)
702 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
704 if (attenuation < 0 || attenuation > 4)
705 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
707 if (channel < 0 || channel > 7)
708 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
710 SV_StartSound (entity, channel, sample, volume, attenuation);
722 PF_ERROR("break: break statement\n");
729 Used for use tracing and shot targeting
730 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
731 if the tryents flag is set.
733 traceline (vector1, vector2, tryents)
736 void PF_traceline (void)
743 pr_xfunction->builtinsprofile += 30;
745 v1 = G_VECTOR(OFS_PARM0);
746 v2 = G_VECTOR(OFS_PARM1);
747 move = G_FLOAT(OFS_PARM2);
748 ent = G_EDICT(OFS_PARM3);
750 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
752 pr_global_struct->trace_allsolid = trace.allsolid;
753 pr_global_struct->trace_startsolid = trace.startsolid;
754 pr_global_struct->trace_fraction = trace.fraction;
755 pr_global_struct->trace_inwater = trace.inwater;
756 pr_global_struct->trace_inopen = trace.inopen;
757 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
758 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
759 pr_global_struct->trace_plane_dist = trace.plane.dist;
761 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
763 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
764 // FIXME: add trace_endcontents
772 Used for use tracing and shot targeting
773 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
774 if the tryents flag is set.
776 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
779 // LordHavoc: added this for my own use, VERY useful, similar to traceline
780 void PF_tracebox (void)
782 float *v1, *v2, *m1, *m2;
787 pr_xfunction->builtinsprofile += 30;
789 v1 = G_VECTOR(OFS_PARM0);
790 m1 = G_VECTOR(OFS_PARM1);
791 m2 = G_VECTOR(OFS_PARM2);
792 v2 = G_VECTOR(OFS_PARM3);
793 move = G_FLOAT(OFS_PARM4);
794 ent = G_EDICT(OFS_PARM5);
796 trace = SV_Move (v1, m1, m2, v2, move, ent);
798 pr_global_struct->trace_allsolid = trace.allsolid;
799 pr_global_struct->trace_startsolid = trace.startsolid;
800 pr_global_struct->trace_fraction = trace.fraction;
801 pr_global_struct->trace_inwater = trace.inwater;
802 pr_global_struct->trace_inopen = trace.inopen;
803 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
804 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
805 pr_global_struct->trace_plane_dist = trace.plane.dist;
807 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
809 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
812 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
813 void PF_TraceToss (void)
819 pr_xfunction->builtinsprofile += 600;
821 ent = G_EDICT(OFS_PARM0);
822 if (ent == sv.edicts)
823 PF_WARNING("tracetoss: can not use world entity\n");
824 ignore = G_EDICT(OFS_PARM1);
826 trace = SV_Trace_Toss (ent, ignore);
828 pr_global_struct->trace_allsolid = trace.allsolid;
829 pr_global_struct->trace_startsolid = trace.startsolid;
830 pr_global_struct->trace_fraction = trace.fraction;
831 pr_global_struct->trace_inwater = trace.inwater;
832 pr_global_struct->trace_inopen = trace.inopen;
833 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
834 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
835 pr_global_struct->trace_plane_dist = trace.plane.dist;
837 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
839 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
847 Returns true if the given entity can move to the given position from it's
848 current position by walking or rolling.
850 scalar checkpos (entity, vector)
853 void PF_checkpos (void)
857 //============================================================================
860 qbyte checkpvs[MAX_MAP_LEAFS/8];
862 int PF_newcheckclient (int check)
868 // cycle to the next one
870 check = bound(1, check, svs.maxclients);
871 if (check == svs.maxclients)
879 pr_xfunction->builtinsprofile++;
881 if (i == svs.maxclients+1)
883 // look up the client's edict
885 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
886 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
888 // found a valid client (possibly the same one again)
892 // get the PVS for the entity
893 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
895 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
896 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
905 Returns a client (or object that has a client enemy) that would be a
908 If there is more than one valid option, they are cycled each frame
910 If (self.origin + self.viewofs) is not in the PVS of the current target,
911 it is not returned at all.
916 int c_invis, c_notvis;
917 void PF_checkclient (void)
922 // find a new check if on a new frame
923 if (sv.time - sv.lastchecktime >= 0.1)
925 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
926 sv.lastchecktime = sv.time;
929 // return check if it might be visible
930 ent = EDICT_NUM(sv.lastcheck);
931 if (ent->e->free || ent->v->health <= 0)
933 RETURN_EDICT(sv.edicts);
937 // if current entity can't possibly see the check entity, return 0
938 self = PROG_TO_EDICT(pr_global_struct->self);
939 VectorAdd(self->v->origin, self->v->view_ofs, view);
940 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
943 RETURN_EDICT(sv.edicts);
947 // might be able to see it
952 //============================================================================
959 Sends text over to the client's execution buffer
961 stuffcmd (clientent, value)
964 void PF_stuffcmd (void)
970 entnum = G_EDICTNUM(OFS_PARM0);
971 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
973 Con_Print("Can't stuffcmd to a non-client\n");
976 str = G_STRING(OFS_PARM1);
979 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
980 Host_ClientCommands ("%s", str);
988 Sends text to server console
993 void PF_localcmd (void)
995 Cbuf_AddText(G_STRING(OFS_PARM0));
1007 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1017 void PF_cvar_set (void)
1019 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1026 Returns a chain of entities that have origins within a spherical area
1028 findradius (origin, radius)
1031 void PF_findradius (void)
1033 edict_t *ent, *chain;
1040 chain = (edict_t *)sv.edicts;
1042 org = G_VECTOR(OFS_PARM0);
1043 radius = G_FLOAT(OFS_PARM1);
1044 radius2 = radius * radius;
1046 ent = NEXT_EDICT(sv.edicts);
1047 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1049 pr_xfunction->builtinsprofile++;
1052 if (ent->v->solid == SOLID_NOT)
1055 // LordHavoc: compare against bounding box rather than center,
1056 // and use DotProduct instead of Length, major speedup
1057 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1058 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1059 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1060 if (DotProduct(eorg, eorg) > radius2)
1063 ent->v->chain = EDICT_TO_PROG(chain);
1067 RETURN_EDICT(chain);
1076 void PF_dprint (void)
1078 char string[STRINGTEMP_LENGTH];
1079 if (developer.integer)
1081 PF_VarString(0, string, sizeof(string));
1090 v = G_FLOAT(OFS_PARM0);
1092 s = PR_GetTempString();
1093 if ((float)((int)v) == v)
1094 sprintf(s, "%i", (int)v);
1096 sprintf(s, "%f", v);
1097 G_INT(OFS_RETURN) = PR_SetString(s);
1103 v = G_FLOAT(OFS_PARM0);
1104 G_FLOAT(OFS_RETURN) = fabs(v);
1110 s = PR_GetTempString();
1111 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1112 G_INT(OFS_RETURN) = PR_SetString(s);
1118 s = PR_GetTempString();
1119 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1120 G_INT(OFS_RETURN) = PR_SetString(s);
1123 void PF_Spawn (void)
1126 pr_xfunction->builtinsprofile += 20;
1131 void PF_Remove (void)
1134 pr_xfunction->builtinsprofile += 20;
1136 ed = G_EDICT(OFS_PARM0);
1137 if (ed == sv.edicts)
1138 PF_WARNING("remove: tried to remove world\n");
1139 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1140 PF_WARNING("remove: tried to remove a client\n");
1141 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1142 if (ed->e->free && developer.integer)
1143 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1148 // entity (entity start, .string field, string match) find = #5;
1156 e = G_EDICTNUM(OFS_PARM0);
1157 f = G_INT(OFS_PARM1);
1158 s = G_STRING(OFS_PARM2);
1161 RETURN_EDICT(sv.edicts);
1165 for (e++ ; e < sv.num_edicts ; e++)
1167 pr_xfunction->builtinsprofile++;
1181 RETURN_EDICT(sv.edicts);
1184 // LordHavoc: added this for searching float, int, and entity reference fields
1185 void PF_FindFloat (void)
1192 e = G_EDICTNUM(OFS_PARM0);
1193 f = G_INT(OFS_PARM1);
1194 s = G_FLOAT(OFS_PARM2);
1196 for (e++ ; e < sv.num_edicts ; e++)
1198 pr_xfunction->builtinsprofile++;
1202 if (E_FLOAT(ed,f) == s)
1209 RETURN_EDICT(sv.edicts);
1212 // chained search for strings in entity fields
1213 // entity(.string field, string match) findchain = #402;
1214 void PF_findchain (void)
1219 edict_t *ent, *chain;
1221 chain = (edict_t *)sv.edicts;
1223 f = G_INT(OFS_PARM0);
1224 s = G_STRING(OFS_PARM1);
1227 RETURN_EDICT(sv.edicts);
1231 ent = NEXT_EDICT(sv.edicts);
1232 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1234 pr_xfunction->builtinsprofile++;
1237 t = E_STRING(ent,f);
1243 ent->v->chain = EDICT_TO_PROG(chain);
1247 RETURN_EDICT(chain);
1250 // LordHavoc: chained search for float, int, and entity reference fields
1251 // entity(.string field, float match) findchainfloat = #403;
1252 void PF_findchainfloat (void)
1257 edict_t *ent, *chain;
1259 chain = (edict_t *)sv.edicts;
1261 f = G_INT(OFS_PARM0);
1262 s = G_FLOAT(OFS_PARM1);
1264 ent = NEXT_EDICT(sv.edicts);
1265 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1267 pr_xfunction->builtinsprofile++;
1270 if (E_FLOAT(ent,f) != s)
1273 ent->v->chain = EDICT_TO_PROG(chain);
1277 RETURN_EDICT(chain);
1280 void PR_CheckEmptyString (char *s)
1283 PF_ERROR("Bad string");
1286 void PF_precache_file (void)
1287 { // precache_file is only used to copy files with qcc, it does nothing
1288 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1291 void PF_precache_sound (void)
1296 if (sv.state != ss_loading)
1297 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1299 s = G_STRING(OFS_PARM0);
1300 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1301 PR_CheckEmptyString (s);
1303 for (i=0 ; i<MAX_SOUNDS ; i++)
1305 if (!sv.sound_precache[i])
1307 sv.sound_precache[i] = s;
1310 if (!strcmp(sv.sound_precache[i], s))
1313 PF_ERROR("PF_precache_sound: overflow");
1316 void PF_precache_model (void)
1321 if (sv.state != ss_loading)
1322 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1324 s = G_STRING(OFS_PARM0);
1325 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1327 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1328 PR_CheckEmptyString (s);
1330 for (i=0 ; i<MAX_MODELS ; i++)
1332 if (!sv.model_precache[i])
1334 sv.model_precache[i] = s;
1335 sv.models[i] = Mod_ForName (s, true, false, false);
1338 if (!strcmp(sv.model_precache[i], s))
1341 PF_ERROR("PF_precache_model: overflow");
1345 void PF_coredump (void)
1350 void PF_traceon (void)
1355 void PF_traceoff (void)
1360 void PF_eprint (void)
1362 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1369 float(float yaw, float dist) walkmove
1372 void PF_walkmove (void)
1380 // assume failure if it returns early
1381 G_FLOAT(OFS_RETURN) = 0;
1383 ent = PROG_TO_EDICT(pr_global_struct->self);
1384 if (ent == sv.edicts)
1385 PF_WARNING("walkmove: can not modify world entity\n");
1387 PF_WARNING("walkmove: can not modify free entity\n");
1388 yaw = G_FLOAT(OFS_PARM0);
1389 dist = G_FLOAT(OFS_PARM1);
1391 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1394 yaw = yaw*M_PI*2 / 360;
1396 move[0] = cos(yaw)*dist;
1397 move[1] = sin(yaw)*dist;
1400 // save program state, because SV_movestep may call other progs
1401 oldf = pr_xfunction;
1402 oldself = pr_global_struct->self;
1404 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1407 // restore program state
1408 pr_xfunction = oldf;
1409 pr_global_struct->self = oldself;
1419 void PF_droptofloor (void)
1425 // assume failure if it returns early
1426 G_FLOAT(OFS_RETURN) = 0;
1428 ent = PROG_TO_EDICT(pr_global_struct->self);
1429 if (ent == sv.edicts)
1430 PF_WARNING("droptofloor: can not modify world entity\n");
1432 PF_WARNING("droptofloor: can not modify free entity\n");
1434 VectorCopy (ent->v->origin, end);
1437 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1439 if (trace.fraction != 1)
1441 VectorCopy (trace.endpos, ent->v->origin);
1442 SV_LinkEdict (ent, false);
1443 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1444 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1445 G_FLOAT(OFS_RETURN) = 1;
1446 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1447 ent->e->suspendedinairflag = true;
1455 void(float style, string value) lightstyle
1458 void PF_lightstyle (void)
1465 style = G_FLOAT(OFS_PARM0);
1466 val = G_STRING(OFS_PARM1);
1468 // change the string in sv
1469 sv.lightstyles[style] = val;
1471 // send message to all clients on this server
1472 if (sv.state != ss_active)
1475 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1477 if (client->netconnection)
1479 MSG_WriteChar (&client->message, svc_lightstyle);
1480 MSG_WriteChar (&client->message,style);
1481 MSG_WriteString (&client->message, val);
1489 f = G_FLOAT(OFS_PARM0);
1491 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1493 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1495 void PF_floor (void)
1497 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1501 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1510 void PF_checkbottom (void)
1512 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1520 void PF_pointcontents (void)
1522 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1529 entity nextent(entity)
1532 void PF_nextent (void)
1537 i = G_EDICTNUM(OFS_PARM0);
1540 pr_xfunction->builtinsprofile++;
1542 if (i == sv.num_edicts)
1544 RETURN_EDICT(sv.edicts);
1560 Pick a vector for the player to shoot along
1561 vector aim(entity, missilespeed)
1566 edict_t *ent, *check, *bestent;
1567 vec3_t start, dir, end, bestdir;
1570 float dist, bestdist;
1573 // assume failure if it returns early
1574 VectorClear(G_VECTOR(OFS_RETURN));
1576 ent = G_EDICT(OFS_PARM0);
1577 if (ent == sv.edicts)
1578 PF_WARNING("aim: can not use world entity\n");
1580 PF_WARNING("aim: can not use free entity\n");
1581 speed = G_FLOAT(OFS_PARM1);
1583 VectorCopy (ent->v->origin, start);
1586 // try sending a trace straight
1587 VectorCopy (pr_global_struct->v_forward, dir);
1588 VectorMA (start, 2048, dir, end);
1589 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1590 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1591 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1593 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1598 // try all possible entities
1599 VectorCopy (dir, bestdir);
1600 bestdist = sv_aim.value;
1603 check = NEXT_EDICT(sv.edicts);
1604 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1606 pr_xfunction->builtinsprofile++;
1607 if (check->v->takedamage != DAMAGE_AIM)
1611 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1612 continue; // don't aim at teammate
1613 for (j=0 ; j<3 ; j++)
1614 end[j] = check->v->origin[j]
1615 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1616 VectorSubtract (end, start, dir);
1617 VectorNormalize (dir);
1618 dist = DotProduct (dir, pr_global_struct->v_forward);
1619 if (dist < bestdist)
1620 continue; // to far to turn
1621 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1622 if (tr.ent == check)
1623 { // can shoot at this one
1631 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1632 dist = DotProduct (dir, pr_global_struct->v_forward);
1633 VectorScale (pr_global_struct->v_forward, dist, end);
1635 VectorNormalize (end);
1636 VectorCopy (end, G_VECTOR(OFS_RETURN));
1640 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1648 This was a major timewaster in progs, so it was converted to C
1651 void PF_changeyaw (void)
1654 float ideal, current, move, speed;
1656 ent = PROG_TO_EDICT(pr_global_struct->self);
1657 if (ent == sv.edicts)
1658 PF_WARNING("changeyaw: can not modify world entity\n");
1660 PF_WARNING("changeyaw: can not modify free entity\n");
1661 current = ANGLEMOD(ent->v->angles[1]);
1662 ideal = ent->v->ideal_yaw;
1663 speed = ent->v->yaw_speed;
1665 if (current == ideal)
1667 move = ideal - current;
1668 if (ideal > current)
1689 ent->v->angles[1] = ANGLEMOD (current + move);
1697 void PF_changepitch (void)
1700 float ideal, current, move, speed;
1703 ent = G_EDICT(OFS_PARM0);
1704 if (ent == sv.edicts)
1705 PF_WARNING("changepitch: can not modify world entity\n");
1707 PF_WARNING("changepitch: can not modify free entity\n");
1708 current = ANGLEMOD( ent->v->angles[0] );
1709 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1710 ideal = val->_float;
1713 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1716 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1717 speed = val->_float;
1720 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1724 if (current == ideal)
1726 move = ideal - current;
1727 if (ideal > current)
1748 ent->v->angles[0] = ANGLEMOD (current + move);
1752 ===============================================================================
1756 ===============================================================================
1759 #define MSG_BROADCAST 0 // unreliable to all
1760 #define MSG_ONE 1 // reliable to one (msg_entity)
1761 #define MSG_ALL 2 // reliable to all
1762 #define MSG_INIT 3 // write to the init string
1764 sizebuf_t *WriteDest (void)
1770 dest = G_FLOAT(OFS_PARM0);
1774 return &sv.datagram;
1777 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1778 entnum = NUM_FOR_EDICT(ent);
1779 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1780 Host_Error("WriteDest: tried to write to non-client\n");
1781 return &svs.clients[entnum-1].message;
1784 return &sv.reliable_datagram;
1790 Host_Error("WriteDest: bad destination");
1797 void PF_WriteByte (void)
1799 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1802 void PF_WriteChar (void)
1804 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1807 void PF_WriteShort (void)
1809 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1812 void PF_WriteLong (void)
1814 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1817 void PF_WriteAngle (void)
1819 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1822 void PF_WriteCoord (void)
1824 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1827 void PF_WriteString (void)
1829 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1833 void PF_WriteEntity (void)
1835 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1838 //=============================================================================
1840 void PF_makestatic (void)
1845 ent = G_EDICT(OFS_PARM0);
1846 if (ent == sv.edicts)
1847 PF_WARNING("makestatic: can not modify world entity\n");
1849 PF_WARNING("makestatic: can not modify free entity\n");
1852 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1857 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1858 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1859 MSG_WriteShort (&sv.signon, ent->v->frame);
1863 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1864 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1865 MSG_WriteByte (&sv.signon, ent->v->frame);
1868 MSG_WriteByte (&sv.signon, ent->v->colormap);
1869 MSG_WriteByte (&sv.signon, ent->v->skin);
1870 for (i=0 ; i<3 ; i++)
1872 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1873 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1876 // throw the entity away now
1880 //=============================================================================
1887 void PF_setspawnparms (void)
1893 ent = G_EDICT(OFS_PARM0);
1894 i = NUM_FOR_EDICT(ent);
1895 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1897 Con_Print("tried to setspawnparms on a non-client\n");
1901 // copy spawn parms out of the client_t
1902 client = svs.clients + i-1;
1903 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1904 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1912 void PF_changelevel (void)
1916 // make sure we don't issue two changelevels
1917 if (svs.changelevel_issued)
1919 svs.changelevel_issued = true;
1921 s = G_STRING(OFS_PARM0);
1922 Cbuf_AddText (va("changelevel %s\n",s));
1927 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1932 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1937 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1944 Returns a vector of length < 1
1949 void PF_randomvec (void)
1954 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1955 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1956 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1958 while (DotProduct(temp, temp) >= 1);
1959 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1966 Returns a color vector indicating the lighting at the requested point.
1968 (Internal Operation note: actually measures the light beneath the point, just like
1969 the model lighting on the client)
1974 void PF_GetLight (void)
1976 vec3_t ambientcolor, diffusecolor, diffusenormal;
1978 p = G_VECTOR(OFS_PARM0);
1979 VectorClear(ambientcolor);
1980 VectorClear(diffusecolor);
1981 VectorClear(diffusenormal);
1982 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1983 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1984 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1987 #define MAX_QC_CVARS 128
1988 cvar_t qc_cvar[MAX_QC_CVARS];
1991 void PF_registercvar (void)
1995 name = G_STRING(OFS_PARM0);
1996 value = G_STRING(OFS_PARM1);
1997 G_FLOAT(OFS_RETURN) = 0;
1998 // first check to see if it has already been defined
1999 if (Cvar_FindVar (name))
2002 // check for overlap with a command
2003 if (Cmd_Exists (name))
2005 Con_Printf("PF_registercvar: %s is a command\n", name);
2009 if (currentqc_cvar >= MAX_QC_CVARS)
2010 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2012 // copy the name and value
2013 variable = &qc_cvar[currentqc_cvar++];
2014 variable->name = Z_Malloc (strlen(name)+1);
2015 strcpy (variable->name, name);
2016 variable->string = Z_Malloc (strlen(value)+1);
2017 strcpy (variable->string, value);
2018 variable->value = atof (value);
2020 Cvar_RegisterVariable(variable);
2021 G_FLOAT(OFS_RETURN) = 1; // success
2028 returns the minimum of two supplied floats
2035 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2037 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2038 else if (pr_argc >= 3)
2041 float f = G_FLOAT(OFS_PARM0);
2042 for (i = 1;i < pr_argc;i++)
2043 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2044 f = G_FLOAT((OFS_PARM0+i*3));
2045 G_FLOAT(OFS_RETURN) = f;
2049 G_FLOAT(OFS_RETURN) = 0;
2050 PF_WARNING("min: must supply at least 2 floats\n");
2058 returns the maximum of two supplied floats
2065 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2067 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2068 else if (pr_argc >= 3)
2071 float f = G_FLOAT(OFS_PARM0);
2072 for (i = 1;i < pr_argc;i++)
2073 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2074 f = G_FLOAT((OFS_PARM0+i*3));
2075 G_FLOAT(OFS_RETURN) = f;
2079 G_FLOAT(OFS_RETURN) = 0;
2080 PF_WARNING("max: must supply at least 2 floats\n");
2088 returns number bounded by supplied range
2090 min(min, value, max)
2093 void PF_bound (void)
2095 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2102 returns a raised to power b
2109 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2116 copies data from one entity to another
2118 copyentity(src, dst)
2121 void PF_copyentity (void)
2124 in = G_EDICT(OFS_PARM0);
2125 if (in == sv.edicts)
2126 PF_WARNING("copyentity: can not read world entity\n");
2128 PF_WARNING("copyentity: can not read free entity\n");
2129 out = G_EDICT(OFS_PARM1);
2130 if (out == sv.edicts)
2131 PF_WARNING("copyentity: can not modify world entity\n");
2133 PF_WARNING("copyentity: can not modify free entity\n");
2134 memcpy(out->v, in->v, progs->entityfields * 4);
2141 sets the color of a client and broadcasts the update to all connected clients
2143 setcolor(clientent, value)
2146 void PF_setcolor (void)
2152 entnum = G_EDICTNUM(OFS_PARM0);
2153 i = G_FLOAT(OFS_PARM1);
2155 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2157 Con_Print("tried to setcolor a non-client\n");
2161 client = svs.clients + entnum-1;
2162 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2165 client->old_colors = i;
2166 client->edict->v->team = (i & 15) + 1;
2168 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2169 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2170 MSG_WriteByte (&sv.reliable_datagram, i);
2177 effect(origin, modelname, startframe, framecount, framerate)
2180 void PF_effect (void)
2183 s = G_STRING(OFS_PARM1);
2185 PF_WARNING("effect: no model specified\n");
2187 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2190 void PF_te_blood (void)
2192 if (G_FLOAT(OFS_PARM2) < 1)
2194 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2195 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2197 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2199 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2201 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2202 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2203 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2205 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2208 void PF_te_bloodshower (void)
2210 if (G_FLOAT(OFS_PARM3) < 1)
2212 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2213 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2215 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2217 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2219 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2220 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2221 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2223 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2225 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2228 void PF_te_explosionrgb (void)
2230 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2231 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2233 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2234 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2235 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2237 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2238 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2239 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2242 void PF_te_particlecube (void)
2244 if (G_FLOAT(OFS_PARM3) < 1)
2246 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2247 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2249 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2250 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2251 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2253 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2255 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2257 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2261 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2263 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2264 // gravity true/false
2265 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2267 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2270 void PF_te_particlerain (void)
2272 if (G_FLOAT(OFS_PARM3) < 1)
2274 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2275 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2277 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2285 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2286 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2287 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2289 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2291 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2294 void PF_te_particlesnow (void)
2296 if (G_FLOAT(OFS_PARM3) < 1)
2298 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2301 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2305 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2306 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2307 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2309 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2310 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2311 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2313 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2315 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2318 void PF_te_spark (void)
2320 if (G_FLOAT(OFS_PARM2) < 1)
2322 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2323 MSG_WriteByte(&sv.datagram, TE_SPARK);
2325 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2326 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2327 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2329 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2330 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2331 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2333 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2336 void PF_te_gunshotquad (void)
2338 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2339 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2341 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2342 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2343 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2346 void PF_te_spikequad (void)
2348 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2349 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2351 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2352 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2353 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2356 void PF_te_superspikequad (void)
2358 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2359 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2361 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2362 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2366 void PF_te_explosionquad (void)
2368 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2369 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2371 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2372 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2373 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2376 void PF_te_smallflash (void)
2378 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2379 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2381 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2382 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2383 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2386 void PF_te_customflash (void)
2388 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2390 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2391 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2393 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2394 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2395 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2397 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2399 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2401 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2402 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2403 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2406 void PF_te_gunshot (void)
2408 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2409 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2411 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2412 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2416 void PF_te_spike (void)
2418 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2419 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2421 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2426 void PF_te_superspike (void)
2428 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2429 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2431 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2432 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2436 void PF_te_explosion (void)
2438 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2439 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2441 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2442 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2446 void PF_te_tarexplosion (void)
2448 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2449 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2451 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2452 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2453 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2456 void PF_te_wizspike (void)
2458 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2459 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2461 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2462 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2463 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2466 void PF_te_knightspike (void)
2468 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2469 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2471 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2476 void PF_te_lavasplash (void)
2478 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2479 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2481 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2482 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2483 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2486 void PF_te_teleport (void)
2488 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2489 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2491 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2496 void PF_te_explosion2 (void)
2498 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2499 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2501 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2505 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2508 void PF_te_lightning1 (void)
2510 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2511 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2513 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2515 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2519 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2520 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2521 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2524 void PF_te_lightning2 (void)
2526 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2527 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2529 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2531 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2535 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2536 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2537 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2540 void PF_te_lightning3 (void)
2542 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2543 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2545 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2547 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2548 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2549 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2551 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2552 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2553 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2556 void PF_te_beam (void)
2558 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2559 MSG_WriteByte(&sv.datagram, TE_BEAM);
2561 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2563 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2564 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2565 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2567 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2568 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2569 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2572 void PF_te_plasmaburn (void)
2574 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2575 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2576 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2577 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2578 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2581 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2584 vec3_t v1, clipplanenormal, normal;
2585 vec_t clipplanedist, clipdist;
2587 if (surf->flags & SURF_PLANEBACK)
2588 VectorNegate(surf->plane->normal, normal);
2590 VectorCopy(surf->plane->normal, normal);
2591 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2593 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2594 VectorNormalizeFast(v1);
2595 CrossProduct(v1, normal, clipplanenormal);
2596 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2597 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2600 clipdist = -clipdist;
2601 VectorMA(out, clipdist, clipplanenormal, out);
2606 static msurface_t *getsurface(edict_t *ed, int surfnum)
2610 if (!ed || ed->e->free)
2612 modelindex = ed->v->modelindex;
2613 if (modelindex < 1 || modelindex >= MAX_MODELS)
2615 model = sv.models[modelindex];
2616 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2618 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2622 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2623 void PF_getsurfacenumpoints(void)
2626 // return 0 if no such surface
2627 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2629 G_FLOAT(OFS_RETURN) = 0;
2633 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2635 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2636 void PF_getsurfacepoint(void)
2641 VectorClear(G_VECTOR(OFS_RETURN));
2642 ed = G_EDICT(OFS_PARM0);
2643 if (!ed || ed->e->free)
2645 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2647 pointnum = G_FLOAT(OFS_PARM2);
2648 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2650 // FIXME: implement rotation/scaling
2651 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2653 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2654 void PF_getsurfacenormal(void)
2657 VectorClear(G_VECTOR(OFS_RETURN));
2658 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2660 // FIXME: implement rotation/scaling
2661 if (surf->flags & SURF_PLANEBACK)
2662 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2664 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2666 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2667 void PF_getsurfacetexture(void)
2670 G_INT(OFS_RETURN) = 0;
2671 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2673 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2675 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2676 void PF_getsurfacenearpoint(void)
2678 int surfnum, best, modelindex;
2680 vec_t dist, bestdist;
2685 G_FLOAT(OFS_RETURN) = -1;
2686 ed = G_EDICT(OFS_PARM0);
2687 point = G_VECTOR(OFS_PARM1);
2689 if (!ed || ed->e->free)
2691 modelindex = ed->v->modelindex;
2692 if (modelindex < 1 || modelindex >= MAX_MODELS)
2694 model = sv.models[modelindex];
2695 if (!model->brushq1.numsurfaces)
2698 // FIXME: implement rotation/scaling
2699 VectorSubtract(point, ed->v->origin, p);
2701 bestdist = 1000000000;
2702 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2704 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2705 dist = PlaneDiff(p, surf->plane);
2707 if (dist < bestdist)
2709 clippointtosurface(surf, p, clipped);
2710 VectorSubtract(clipped, p, clipped);
2711 dist += DotProduct(clipped, clipped);
2712 if (dist < bestdist)
2719 G_FLOAT(OFS_RETURN) = best;
2721 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2722 void PF_getsurfaceclippedpoint(void)
2727 VectorClear(G_VECTOR(OFS_RETURN));
2728 ed = G_EDICT(OFS_PARM0);
2729 if (!ed || ed->e->free)
2731 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2733 // FIXME: implement rotation/scaling
2734 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2735 clippointtosurface(surf, p, out);
2736 // FIXME: implement rotation/scaling
2737 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2740 #define MAX_PRFILES 256
2742 qfile_t *pr_files[MAX_PRFILES];
2744 void PR_Files_Init(void)
2746 memset(pr_files, 0, sizeof(pr_files));
2749 void PR_Files_CloseAll(void)
2752 for (i = 0;i < MAX_PRFILES;i++)
2755 FS_Close(pr_files[i]);
2760 //float(string s) stof = #81; // get numerical value from a string
2763 char string[STRINGTEMP_LENGTH];
2764 PF_VarString(0, string, sizeof(string));
2765 G_FLOAT(OFS_RETURN) = atof(string);
2768 //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
2771 int filenum, mode, i;
2772 char *modestring, *filename;
2773 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2774 if (pr_files[filenum] == NULL)
2776 if (filenum >= MAX_PRFILES)
2778 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2779 G_FLOAT(OFS_RETURN) = -2;
2782 mode = G_FLOAT(OFS_PARM1);
2785 case 0: // FILE_READ
2788 case 1: // FILE_APPEND
2791 case 2: // FILE_WRITE
2795 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2796 G_FLOAT(OFS_RETURN) = -3;
2799 filename = G_STRING(OFS_PARM0);
2800 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2801 // ../ is parent directory on many platforms
2802 // // is parent directory on Amiga
2803 // / at the beginning of a path is root on unix, and parent directory on Amiga
2804 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2805 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2806 for (i = 0;filename[i];i++)
2808 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2810 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);
2811 G_FLOAT(OFS_RETURN) = -4;
2815 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2817 if (pr_files[filenum] == NULL && modestring == "rb")
2818 pr_files[filenum] = FS_Open(filename, modestring, false);
2820 if (pr_files[filenum] == NULL)
2821 G_FLOAT(OFS_RETURN) = -1;
2823 G_FLOAT(OFS_RETURN) = filenum;
2826 //void(float fhandle) fclose = #111; // closes a file
2827 void PF_fclose(void)
2829 int filenum = G_FLOAT(OFS_PARM0);
2830 if (filenum < 0 || filenum >= MAX_PRFILES)
2832 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2835 if (pr_files[filenum] == NULL)
2837 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2840 FS_Close(pr_files[filenum]);
2841 pr_files[filenum] = NULL;
2844 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2848 static char string[STRINGTEMP_LENGTH];
2849 int filenum = G_FLOAT(OFS_PARM0);
2850 if (filenum < 0 || filenum >= MAX_PRFILES)
2852 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2855 if (pr_files[filenum] == NULL)
2857 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2863 c = FS_Getc(pr_files[filenum]);
2864 if (c == '\r' || c == '\n' || c < 0)
2866 if (end < STRINGTEMP_LENGTH - 1)
2870 // remove \n following \r
2872 c = FS_Getc(pr_files[filenum]);
2873 if (developer.integer)
2874 Con_Printf("fgets: %s\n", string);
2876 G_INT(OFS_RETURN) = PR_SetString(string);
2878 G_INT(OFS_RETURN) = 0;
2881 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2885 char string[STRINGTEMP_LENGTH];
2886 int filenum = G_FLOAT(OFS_PARM0);
2887 if (filenum < 0 || filenum >= MAX_PRFILES)
2889 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2892 if (pr_files[filenum] == NULL)
2894 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2897 PF_VarString(1, string, sizeof(string));
2898 if ((stringlength = strlen(string)))
2899 FS_Write(pr_files[filenum], string, stringlength);
2900 if (developer.integer)
2901 Con_Printf("fputs: %s\n", string);
2904 //float(string s) strlen = #114; // returns how many characters are in a string
2905 void PF_strlen(void)
2908 s = G_STRING(OFS_PARM0);
2910 G_FLOAT(OFS_RETURN) = strlen(s);
2912 G_FLOAT(OFS_RETURN) = 0;
2915 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2916 void PF_strcat(void)
2918 char *s = PR_GetTempString();
2919 PF_VarString(0, s, STRINGTEMP_LENGTH);
2920 G_INT(OFS_RETURN) = PR_SetString(s);
2923 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2924 void PF_substring(void)
2926 int i, start, length;
2927 char *s, *string = PR_GetTempString();
2928 s = G_STRING(OFS_PARM0);
2929 start = G_FLOAT(OFS_PARM1);
2930 length = G_FLOAT(OFS_PARM2);
2933 for (i = 0;i < start && *s;i++, s++);
2934 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2937 G_INT(OFS_RETURN) = PR_SetString(string);
2940 //vector(string s) stov = #117; // returns vector value from a string
2943 char string[STRINGTEMP_LENGTH];
2944 PF_VarString(0, string, sizeof(string));
2945 Math_atov(string, G_VECTOR(OFS_RETURN));
2948 //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)
2949 void PF_strzone(void)
2952 in = G_STRING(OFS_PARM0);
2953 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2955 G_INT(OFS_RETURN) = PR_SetString(out);
2958 //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!!!)
2959 void PF_strunzone(void)
2961 Mem_Free(G_STRING(OFS_PARM0));
2964 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2965 //this function originally written by KrimZon, made shorter by LordHavoc
2966 void PF_clientcommand (void)
2968 client_t *temp_client;
2971 //find client for this entity
2972 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2973 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2975 Con_Print("PF_clientcommand: entity is not a client\n");
2979 temp_client = host_client;
2980 host_client = svs.clients + i;
2981 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2982 host_client = temp_client;
2985 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2986 //this function originally written by KrimZon, made shorter by LordHavoc
2987 //20040203: rewritten by LordHavoc (no longer uses allocations)
2989 char *tokens[256], tokenbuf[4096];
2990 void PF_tokenize (void)
2994 p = G_STRING(OFS_PARM0);
2998 while(COM_ParseToken(&p, false))
3000 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3002 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3004 tokens[num_tokens++] = tokenbuf + pos;
3005 strcpy(tokenbuf + pos, com_token);
3006 pos += strlen(com_token) + 1;
3009 G_FLOAT(OFS_RETURN) = num_tokens;
3012 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3013 //this function originally written by KrimZon, made shorter by LordHavoc
3016 int token_num = G_FLOAT(OFS_PARM0);
3017 if (token_num >= 0 && token_num < num_tokens)
3018 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3020 G_INT(OFS_RETURN) = PR_SetString("");
3023 //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)
3024 void PF_setattachment (void)
3026 edict_t *e = G_EDICT(OFS_PARM0);
3027 edict_t *tagentity = G_EDICT(OFS_PARM1);
3028 char *tagname = G_STRING(OFS_PARM2);
3034 PF_WARNING("setattachment: can not modify world entity\n");
3036 PF_WARNING("setattachment: can not modify free entity\n");
3038 if (tagentity == NULL)
3039 tagentity = sv.edicts;
3041 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3043 v->edict = EDICT_TO_PROG(tagentity);
3045 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3048 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3050 modelindex = (int)tagentity->v->modelindex;
3051 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3053 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3054 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3055 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3057 if (v->_float == 0 && model->alias.aliasnum_tags)
3058 for (i = 0;i < model->alias.aliasnum_tags;i++)
3059 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3062 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);
3065 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));
3070 /////////////////////////////////////////
3071 // DP_QC_FS_SEARCH extension
3073 // qc fs search handling
3074 #define MAX_SEARCHES 128
3076 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3078 void PR_Search_Init(void)
3080 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3083 void PR_Search_Reset(void)
3086 // reset the fssearch list
3087 for(i = 0; i < MAX_SEARCHES; i++)
3088 if(pr_fssearchlist[i])
3089 FS_FreeSearch(pr_fssearchlist[i]);
3090 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3097 float search_begin(string pattern, float caseinsensitive, float quiet)
3100 void PF_search_begin(void)
3104 int caseinsens, quiet;
3106 pattern = G_STRING(OFS_PARM0);
3108 PR_CheckEmptyString(pattern);
3110 caseinsens = G_FLOAT(OFS_PARM1);
3111 quiet = G_FLOAT(OFS_PARM2);
3113 for(handle = 0; handle < MAX_SEARCHES; handle++)
3114 if(!pr_fssearchlist[handle])
3117 if(handle >= MAX_SEARCHES)
3119 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3120 G_FLOAT(OFS_RETURN) = -2;
3124 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3125 G_FLOAT(OFS_RETURN) = -1;
3127 G_FLOAT(OFS_RETURN) = handle;
3134 void search_end(float handle)
3137 void PF_search_end(void)
3141 handle = G_FLOAT(OFS_PARM0);
3143 if(handle < 0 || handle >= MAX_SEARCHES)
3145 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3148 if(pr_fssearchlist[handle] == NULL)
3150 Con_Printf("PF_search_end: no such handle %i\n", handle);
3154 FS_FreeSearch(pr_fssearchlist[handle]);
3155 pr_fssearchlist[handle] = NULL;
3162 float search_getsize(float handle)
3165 void PF_search_getsize(void)
3169 handle = G_FLOAT(OFS_PARM0);
3171 if(handle < 0 || handle >= MAX_SEARCHES)
3173 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3176 if(pr_fssearchlist[handle] == NULL)
3178 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3182 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3187 VM_search_getfilename
3189 string search_getfilename(float handle, float num)
3192 void PF_search_getfilename(void)
3194 int handle, filenum;
3197 handle = G_FLOAT(OFS_PARM0);
3198 filenum = G_FLOAT(OFS_PARM1);
3200 if(handle < 0 || handle >= MAX_SEARCHES)
3202 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3205 if(pr_fssearchlist[handle] == NULL)
3207 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3210 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3212 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3216 tmp = PR_GetTempString();
3217 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3219 G_INT(OFS_RETURN) = PR_SetString(tmp);
3222 void PF_cvar_string (void)
3228 str = G_STRING(OFS_PARM0);
3229 var = Cvar_FindVar (str);
3231 tmp = PR_GetTempString();
3232 strcpy(tmp, var->string);
3234 G_INT(OFS_RETURN) = PR_SetString(tmp);
3239 builtin_t pr_builtin[] =
3242 PF_makevectors, // #1 void(entity e) makevectors
3243 PF_setorigin, // #2 void(entity e, vector o) setorigin
3244 PF_setmodel, // #3 void(entity e, string m) setmodel
3245 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3246 NULL, // #5 void(entity e, vector min, vector max) setabssize
3247 PF_break, // #6 void() break
3248 PF_random, // #7 float() random
3249 PF_sound, // #8 void(entity e, float chan, string samp) sound
3250 PF_normalize, // #9 vector(vector v) normalize
3251 PF_error, // #10 void(string e) error
3252 PF_objerror, // #11 void(string e) objerror
3253 PF_vlen, // #12 float(vector v) vlen
3254 PF_vectoyaw, // #13 float(vector v) vectoyaw
3255 PF_Spawn, // #14 entity() spawn
3256 PF_Remove, // #15 void(entity e) remove
3257 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3258 PF_checkclient, // #17 entity() clientlist
3259 PF_Find, // #18 entity(entity start, .string fld, string match) find
3260 PF_precache_sound, // #19 void(string s) precache_sound
3261 PF_precache_model, // #20 void(string s) precache_model
3262 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3263 PF_findradius, // #22 entity(vector org, float rad) findradius
3264 PF_bprint, // #23 void(string s) bprint
3265 PF_sprint, // #24 void(entity client, string s) sprint
3266 PF_dprint, // #25 void(string s) dprint
3267 PF_ftos, // #26 void(string s) ftos
3268 PF_vtos, // #27 void(string s) vtos
3269 PF_coredump, // #28 void() coredump
3270 PF_traceon, // #29 void() traceon
3271 PF_traceoff, // #30 void() traceoff
3272 PF_eprint, // #31 void(entity e) eprint
3273 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3275 PF_droptofloor, // #34 float() droptofloor
3276 PF_lightstyle, // #35 void(float style, string value) lightstyle
3277 PF_rint, // #36 float(float v) rint
3278 PF_floor, // #37 float(float v) floor
3279 PF_ceil, // #38 float(float v) ceil
3281 PF_checkbottom, // #40 float(entity e) checkbottom
3282 PF_pointcontents , // #41 float(vector v) pointcontents
3284 PF_fabs, // #43 float(float f) fabs
3285 PF_aim, // #44 vector(entity e, float speed) aim
3286 PF_cvar, // #45 float(string s) cvar
3287 PF_localcmd, // #46 void(string s) localcmd
3288 PF_nextent, // #47 entity(entity e) nextent
3289 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3290 PF_changeyaw, // #49 void() ChangeYaw
3292 PF_vectoangles, // #51 vector(vector v) vectoangles
3293 PF_WriteByte, // #52 void(float to, float f) WriteByte
3294 PF_WriteChar, // #53 void(float to, float f) WriteChar
3295 PF_WriteShort, // #54 void(float to, float f) WriteShort
3296 PF_WriteLong, // #55 void(float to, float f) WriteLong
3297 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3298 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3299 PF_WriteString, // #58 void(float to, string s) WriteString
3300 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3301 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3302 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3303 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3304 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3305 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3306 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3308 SV_MoveToGoal, // #67 void(float step) movetogoal
3309 PF_precache_file, // #68 string(string s) precache_file
3310 PF_makestatic, // #69 void(entity e) makestatic
3311 PF_changelevel, // #70 void(string s) changelevel
3313 PF_cvar_set, // #72 void(string var, string val) cvar_set
3314 PF_centerprint, // #73 void(entity client, strings) centerprint
3315 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3316 PF_precache_model, // #75 string(string s) precache_model2
3317 PF_precache_sound, // #76 string(string s) precache_sound2
3318 PF_precache_file, // #77 string(string s) precache_file2
3319 PF_setspawnparms, // #78 void(entity e) setspawnparms
3322 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3331 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3332 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3333 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3334 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3335 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3336 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3337 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3338 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3339 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3340 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3351 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3352 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3353 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3354 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3355 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3356 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3357 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3358 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3359 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3360 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3361 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3362 a a a a a a a a // #120-199
3363 a a a a a a a a a a // #200-299
3364 a a a a a a a a a a // #300-399
3365 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3366 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3367 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3368 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3369 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3370 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3371 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3372 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3373 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3374 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3375 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3376 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3377 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3378 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3379 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3380 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3381 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3382 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3383 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3384 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3385 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3386 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3387 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3388 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3389 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3390 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3391 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3392 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3393 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3394 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3395 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3396 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3397 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3398 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3399 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3400 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3401 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3402 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3403 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3404 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3405 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3406 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3407 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3408 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3409 PF_search_begin, // #444
3410 PF_search_end, // #445
3411 PF_search_getsize, // #446
3412 PF_search_getfilename, // #447
3413 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3415 a a a a a // #450-499 (LordHavoc)
3418 builtin_t *pr_builtins = pr_builtin;
3419 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3421 void PR_Cmd_Init(void)
3423 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3428 void PR_Cmd_Reset(void)
3430 Mem_EmptyPool(pr_strings_mempool);
3432 PR_Files_CloseAll();