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
25 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
29 ===============================================================================
33 ===============================================================================
37 char *PF_VarString (int first)
40 static char out[4096]; // FIXME: buffer overflow potential
43 for (i = first;i < pr_argc;i++)
44 strcat (out, G_STRING((OFS_PARM0+i*3)));
48 char *ENGINE_EXTENSIONS =
50 "DP_ENT_CUSTOMCOLORMAP "
51 "DP_ENT_EXTERIORMODELTOCLIENT "
52 "DP_ENT_LOWPRECISION "
65 "DP_QC_FINDCHAINFLOAT "
70 "DP_QC_SINCOSSQRTPOW "
73 "DP_QC_VECTORVECTORS "
78 "DP_SV_DRAWONLYTOCLIENT "
80 "DP_SV_EXTERIORMODELTOCLIENT "
81 "DP_SV_NODRAWTOCLIENT "
82 "DP_SV_PLAYERPHYSICS "
97 qboolean checkextension(char *name)
102 for (e = ENGINE_EXTENSIONS;*e;e++)
109 while (*e && *e != ' ')
111 if (e - start == len)
112 if (!strncasecmp(start, name, len))
122 returns true if the extension is supported by the server
124 checkextension(extensionname)
127 void PF_checkextension (void)
129 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
136 This is a TERMINAL error, which will kill off the entire server.
148 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
149 ed = PROG_TO_EDICT(pr_global_struct->self);
152 Host_Error ("Program error");
159 Dumps out self, then an error message. The program is aborted and self is
160 removed, but the level can continue.
165 void PF_objerror (void)
171 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
172 ed = PROG_TO_EDICT(pr_global_struct->self);
182 Writes new values for v_forward, v_up, and v_right based on angles
186 void PF_makevectors (void)
188 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
195 Writes new values for v_forward, v_up, and v_right based on the given forward vector
196 vectorvectors(vector, vector)
199 void PF_vectorvectors (void)
201 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
202 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
209 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.
211 setorigin (entity, origin)
214 void PF_setorigin (void)
219 e = G_EDICT(OFS_PARM0);
220 org = G_VECTOR(OFS_PARM1);
221 VectorCopy (org, e->v->origin);
222 SV_LinkEdict (e, false);
226 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
230 for (i=0 ; i<3 ; i++)
232 Host_Error ("backwards mins/maxs");
234 // set derived values
235 VectorCopy (min, e->v->mins);
236 VectorCopy (max, e->v->maxs);
237 VectorSubtract (max, min, e->v->size);
239 SV_LinkEdict (e, false);
246 the size box is rotated by the current angle
247 LordHavoc: no it isn't...
249 setsize (entity, minvector, maxvector)
252 void PF_setsize (void)
257 e = G_EDICT(OFS_PARM0);
258 min = G_VECTOR(OFS_PARM1);
259 max = G_VECTOR(OFS_PARM2);
260 SetMinMaxSize (e, min, max, false);
268 setmodel(entity, model)
271 void PF_setmodel (void)
278 e = G_EDICT(OFS_PARM0);
279 m = G_STRING(OFS_PARM1);
281 // check to see if model was properly precached
282 for (i=0, check = sv.model_precache ; *check ; i++, check++)
283 if (!strcmp(*check, m))
287 Host_Error ("no precache: %s\n", m);
290 e->v->model = PR_SetString(*check);
291 e->v->modelindex = i;
293 mod = sv.models[ (int)e->v->modelindex];
296 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
298 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
305 broadcast print to everyone on server
310 void PF_bprint (void)
315 SV_BroadcastPrintf ("%s", s);
322 single print to a specific client
324 sprint(clientent, value)
327 void PF_sprint (void)
333 entnum = G_EDICTNUM(OFS_PARM0);
336 if (entnum < 1 || entnum > svs.maxclients)
338 Con_Printf ("tried to sprint to a non-client\n");
342 client = &svs.clients[entnum-1];
344 MSG_WriteChar (&client->message,svc_print);
345 MSG_WriteString (&client->message, s );
353 single print to a specific client
355 centerprint(clientent, value)
358 void PF_centerprint (void)
364 entnum = G_EDICTNUM(OFS_PARM0);
367 if (entnum < 1 || entnum > svs.maxclients)
369 Con_Printf ("tried to sprint to a non-client\n");
373 client = &svs.clients[entnum-1];
375 MSG_WriteChar (&client->message,svc_centerprint);
376 MSG_WriteString (&client->message, s );
384 vector normalize(vector)
387 void PF_normalize (void)
393 value1 = G_VECTOR(OFS_PARM0);
395 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
399 newvalue[0] = newvalue[1] = newvalue[2] = 0;
403 newvalue[0] = value1[0] * new;
404 newvalue[1] = value1[1] * new;
405 newvalue[2] = value1[2] * new;
408 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
423 value1 = G_VECTOR(OFS_PARM0);
425 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
428 G_FLOAT(OFS_RETURN) = new;
435 float vectoyaw(vector)
438 void PF_vectoyaw (void)
443 value1 = G_VECTOR(OFS_PARM0);
445 if (value1[1] == 0 && value1[0] == 0)
449 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
454 G_FLOAT(OFS_RETURN) = yaw;
462 vector vectoangles(vector)
465 void PF_vectoangles (void)
471 value1 = G_VECTOR(OFS_PARM0);
473 if (value1[1] == 0 && value1[0] == 0)
483 // LordHavoc: optimized a bit
486 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
490 else if (value1[1] > 0)
495 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
496 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
501 G_FLOAT(OFS_RETURN+0) = pitch;
502 G_FLOAT(OFS_RETURN+1) = yaw;
503 G_FLOAT(OFS_RETURN+2) = 0;
510 Returns a number from 0<= num < 1
515 void PF_random (void)
519 num = (rand ()&0x7fff) / ((float)0x7fff);
521 G_FLOAT(OFS_RETURN) = num;
528 particle(origin, color, count)
531 void PF_particle (void)
537 org = G_VECTOR(OFS_PARM0);
538 dir = G_VECTOR(OFS_PARM1);
539 color = G_FLOAT(OFS_PARM2);
540 count = G_FLOAT(OFS_PARM3);
541 SV_StartParticle (org, dir, color, count);
551 void PF_ambientsound (void)
556 float vol, attenuation;
557 int i, soundnum, large;
559 pos = G_VECTOR (OFS_PARM0);
560 samp = G_STRING(OFS_PARM1);
561 vol = G_FLOAT(OFS_PARM2);
562 attenuation = G_FLOAT(OFS_PARM3);
564 // check to see if samp was properly precached
565 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
566 if (!strcmp(*check,samp))
571 Con_Printf ("no precache: %s\n", samp);
579 // add an svc_spawnambient command to the level signon packet
582 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
584 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
586 for (i=0 ; i<3 ; i++)
587 MSG_WriteDPCoord(&sv.signon, pos[i]);
590 MSG_WriteShort (&sv.signon, soundnum);
592 MSG_WriteByte (&sv.signon, soundnum);
594 MSG_WriteByte (&sv.signon, vol*255);
595 MSG_WriteByte (&sv.signon, attenuation*64);
603 Each entity can have eight independant sound sources, like voice,
606 Channel 0 is an auto-allocate channel, the others override anything
607 already running on that entity/channel pair.
609 An attenuation of 0 will play full volume everywhere in the level.
610 Larger attenuations will drop off.
622 entity = G_EDICT(OFS_PARM0);
623 channel = G_FLOAT(OFS_PARM1);
624 sample = G_STRING(OFS_PARM2);
625 volume = G_FLOAT(OFS_PARM3) * 255;
626 attenuation = G_FLOAT(OFS_PARM4);
628 if (volume < 0 || volume > 255)
629 Host_Error ("SV_StartSound: volume = %i", volume);
631 if (attenuation < 0 || attenuation > 4)
632 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
634 if (channel < 0 || channel > 7)
635 Host_Error ("SV_StartSound: channel = %i", channel);
637 SV_StartSound (entity, channel, sample, volume, attenuation);
649 Host_Error ("break statement");
656 Used for use tracing and shot targeting
657 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
658 if the tryents flag is set.
660 traceline (vector1, vector2, tryents)
663 void PF_traceline (void)
670 pr_xfunction->builtinsprofile += 30;
672 v1 = G_VECTOR(OFS_PARM0);
673 v2 = G_VECTOR(OFS_PARM1);
674 nomonsters = G_FLOAT(OFS_PARM2);
675 ent = G_EDICT(OFS_PARM3);
677 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
679 pr_global_struct->trace_allsolid = trace.allsolid;
680 pr_global_struct->trace_startsolid = trace.startsolid;
681 pr_global_struct->trace_fraction = trace.fraction;
682 pr_global_struct->trace_inwater = trace.inwater;
683 pr_global_struct->trace_inopen = trace.inopen;
684 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
685 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
686 pr_global_struct->trace_plane_dist = trace.plane.dist;
688 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
690 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
691 // FIXME: add trace_endcontents
699 Used for use tracing and shot targeting
700 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
701 if the tryents flag is set.
703 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
706 // LordHavoc: added this for my own use, VERY useful, similar to traceline
707 void PF_tracebox (void)
709 float *v1, *v2, *m1, *m2;
714 pr_xfunction->builtinsprofile += 30;
716 v1 = G_VECTOR(OFS_PARM0);
717 m1 = G_VECTOR(OFS_PARM1);
718 m2 = G_VECTOR(OFS_PARM2);
719 v2 = G_VECTOR(OFS_PARM3);
720 nomonsters = G_FLOAT(OFS_PARM4);
721 ent = G_EDICT(OFS_PARM5);
723 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
725 pr_global_struct->trace_allsolid = trace.allsolid;
726 pr_global_struct->trace_startsolid = trace.startsolid;
727 pr_global_struct->trace_fraction = trace.fraction;
728 pr_global_struct->trace_inwater = trace.inwater;
729 pr_global_struct->trace_inopen = trace.inopen;
730 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
731 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
732 pr_global_struct->trace_plane_dist = trace.plane.dist;
734 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
736 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
739 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
740 void PF_TraceToss (void)
746 pr_xfunction->builtinsprofile += 600;
748 ent = G_EDICT(OFS_PARM0);
749 ignore = G_EDICT(OFS_PARM1);
751 trace = SV_Trace_Toss (ent, ignore);
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);
772 Returns true if the given entity can move to the given position from it's
773 current position by walking or rolling.
775 scalar checkpos (entity, vector)
778 void PF_checkpos (void)
782 //============================================================================
784 qbyte checkpvs[MAX_MAP_LEAFS/8];
786 int PF_newcheckclient (int check)
794 // cycle to the next one
798 if (check > svs.maxclients)
799 check = svs.maxclients;
801 if (check == svs.maxclients)
808 pr_xfunction->builtinsprofile++;
809 if (i == svs.maxclients+1)
815 break; // didn't find anything else
819 if (ent->v->health <= 0)
821 if ((int)ent->v->flags & FL_NOTARGET)
824 // anything that is a client, or has a client as an enemy
828 // get the PVS for the entity
829 VectorAdd (ent->v->origin, ent->v->view_ofs, org);
830 leaf = Mod_PointInLeaf (org, sv.worldmodel);
831 pvs = Mod_LeafPVS (leaf, sv.worldmodel);
832 memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
841 Returns a client (or object that has a client enemy) that would be a
844 If there is more than one valid option, they are cycled each frame
846 If (self.origin + self.viewofs) is not in the PVS of the current target,
847 it is not returned at all.
852 int c_invis, c_notvis;
853 void PF_checkclient (void)
860 // find a new check if on a new frame
861 if (sv.time - sv.lastchecktime >= 0.1)
863 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
864 sv.lastchecktime = sv.time;
867 // return check if it might be visible
868 ent = EDICT_NUM(sv.lastcheck);
869 if (ent->free || ent->v->health <= 0)
871 RETURN_EDICT(sv.edicts);
875 // if current entity can't possibly see the check entity, return 0
876 self = PROG_TO_EDICT(pr_global_struct->self);
877 VectorAdd (self->v->origin, self->v->view_ofs, view);
878 leaf = Mod_PointInLeaf (view, sv.worldmodel);
881 l = (leaf - sv.worldmodel->leafs) - 1;
882 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
885 RETURN_EDICT(sv.edicts);
890 // might be able to see it
895 //============================================================================
902 Sends text over to the client's execution buffer
904 stuffcmd (clientent, value)
907 void PF_stuffcmd (void)
913 entnum = G_EDICTNUM(OFS_PARM0);
914 if (entnum < 1 || entnum > svs.maxclients)
915 Host_Error ("Parm 0 not a client");
916 str = G_STRING(OFS_PARM1);
919 host_client = &svs.clients[entnum-1];
920 Host_ClientCommands ("%s", str);
928 Sends text over to the client's execution buffer
933 void PF_localcmd (void)
937 str = G_STRING(OFS_PARM0);
952 str = G_STRING(OFS_PARM0);
954 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
964 void PF_cvar_set (void)
968 var = G_STRING(OFS_PARM0);
969 val = G_STRING(OFS_PARM1);
978 Returns a chain of entities that have origins within a spherical area
980 findradius (origin, radius)
983 void PF_findradius (void)
985 edict_t *ent, *chain;
992 chain = (edict_t *)sv.edicts;
994 org = G_VECTOR(OFS_PARM0);
995 radius = G_FLOAT(OFS_PARM1);
996 radius2 = radius * radius;
998 ent = NEXT_EDICT(sv.edicts);
999 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1001 pr_xfunction->builtinsprofile++;
1004 if (ent->v->solid == SOLID_NOT)
1007 // LordHavoc: compare against bounding box rather than center,
1008 // and use DotProduct instead of Length, major speedup
1009 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1010 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1011 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1012 if (DotProduct(eorg, eorg) > radius2)
1015 ent->v->chain = EDICT_TO_PROG(chain);
1019 RETURN_EDICT(chain);
1028 void PF_dprint (void)
1030 Con_DPrintf ("%s",PF_VarString(0));
1033 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
1034 #define STRINGTEMP_BUFFERS 16
1035 #define STRINGTEMP_LENGTH 128
1036 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
1037 static int pr_string_tempindex = 0;
1039 static char *PR_GetTempString(void)
1042 s = pr_string_temp[pr_string_tempindex];
1043 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
1051 v = G_FLOAT(OFS_PARM0);
1053 s = PR_GetTempString();
1054 // LordHavoc: ftos improvement
1055 sprintf (s, "%g", v);
1056 G_INT(OFS_RETURN) = PR_SetString(s);
1062 v = G_FLOAT(OFS_PARM0);
1063 G_FLOAT(OFS_RETURN) = fabs(v);
1069 s = PR_GetTempString();
1070 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1071 G_INT(OFS_RETURN) = PR_SetString(s);
1077 s = PR_GetTempString();
1078 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1079 G_INT(OFS_RETURN) = PR_SetString(s);
1082 void PF_Spawn (void)
1085 pr_xfunction->builtinsprofile += 20;
1090 void PF_Remove (void)
1093 pr_xfunction->builtinsprofile += 20;
1095 ed = G_EDICT(OFS_PARM0);
1096 if (ed == sv.edicts)
1097 Host_Error("remove: tried to remove world\n");
1098 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1099 Host_Error("remove: tried to remove a client\n");
1104 // entity (entity start, .string field, string match) find = #5;
1112 e = G_EDICTNUM(OFS_PARM0);
1113 f = G_INT(OFS_PARM1);
1114 s = G_STRING(OFS_PARM2);
1117 RETURN_EDICT(sv.edicts);
1121 for (e++ ; e < sv.num_edicts ; e++)
1123 pr_xfunction->builtinsprofile++;
1137 RETURN_EDICT(sv.edicts);
1140 // LordHavoc: added this for searching float, int, and entity reference fields
1141 void PF_FindFloat (void)
1148 e = G_EDICTNUM(OFS_PARM0);
1149 f = G_INT(OFS_PARM1);
1150 s = G_FLOAT(OFS_PARM2);
1152 for (e++ ; e < sv.num_edicts ; e++)
1154 pr_xfunction->builtinsprofile++;
1158 if (E_FLOAT(ed,f) == s)
1165 RETURN_EDICT(sv.edicts);
1168 // chained search for strings in entity fields
1169 // entity(.string field, string match) findchain = #402;
1170 void PF_findchain (void)
1175 edict_t *ent, *chain;
1177 chain = (edict_t *)sv.edicts;
1179 f = G_INT(OFS_PARM0);
1180 s = G_STRING(OFS_PARM1);
1183 RETURN_EDICT(sv.edicts);
1187 ent = NEXT_EDICT(sv.edicts);
1188 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1190 pr_xfunction->builtinsprofile++;
1193 t = E_STRING(ent,f);
1199 ent->v->chain = EDICT_TO_PROG(chain);
1203 RETURN_EDICT(chain);
1206 // LordHavoc: chained search for float, int, and entity reference fields
1207 // entity(.string field, float match) findchainfloat = #403;
1208 void PF_findchainfloat (void)
1213 edict_t *ent, *chain;
1215 chain = (edict_t *)sv.edicts;
1217 f = G_INT(OFS_PARM0);
1218 s = G_FLOAT(OFS_PARM1);
1220 ent = NEXT_EDICT(sv.edicts);
1221 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1223 pr_xfunction->builtinsprofile++;
1226 if (E_FLOAT(ent,f) != s)
1229 ent->v->chain = EDICT_TO_PROG(chain);
1233 RETURN_EDICT(chain);
1236 void PR_CheckEmptyString (char *s)
1239 Host_Error ("Bad string");
1242 void PF_precache_file (void)
1243 { // precache_file is only used to copy files with qcc, it does nothing
1244 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1247 void PF_precache_sound (void)
1252 if (sv.state != ss_loading)
1253 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1255 s = G_STRING(OFS_PARM0);
1256 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1257 PR_CheckEmptyString (s);
1259 for (i=0 ; i<MAX_SOUNDS ; i++)
1261 if (!sv.sound_precache[i])
1263 sv.sound_precache[i] = s;
1266 if (!strcmp(sv.sound_precache[i], s))
1269 Host_Error ("PF_precache_sound: overflow");
1272 void PF_precache_model (void)
1277 if (sv.state != ss_loading)
1278 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1280 s = G_STRING(OFS_PARM0);
1281 if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
1283 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1284 PR_CheckEmptyString (s);
1286 for (i=0 ; i<MAX_MODELS ; i++)
1288 if (!sv.model_precache[i])
1290 sv.model_precache[i] = s;
1291 sv.models[i] = Mod_ForName (s, true, false, false);
1294 if (!strcmp(sv.model_precache[i], s))
1297 Host_Error ("PF_precache_model: overflow");
1301 void PF_coredump (void)
1306 void PF_traceon (void)
1311 void PF_traceoff (void)
1316 void PF_eprint (void)
1318 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1325 float(float yaw, float dist) walkmove
1328 void PF_walkmove (void)
1336 ent = PROG_TO_EDICT(pr_global_struct->self);
1337 yaw = G_FLOAT(OFS_PARM0);
1338 dist = G_FLOAT(OFS_PARM1);
1340 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1342 G_FLOAT(OFS_RETURN) = 0;
1346 yaw = yaw*M_PI*2 / 360;
1348 move[0] = cos(yaw)*dist;
1349 move[1] = sin(yaw)*dist;
1352 // save program state, because SV_movestep may call other progs
1353 oldf = pr_xfunction;
1354 oldself = pr_global_struct->self;
1356 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1359 // restore program state
1360 pr_xfunction = oldf;
1361 pr_global_struct->self = oldself;
1371 void PF_droptofloor (void)
1377 ent = PROG_TO_EDICT(pr_global_struct->self);
1379 VectorCopy (ent->v->origin, end);
1382 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1384 if (trace.fraction == 1)
1385 G_FLOAT(OFS_RETURN) = 0;
1388 VectorCopy (trace.endpos, ent->v->origin);
1389 SV_LinkEdict (ent, false);
1390 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1391 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1392 G_FLOAT(OFS_RETURN) = 1;
1393 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1394 ent->suspendedinairflag = true;
1402 void(float style, string value) lightstyle
1405 void PF_lightstyle (void)
1412 style = G_FLOAT(OFS_PARM0);
1413 val = G_STRING(OFS_PARM1);
1415 // change the string in sv
1416 sv.lightstyles[style] = val;
1418 // send message to all clients on this server
1419 if (sv.state != ss_active)
1422 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1423 if (client->active || client->spawned)
1425 MSG_WriteChar (&client->message, svc_lightstyle);
1426 MSG_WriteChar (&client->message,style);
1427 MSG_WriteString (&client->message, val);
1434 f = G_FLOAT(OFS_PARM0);
1436 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1438 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1440 void PF_floor (void)
1442 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1446 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1455 void PF_checkbottom (void)
1457 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1465 void PF_pointcontents (void)
1467 G_FLOAT(OFS_RETURN) = Mod_PointContents(G_VECTOR(OFS_PARM0), sv.worldmodel);
1474 entity nextent(entity)
1477 void PF_nextent (void)
1482 i = G_EDICTNUM(OFS_PARM0);
1485 pr_xfunction->builtinsprofile++;
1487 if (i == sv.num_edicts)
1489 RETURN_EDICT(sv.edicts);
1505 Pick a vector for the player to shoot along
1506 vector aim(entity, missilespeed)
1511 edict_t *ent, *check, *bestent;
1512 vec3_t start, dir, end, bestdir;
1515 float dist, bestdist;
1518 ent = G_EDICT(OFS_PARM0);
1519 speed = G_FLOAT(OFS_PARM1);
1521 VectorCopy (ent->v->origin, start);
1524 // try sending a trace straight
1525 VectorCopy (pr_global_struct->v_forward, dir);
1526 VectorMA (start, 2048, dir, end);
1527 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1528 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1529 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1531 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1536 // try all possible entities
1537 VectorCopy (dir, bestdir);
1538 bestdist = sv_aim.value;
1541 check = NEXT_EDICT(sv.edicts);
1542 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1544 pr_xfunction->builtinsprofile++;
1545 if (check->v->takedamage != DAMAGE_AIM)
1549 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1550 continue; // don't aim at teammate
1551 for (j=0 ; j<3 ; j++)
1552 end[j] = check->v->origin[j]
1553 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1554 VectorSubtract (end, start, dir);
1555 VectorNormalize (dir);
1556 dist = DotProduct (dir, pr_global_struct->v_forward);
1557 if (dist < bestdist)
1558 continue; // to far to turn
1559 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1560 if (tr.ent == check)
1561 { // can shoot at this one
1569 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1570 dist = DotProduct (dir, pr_global_struct->v_forward);
1571 VectorScale (pr_global_struct->v_forward, dist, end);
1573 VectorNormalize (end);
1574 VectorCopy (end, G_VECTOR(OFS_RETURN));
1578 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1586 This was a major timewaster in progs, so it was converted to C
1589 void PF_changeyaw (void)
1592 float ideal, current, move, speed;
1594 ent = PROG_TO_EDICT(pr_global_struct->self);
1595 current = ANGLEMOD(ent->v->angles[1]);
1596 ideal = ent->v->ideal_yaw;
1597 speed = ent->v->yaw_speed;
1599 if (current == ideal)
1601 move = ideal - current;
1602 if (ideal > current)
1623 ent->v->angles[1] = ANGLEMOD (current + move);
1631 void PF_changepitch (void)
1634 float ideal, current, move, speed;
1637 ent = G_EDICT(OFS_PARM0);
1638 current = ANGLEMOD( ent->v->angles[0] );
1639 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1640 ideal = val->_float;
1643 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1646 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1647 speed = val->_float;
1650 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1654 if (current == ideal)
1656 move = ideal - current;
1657 if (ideal > current)
1678 ent->v->angles[0] = ANGLEMOD (current + move);
1682 ===============================================================================
1686 ===============================================================================
1689 #define MSG_BROADCAST 0 // unreliable to all
1690 #define MSG_ONE 1 // reliable to one (msg_entity)
1691 #define MSG_ALL 2 // reliable to all
1692 #define MSG_INIT 3 // write to the init string
1694 sizebuf_t *WriteDest (void)
1700 dest = G_FLOAT(OFS_PARM0);
1704 return &sv.datagram;
1707 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1708 entnum = NUM_FOR_EDICT(ent);
1709 if (entnum < 1 || entnum > svs.maxclients)
1710 Host_Error ("WriteDest: not a client");
1711 return &svs.clients[entnum-1].message;
1714 return &sv.reliable_datagram;
1720 Host_Error ("WriteDest: bad destination");
1727 void PF_WriteByte (void)
1729 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1732 void PF_WriteChar (void)
1734 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1737 void PF_WriteShort (void)
1739 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1742 void PF_WriteLong (void)
1744 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1747 void PF_WriteAngle (void)
1749 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1752 void PF_WriteCoord (void)
1754 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1757 void PF_WriteString (void)
1759 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1763 void PF_WriteEntity (void)
1765 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1768 //=============================================================================
1770 void PF_makestatic (void)
1775 ent = G_EDICT(OFS_PARM0);
1778 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1783 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1784 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1785 MSG_WriteShort (&sv.signon, ent->v->frame);
1789 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1790 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1791 MSG_WriteByte (&sv.signon, ent->v->frame);
1794 MSG_WriteByte (&sv.signon, ent->v->colormap);
1795 MSG_WriteByte (&sv.signon, ent->v->skin);
1796 for (i=0 ; i<3 ; i++)
1798 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1799 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1802 // throw the entity away now
1806 //=============================================================================
1813 void PF_setspawnparms (void)
1819 ent = G_EDICT(OFS_PARM0);
1820 i = NUM_FOR_EDICT(ent);
1821 if (i < 1 || i > svs.maxclients)
1822 Host_Error ("Entity is not a client");
1824 // copy spawn parms out of the client_t
1825 client = svs.clients + (i-1);
1827 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1828 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1836 void PF_changelevel (void)
1840 // make sure we don't issue two changelevels
1841 if (svs.changelevel_issued)
1843 svs.changelevel_issued = true;
1845 s = G_STRING(OFS_PARM0);
1846 Cbuf_AddText (va("changelevel %s\n",s));
1851 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1856 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1861 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1868 Returns a vector of length < 1
1873 void PF_randomvec (void)
1878 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1879 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1880 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1882 while (DotProduct(temp, temp) >= 1);
1883 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1886 void SV_LightPoint (vec3_t color, vec3_t p);
1891 Returns a color vector indicating the lighting at the requested point.
1893 (Internal Operation note: actually measures the light beneath the point, just like
1894 the model lighting on the client)
1899 void PF_GetLight (void)
1903 p = G_VECTOR(OFS_PARM0);
1904 SV_LightPoint (color, p);
1905 VectorCopy (color, G_VECTOR(OFS_RETURN));
1908 #define MAX_QC_CVARS 128
1909 cvar_t qc_cvar[MAX_QC_CVARS];
1912 void PF_registercvar (void)
1916 name = G_STRING(OFS_PARM0);
1917 value = G_STRING(OFS_PARM1);
1918 G_FLOAT(OFS_RETURN) = 0;
1919 // first check to see if it has already been defined
1920 if (Cvar_FindVar (name))
1923 // check for overlap with a command
1924 if (Cmd_Exists (name))
1926 Con_Printf ("PF_registercvar: %s is a command\n", name);
1930 if (currentqc_cvar >= MAX_QC_CVARS)
1931 Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1933 // copy the name and value
1934 variable = &qc_cvar[currentqc_cvar++];
1935 variable->name = Z_Malloc (strlen(name)+1);
1936 strcpy (variable->name, name);
1937 variable->string = Z_Malloc (strlen(value)+1);
1938 strcpy (variable->string, value);
1939 variable->value = atof (value);
1941 Cvar_RegisterVariable(variable);
1942 G_FLOAT(OFS_RETURN) = 1; // success
1949 returns the minimum of two supplied floats
1956 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1958 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
1959 else if (pr_argc >= 3)
1962 float f = G_FLOAT(OFS_PARM0);
1963 for (i = 1;i < pr_argc;i++)
1964 if (G_FLOAT((OFS_PARM0+i*3)) < f)
1965 f = G_FLOAT((OFS_PARM0+i*3));
1966 G_FLOAT(OFS_RETURN) = f;
1969 Host_Error("min: must supply at least 2 floats\n");
1976 returns the maximum of two supplied floats
1983 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1985 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
1986 else if (pr_argc >= 3)
1989 float f = G_FLOAT(OFS_PARM0);
1990 for (i = 1;i < pr_argc;i++)
1991 if (G_FLOAT((OFS_PARM0+i*3)) > f)
1992 f = G_FLOAT((OFS_PARM0+i*3));
1993 G_FLOAT(OFS_RETURN) = f;
1996 Host_Error("max: must supply at least 2 floats\n");
2003 returns number bounded by supplied range
2005 min(min, value, max)
2008 void PF_bound (void)
2010 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2017 returns a raised to power b
2024 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2031 copies data from one entity to another
2033 copyentity(src, dst)
2036 void PF_copyentity (void)
2039 in = G_EDICT(OFS_PARM0);
2040 out = G_EDICT(OFS_PARM1);
2041 memcpy(out->v, in->v, progs->entityfields * 4);
2048 sets the color of a client and broadcasts the update to all connected clients
2050 setcolors(clientent, value)
2053 void PF_setcolors (void)
2058 entnum = G_EDICTNUM(OFS_PARM0);
2059 i = G_FLOAT(OFS_PARM1);
2061 if (entnum < 1 || entnum > svs.maxclients)
2063 Con_Printf ("tried to setcolor a non-client\n");
2067 client = &svs.clients[entnum-1];
2069 client->edict->v->team = (i & 15) + 1;
2071 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2072 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2073 MSG_WriteByte (&sv.reliable_datagram, i);
2080 effect(origin, modelname, startframe, framecount, framerate)
2083 void PF_effect (void)
2086 s = G_STRING(OFS_PARM1);
2088 Host_Error("effect: no model specified\n");
2090 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2093 void PF_te_blood (void)
2095 if (G_FLOAT(OFS_PARM2) < 1)
2097 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2100 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2101 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2102 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2104 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2105 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2106 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2108 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2111 void PF_te_bloodshower (void)
2113 if (G_FLOAT(OFS_PARM3) < 1)
2115 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2118 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2119 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2120 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2122 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2123 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2124 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2126 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2128 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2131 void PF_te_explosionrgb (void)
2133 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2134 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2136 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2137 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2138 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2140 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2141 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2142 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2145 void PF_te_particlecube (void)
2147 if (G_FLOAT(OFS_PARM3) < 1)
2149 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2152 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2153 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2154 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2156 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2157 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2158 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2160 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2161 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2162 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2164 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2166 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2167 // gravity true/false
2168 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2170 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2173 void PF_te_particlerain (void)
2175 if (G_FLOAT(OFS_PARM3) < 1)
2177 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2180 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2181 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2182 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2184 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2185 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2186 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2188 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2189 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2190 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2192 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2194 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2197 void PF_te_particlesnow (void)
2199 if (G_FLOAT(OFS_PARM3) < 1)
2201 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2204 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2205 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2206 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2208 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2209 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2210 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2212 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2213 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2214 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2216 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2218 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2221 void PF_te_spark (void)
2223 if (G_FLOAT(OFS_PARM2) < 1)
2225 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226 MSG_WriteByte(&sv.datagram, TE_SPARK);
2228 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2229 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2230 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2232 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2233 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2234 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2236 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2239 void PF_te_gunshotquad (void)
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2244 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2245 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2246 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2249 void PF_te_spikequad (void)
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2255 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2256 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2259 void PF_te_superspikequad (void)
2261 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2262 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2264 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2265 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2266 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2269 void PF_te_explosionquad (void)
2271 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2272 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2274 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2275 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2279 void PF_te_smallflash (void)
2281 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2282 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2285 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2286 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2289 void PF_te_customflash (void)
2291 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2293 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2294 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2296 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2297 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2298 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2300 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2302 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2304 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2305 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2306 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2309 void PF_te_gunshot (void)
2311 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2312 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2314 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2315 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2316 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2319 void PF_te_spike (void)
2321 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2322 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2324 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2325 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2326 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2329 void PF_te_superspike (void)
2331 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2332 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2334 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2335 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2336 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2339 void PF_te_explosion (void)
2341 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2342 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2344 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2345 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2346 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2349 void PF_te_tarexplosion (void)
2351 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2352 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2354 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2355 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2356 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2359 void PF_te_wizspike (void)
2361 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2362 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2364 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2365 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2366 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2369 void PF_te_knightspike (void)
2371 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2372 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2374 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2375 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2376 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2379 void PF_te_lavasplash (void)
2381 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2382 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2384 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2385 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2386 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2389 void PF_te_teleport (void)
2391 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2392 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
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]);
2399 void PF_te_explosion2 (void)
2401 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2402 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2404 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2405 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2406 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2408 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2411 void PF_te_lightning1 (void)
2413 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2414 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2416 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2418 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2419 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2420 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2424 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2427 void PF_te_lightning2 (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2432 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2434 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2435 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2436 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2438 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2439 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2440 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2443 void PF_te_lightning3 (void)
2445 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2446 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2448 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2450 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2451 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2452 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2454 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2456 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2459 void PF_te_beam (void)
2461 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2462 MSG_WriteByte(&sv.datagram, TE_BEAM);
2464 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2466 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2467 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2468 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2470 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2471 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2475 void PF_te_plasmaburn (void)
2477 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2478 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2479 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2480 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2481 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2484 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2487 vec3_t v1, clipplanenormal, normal;
2488 vec_t clipplanedist, clipdist;
2490 if (surf->flags & SURF_PLANEBACK)
2491 VectorNegate(surf->plane->normal, normal);
2493 VectorCopy(surf->plane->normal, normal);
2494 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2496 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2497 VectorNormalizeFast(v1);
2498 CrossProduct(v1, normal, clipplanenormal);
2499 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2500 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2503 clipdist = -clipdist;
2504 VectorMA(out, clipdist, clipplanenormal, out);
2509 static msurface_t *getsurface(edict_t *ed, int surfnum)
2513 if (!ed || ed->free)
2515 modelindex = ed->v->modelindex;
2516 if (modelindex < 1 || modelindex >= MAX_MODELS)
2518 model = sv.models[modelindex];
2519 if (model->type != mod_brush)
2521 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2523 return model->surfaces + surfnum + model->firstmodelsurface;
2527 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2528 void PF_getsurfacenumpoints(void)
2531 // return 0 if no such surface
2532 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2534 G_FLOAT(OFS_RETURN) = 0;
2538 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2540 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2541 void PF_getsurfacepoint(void)
2546 VectorClear(G_VECTOR(OFS_RETURN));
2547 ed = G_EDICT(OFS_PARM0);
2548 if (!ed || ed->free)
2550 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2552 pointnum = G_FLOAT(OFS_PARM2);
2553 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2555 // FIXME: implement rotation/scaling
2556 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2558 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2559 void PF_getsurfacenormal(void)
2562 VectorClear(G_VECTOR(OFS_RETURN));
2563 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2565 // FIXME: implement rotation/scaling
2566 if (surf->flags & SURF_PLANEBACK)
2567 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2569 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2571 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2572 void PF_getsurfacetexture(void)
2575 G_INT(OFS_RETURN) = 0;
2576 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2578 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2580 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2581 void PF_getsurfacenearpoint(void)
2583 int surfnum, best, modelindex;
2585 vec_t dist, bestdist;
2590 G_FLOAT(OFS_RETURN) = -1;
2591 ed = G_EDICT(OFS_PARM0);
2592 point = G_VECTOR(OFS_PARM1);
2594 if (!ed || ed->free)
2596 modelindex = ed->v->modelindex;
2597 if (modelindex < 1 || modelindex >= MAX_MODELS)
2599 model = sv.models[modelindex];
2600 if (model->type != mod_brush)
2603 // FIXME: implement rotation/scaling
2604 VectorSubtract(point, ed->v->origin, p);
2606 bestdist = 1000000000;
2607 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2609 surf = model->surfaces + surfnum + model->firstmodelsurface;
2610 dist = PlaneDiff(p, surf->plane);
2612 if (dist < bestdist)
2614 clippointtosurface(surf, p, clipped);
2615 VectorSubtract(clipped, p, clipped);
2616 dist += DotProduct(clipped, clipped);
2617 if (dist < bestdist)
2624 G_FLOAT(OFS_RETURN) = best;
2626 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2627 void PF_getsurfaceclippedpoint(void)
2632 VectorClear(G_VECTOR(OFS_RETURN));
2633 ed = G_EDICT(OFS_PARM0);
2634 if (!ed || ed->free)
2636 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2638 // FIXME: implement rotation/scaling
2639 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2640 clippointtosurface(surf, p, out);
2641 // FIXME: implement rotation/scaling
2642 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2645 void PF_Fixme (void)
2647 Host_Error ("unimplemented QC builtin"); // LordHavoc: was misspelled (bulitin)
2652 builtin_t pr_builtin[] =
2655 PF_makevectors, // void(entity e) makevectors = #1;
2656 PF_setorigin, // void(entity e, vector o) setorigin = #2;
2657 PF_setmodel, // void(entity e, string m) setmodel = #3;
2658 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
2659 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
2660 PF_break, // void() break = #6;
2661 PF_random, // float() random = #7;
2662 PF_sound, // void(entity e, float chan, string samp) sound = #8;
2663 PF_normalize, // vector(vector v) normalize = #9;
2664 PF_error, // void(string e) error = #10;
2665 PF_objerror, // void(string e) objerror = #11;
2666 PF_vlen, // float(vector v) vlen = #12;
2667 PF_vectoyaw, // float(vector v) vectoyaw = #13;
2668 PF_Spawn, // entity() spawn = #14;
2669 PF_Remove, // void(entity e) remove = #15;
2670 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
2671 PF_checkclient, // entity() clientlist = #17;
2672 PF_Find, // entity(entity start, .string fld, string match) find = #18;
2673 PF_precache_sound, // void(string s) precache_sound = #19;
2674 PF_precache_model, // void(string s) precache_model = #20;
2675 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
2676 PF_findradius, // entity(vector org, float rad) findradius = #22;
2677 PF_bprint, // void(string s) bprint = #23;
2678 PF_sprint, // void(entity client, string s) sprint = #24;
2679 PF_dprint, // void(string s) dprint = #25;
2680 PF_ftos, // void(string s) ftos = #26;
2681 PF_vtos, // void(string s) vtos = #27;
2685 PF_eprint, // void(entity e) debug print an entire entity
2686 PF_walkmove, // float(float yaw, float dist) walkmove
2687 PF_Fixme, // float(float yaw, float dist) walkmove
2737 PF_precache_sound, // precache_sound2 is different only for qcc
2742 PF_Fixme, // #79 LordHavoc: dunno who owns 79-89, so these are just padding
2754 PF_tracebox, // #90 LordHavoc builtin range (9x)
2755 PF_randomvec, // #91
2757 PF_registercvar, // #93
2762 PF_FindFloat, // #98
2763 PF_checkextension, // #99
2764 #define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme,
2765 #define aa a a a a a a a a a a
2769 PF_copyentity, // #400 LordHavoc: builtin range (4xx)
2770 PF_setcolors, // #401
2771 PF_findchain, // #402
2772 PF_findchainfloat, // #403
2774 PF_te_blood, // #405
2775 PF_te_bloodshower, // #406
2776 PF_te_explosionrgb, // #407
2777 PF_te_particlecube, // #408
2778 PF_te_particlerain, // #409
2779 PF_te_particlesnow, // #410
2780 PF_te_spark, // #411
2781 PF_te_gunshotquad, // #412
2782 PF_te_spikequad, // #413
2783 PF_te_superspikequad, // #414
2784 PF_te_explosionquad, // #415
2785 PF_te_smallflash, // #416
2786 PF_te_customflash, // #417
2787 PF_te_gunshot, // #418
2788 PF_te_spike, // #419
2789 PF_te_superspike, // #420
2790 PF_te_explosion, // #421
2791 PF_te_tarexplosion, // #422
2792 PF_te_wizspike, // #423
2793 PF_te_knightspike, // #424
2794 PF_te_lavasplash, // #425
2795 PF_te_teleport, // #426
2796 PF_te_explosion2, // #427
2797 PF_te_lightning1, // #428
2798 PF_te_lightning2, // #429
2799 PF_te_lightning3, // #430
2801 PF_vectorvectors, // #432
2802 PF_te_plasmaburn, // #433
2803 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2804 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2805 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2806 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2807 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2808 PF_getsurfaceclippedpoint,// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2811 builtin_t *pr_builtins = pr_builtin;
2812 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);