now counts (very approximate) cost of builtin functions called by progs, profile...
[divverent/darkplaces.git] / pr_cmds.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 #include "quakedef.h"
22
23 cvar_t  sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
24
25 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
26
27
28 /*
29 ===============================================================================
30
31                                                 BUILT-IN FUNCTIONS
32
33 ===============================================================================
34 */
35
36
37 char *PF_VarString (int first)
38 {
39         int             i;
40         static char out[4096]; // FIXME: buffer overflow potential
41
42         out[0] = 0;
43         for (i = first;i < pr_argc;i++)
44                 strcat (out, G_STRING((OFS_PARM0+i*3)));
45         return out;
46 }
47
48 char *ENGINE_EXTENSIONS =
49 "DP_ENT_ALPHA "
50 "DP_ENT_CUSTOMCOLORMAP "
51 "DP_ENT_EXTERIORMODELTOCLIENT "
52 "DP_ENT_LOWPRECISION "
53 "DP_ENT_GLOW "
54 "DP_ENT_SCALE "
55 "DP_ENT_VIEWMODEL "
56 "DP_GFX_FOG "
57 "DP_HALFLIFE_MAP "
58 "DP_INPUTBUTTONS "
59 "DP_MONSTERWALK "
60 "DP_MOVETYPEFOLLOW "
61 "DP_QC_CHANGEPITCH "
62 "DP_QC_COPYENTITY "
63 "DP_QC_ETOS "
64 "DP_QC_FINDCHAIN "
65 "DP_QC_FINDCHAINFLOAT "
66 "DP_QC_FINDFLOAT "
67 "DP_QC_GETLIGHT "
68 "DP_QC_MINMAXBOUND "
69 "DP_QC_RANDOMVEC "
70 "DP_QC_SINCOSSQRTPOW "
71 "DP_QC_TRACEBOX "
72 "DP_QC_TRACETOSS "
73 "DP_QC_VECTORVECTORS "
74 "DP_QUAKE2_MODEL "
75 "DP_REGISTERCVAR "
76 "DP_SOLIDCORPSE "
77 "DP_SPRITE32 "
78 "DP_SV_DRAWONLYTOCLIENT "
79 "DP_SV_EFFECT "
80 "DP_SV_EXTERIORMODELTOCLIENT "
81 "DP_SV_NODRAWTOCLIENT "
82 "DP_SV_PLAYERPHYSICS "
83 "DP_SV_SETCOLOR "
84 "DP_SV_SLOWMO "
85 "DP_TE_BLOOD "
86 "DP_TE_BLOODSHOWER "
87 "DP_TE_EXPLOSIONRGB "
88 "DP_TE_PARTICLECUBE "
89 "DP_TE_PARTICLERAIN "
90 "DP_TE_PARTICLESNOW "
91 "DP_TE_SPARK "
92 "NEH_CMD_PLAY2 "
93 "NEH_RESTOREGAME "
94 "TW_SV_STEPCONTROL "
95 ;
96
97 qboolean checkextension(char *name)
98 {
99         int len;
100         char *e, *start;
101         len = strlen(name);
102         for (e = ENGINE_EXTENSIONS;*e;e++)
103         {
104                 while (*e == ' ')
105                         e++;
106                 if (!*e)
107                         break;
108                 start = e;
109                 while (*e && *e != ' ')
110                         e++;
111                 if (e - start == len)
112                         if (!strncasecmp(start, name, len))
113                                 return true;
114         }
115         return false;
116 }
117
118 /*
119 =================
120 PF_checkextension
121
122 returns true if the extension is supported by the server
123
124 checkextension(extensionname)
125 =================
126 */
127 void PF_checkextension (void)
128 {
129         G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
130 }
131
132 /*
133 =================
134 PF_error
135
136 This is a TERMINAL error, which will kill off the entire server.
137 Dumps self.
138
139 error(value)
140 =================
141 */
142 void PF_error (void)
143 {
144         char    *s;
145         edict_t *ed;
146
147         s = PF_VarString(0);
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);
150         ED_Print (ed);
151
152         Host_Error ("Program error");
153 }
154
155 /*
156 =================
157 PF_objerror
158
159 Dumps out self, then an error message.  The program is aborted and self is
160 removed, but the level can continue.
161
162 objerror(value)
163 =================
164 */
165 void PF_objerror (void)
166 {
167         char    *s;
168         edict_t *ed;
169
170         s = PF_VarString(0);
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);
173         ED_Print (ed);
174         ED_Free (ed);
175 }
176
177
178 /*
179 ==============
180 PF_makevectors
181
182 Writes new values for v_forward, v_up, and v_right based on angles
183 makevectors(vector)
184 ==============
185 */
186 void PF_makevectors (void)
187 {
188         AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
189 }
190
191 /*
192 ==============
193 PF_vectorvectors
194
195 Writes new values for v_forward, v_up, and v_right based on the given forward vector
196 vectorvectors(vector, vector)
197 ==============
198 */
199 void PF_vectorvectors (void)
200 {
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);
203 }
204
205 /*
206 =================
207 PF_setorigin
208
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.
210
211 setorigin (entity, origin)
212 =================
213 */
214 void PF_setorigin (void)
215 {
216         edict_t *e;
217         float   *org;
218
219         e = G_EDICT(OFS_PARM0);
220         org = G_VECTOR(OFS_PARM1);
221         VectorCopy (org, e->v->origin);
222         SV_LinkEdict (e, false);
223 }
224
225
226 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
227 {
228         int             i;
229         
230         for (i=0 ; i<3 ; i++)
231                 if (min[i] > max[i])
232                         Host_Error ("backwards mins/maxs");
233
234 // set derived values
235         VectorCopy (min, e->v->mins);
236         VectorCopy (max, e->v->maxs);
237         VectorSubtract (max, min, e->v->size);
238
239         SV_LinkEdict (e, false);
240 }
241
242 /*
243 =================
244 PF_setsize
245
246 the size box is rotated by the current angle
247 LordHavoc: no it isn't...
248
249 setsize (entity, minvector, maxvector)
250 =================
251 */
252 void PF_setsize (void)
253 {
254         edict_t *e;
255         float   *min, *max;
256
257         e = G_EDICT(OFS_PARM0);
258         min = G_VECTOR(OFS_PARM1);
259         max = G_VECTOR(OFS_PARM2);
260         SetMinMaxSize (e, min, max, false);
261 }
262
263
264 /*
265 =================
266 PF_setmodel
267
268 setmodel(entity, model)
269 =================
270 */
271 void PF_setmodel (void)
272 {
273         edict_t *e;
274         char    *m, **check;
275         model_t *mod;
276         int             i;
277
278         e = G_EDICT(OFS_PARM0);
279         m = G_STRING(OFS_PARM1);
280
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))
284                         break;
285
286         if (!*check)
287                 Host_Error ("no precache: %s\n", m);
288
289
290         e->v->model = PR_SetString(*check);
291         e->v->modelindex = i;
292
293         mod = sv.models[ (int)e->v->modelindex];
294
295         if (mod)
296                 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
297         else
298                 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
299 }
300
301 /*
302 =================
303 PF_bprint
304
305 broadcast print to everyone on server
306
307 bprint(value)
308 =================
309 */
310 void PF_bprint (void)
311 {
312         char            *s;
313
314         s = PF_VarString(0);
315         SV_BroadcastPrintf ("%s", s);
316 }
317
318 /*
319 =================
320 PF_sprint
321
322 single print to a specific client
323
324 sprint(clientent, value)
325 =================
326 */
327 void PF_sprint (void)
328 {
329         char            *s;
330         client_t        *client;
331         int                     entnum;
332         
333         entnum = G_EDICTNUM(OFS_PARM0);
334         s = PF_VarString(1);
335         
336         if (entnum < 1 || entnum > svs.maxclients)
337         {
338                 Con_Printf ("tried to sprint to a non-client\n");
339                 return;
340         }
341                 
342         client = &svs.clients[entnum-1];
343                 
344         MSG_WriteChar (&client->message,svc_print);
345         MSG_WriteString (&client->message, s );
346 }
347
348
349 /*
350 =================
351 PF_centerprint
352
353 single print to a specific client
354
355 centerprint(clientent, value)
356 =================
357 */
358 void PF_centerprint (void)
359 {
360         char            *s;
361         client_t        *client;
362         int                     entnum;
363         
364         entnum = G_EDICTNUM(OFS_PARM0);
365         s = PF_VarString(1);
366         
367         if (entnum < 1 || entnum > svs.maxclients)
368         {
369                 Con_Printf ("tried to sprint to a non-client\n");
370                 return;
371         }
372                 
373         client = &svs.clients[entnum-1];
374
375         MSG_WriteChar (&client->message,svc_centerprint);
376         MSG_WriteString (&client->message, s );
377 }
378
379
380 /*
381 =================
382 PF_normalize
383
384 vector normalize(vector)
385 =================
386 */
387 void PF_normalize (void)
388 {
389         float   *value1;
390         vec3_t  newvalue;
391         float   new;
392         
393         value1 = G_VECTOR(OFS_PARM0);
394
395         new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
396         new = sqrt(new);
397         
398         if (new == 0)
399                 newvalue[0] = newvalue[1] = newvalue[2] = 0;
400         else
401         {
402                 new = 1/new;
403                 newvalue[0] = value1[0] * new;
404                 newvalue[1] = value1[1] * new;
405                 newvalue[2] = value1[2] * new;
406         }
407         
408         VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
409 }
410
411 /*
412 =================
413 PF_vlen
414
415 scalar vlen(vector)
416 =================
417 */
418 void PF_vlen (void)
419 {
420         float   *value1;
421         float   new;
422
423         value1 = G_VECTOR(OFS_PARM0);
424
425         new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
426         new = sqrt(new);
427         
428         G_FLOAT(OFS_RETURN) = new;
429 }
430
431 /*
432 =================
433 PF_vectoyaw
434
435 float vectoyaw(vector)
436 =================
437 */
438 void PF_vectoyaw (void)
439 {
440         float   *value1;
441         float   yaw;
442         
443         value1 = G_VECTOR(OFS_PARM0);
444
445         if (value1[1] == 0 && value1[0] == 0)
446                 yaw = 0;
447         else
448         {
449                 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
450                 if (yaw < 0)
451                         yaw += 360;
452         }
453
454         G_FLOAT(OFS_RETURN) = yaw;
455 }
456
457
458 /*
459 =================
460 PF_vectoangles
461
462 vector vectoangles(vector)
463 =================
464 */
465 void PF_vectoangles (void)
466 {
467         float   *value1;
468         float   forward;
469         float   yaw, pitch;
470         
471         value1 = G_VECTOR(OFS_PARM0);
472
473         if (value1[1] == 0 && value1[0] == 0)
474         {
475                 yaw = 0;
476                 if (value1[2] > 0)
477                         pitch = 90;
478                 else
479                         pitch = 270;
480         }
481         else
482         {
483                 // LordHavoc: optimized a bit
484                 if (value1[0])
485                 {
486                         yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
487                         if (yaw < 0)
488                                 yaw += 360;
489                 }
490                 else if (value1[1] > 0)
491                         yaw = 90;
492                 else
493                         yaw = 270;
494
495                 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
496                 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
497                 if (pitch < 0)
498                         pitch += 360;
499         }
500
501         G_FLOAT(OFS_RETURN+0) = pitch;
502         G_FLOAT(OFS_RETURN+1) = yaw;
503         G_FLOAT(OFS_RETURN+2) = 0;
504 }
505
506 /*
507 =================
508 PF_Random
509
510 Returns a number from 0<= num < 1
511
512 random()
513 =================
514 */
515 void PF_random (void)
516 {
517         float           num;
518
519         num = (rand ()&0x7fff) / ((float)0x7fff);
520
521         G_FLOAT(OFS_RETURN) = num;
522 }
523
524 /*
525 =================
526 PF_particle
527
528 particle(origin, color, count)
529 =================
530 */
531 void PF_particle (void)
532 {
533         float           *org, *dir;
534         float           color;
535         float           count;
536                         
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);
542 }
543
544
545 /*
546 =================
547 PF_ambientsound
548
549 =================
550 */
551 void PF_ambientsound (void)
552 {
553         char            **check;
554         char            *samp;
555         float           *pos;
556         float           vol, attenuation;
557         int                     i, soundnum, large;
558
559         pos = G_VECTOR (OFS_PARM0);                     
560         samp = G_STRING(OFS_PARM1);
561         vol = G_FLOAT(OFS_PARM2);
562         attenuation = G_FLOAT(OFS_PARM3);
563         
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))
567                         break;
568
569         if (!*check)
570         {
571                 Con_Printf ("no precache: %s\n", samp);
572                 return;
573         }
574
575         large = false;
576         if (soundnum >= 256)
577                 large = true;
578
579         // add an svc_spawnambient command to the level signon packet
580
581         if (large)
582                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
583         else
584                 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
585
586         for (i=0 ; i<3 ; i++)
587                 MSG_WriteDPCoord(&sv.signon, pos[i]);
588
589         if (large)
590                 MSG_WriteShort (&sv.signon, soundnum);
591         else
592                 MSG_WriteByte (&sv.signon, soundnum);
593
594         MSG_WriteByte (&sv.signon, vol*255);
595         MSG_WriteByte (&sv.signon, attenuation*64);
596
597 }
598
599 /*
600 =================
601 PF_sound
602
603 Each entity can have eight independant sound sources, like voice,
604 weapon, feet, etc.
605
606 Channel 0 is an auto-allocate channel, the others override anything
607 already running on that entity/channel pair.
608
609 An attenuation of 0 will play full volume everywhere in the level.
610 Larger attenuations will drop off.
611
612 =================
613 */
614 void PF_sound (void)
615 {
616         char            *sample;
617         int                     channel;
618         edict_t         *entity;
619         int             volume;
620         float attenuation;
621                 
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);
627         
628         if (volume < 0 || volume > 255)
629                 Host_Error ("SV_StartSound: volume = %i", volume);
630
631         if (attenuation < 0 || attenuation > 4)
632                 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
633
634         if (channel < 0 || channel > 7)
635                 Host_Error ("SV_StartSound: channel = %i", channel);
636
637         SV_StartSound (entity, channel, sample, volume, attenuation);
638 }
639
640 /*
641 =================
642 PF_break
643
644 break()
645 =================
646 */
647 void PF_break (void)
648 {
649         Host_Error ("break statement");
650 }
651
652 /*
653 =================
654 PF_traceline
655
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.
659
660 traceline (vector1, vector2, tryents)
661 =================
662 */
663 void PF_traceline (void)
664 {
665         float   *v1, *v2;
666         trace_t trace;
667         int             nomonsters;
668         edict_t *ent;
669
670         pr_xfunction->builtinsprofile += 30;
671
672         v1 = G_VECTOR(OFS_PARM0);
673         v2 = G_VECTOR(OFS_PARM1);
674         nomonsters = G_FLOAT(OFS_PARM2);
675         ent = G_EDICT(OFS_PARM3);
676
677         trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
678
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;
687         if (trace.ent)
688                 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
689         else
690                 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
691         // FIXME: add trace_endcontents
692 }
693
694
695 /*
696 =================
697 PF_tracebox
698
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.
702
703 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
704 =================
705 */
706 // LordHavoc: added this for my own use, VERY useful, similar to traceline
707 void PF_tracebox (void)
708 {
709         float   *v1, *v2, *m1, *m2;
710         trace_t trace;
711         int             nomonsters;
712         edict_t *ent;
713
714         pr_xfunction->builtinsprofile += 30;
715
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);
722
723         trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
724
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;
733         if (trace.ent)
734                 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
735         else
736                 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
737 }
738
739 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
740 void PF_TraceToss (void)
741 {
742         trace_t trace;
743         edict_t *ent;
744         edict_t *ignore;
745
746         pr_xfunction->builtinsprofile += 600;
747
748         ent = G_EDICT(OFS_PARM0);
749         ignore = G_EDICT(OFS_PARM1);
750
751         trace = SV_Trace_Toss (ent, ignore);
752
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;
761         if (trace.ent)
762                 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
763         else
764                 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
765 }
766
767
768 /*
769 =================
770 PF_checkpos
771
772 Returns true if the given entity can move to the given position from it's
773 current position by walking or rolling.
774 FIXME: make work...
775 scalar checkpos (entity, vector)
776 =================
777 */
778 void PF_checkpos (void)
779 {
780 }
781
782 //============================================================================
783
784 qbyte checkpvs[MAX_MAP_LEAFS/8];
785
786 int PF_newcheckclient (int check)
787 {
788         int             i;
789         qbyte   *pvs;
790         edict_t *ent;
791         mleaf_t *leaf;
792         vec3_t  org;
793
794 // cycle to the next one
795
796         if (check < 1)
797                 check = 1;
798         if (check > svs.maxclients)
799                 check = svs.maxclients;
800
801         if (check == svs.maxclients)
802                 i = 1;
803         else
804                 i = check + 1;
805
806         for ( ;  ; i++)
807         {
808                 pr_xfunction->builtinsprofile++;
809                 if (i == svs.maxclients+1)
810                         i = 1;
811
812                 ent = EDICT_NUM(i);
813
814                 if (i == check)
815                         break;  // didn't find anything else
816
817                 if (ent->free)
818                         continue;
819                 if (ent->v->health <= 0)
820                         continue;
821                 if ((int)ent->v->flags & FL_NOTARGET)
822                         continue;
823
824         // anything that is a client, or has a client as an enemy
825                 break;
826         }
827
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 );
833
834         return i;
835 }
836
837 /*
838 =================
839 PF_checkclient
840
841 Returns a client (or object that has a client enemy) that would be a
842 valid target.
843
844 If there is more than one valid option, they are cycled each frame
845
846 If (self.origin + self.viewofs) is not in the PVS of the current target,
847 it is not returned at all.
848
849 name checkclient ()
850 =================
851 */
852 int c_invis, c_notvis;
853 void PF_checkclient (void)
854 {
855         edict_t *ent, *self;
856         mleaf_t *leaf;
857         int             l;
858         vec3_t  view;
859
860         // find a new check if on a new frame
861         if (sv.time - sv.lastchecktime >= 0.1)
862         {
863                 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
864                 sv.lastchecktime = sv.time;
865         }
866
867         // return check if it might be visible
868         ent = EDICT_NUM(sv.lastcheck);
869         if (ent->free || ent->v->health <= 0)
870         {
871                 RETURN_EDICT(sv.edicts);
872                 return;
873         }
874
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);
879         if (leaf)
880         {
881                 l = (leaf - sv.worldmodel->leafs) - 1;
882                 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
883                 {
884                         c_notvis++;
885                         RETURN_EDICT(sv.edicts);
886                         return;
887                 }
888         }
889
890         // might be able to see it
891         c_invis++;
892         RETURN_EDICT(ent);
893 }
894
895 //============================================================================
896
897
898 /*
899 =================
900 PF_stuffcmd
901
902 Sends text over to the client's execution buffer
903
904 stuffcmd (clientent, value)
905 =================
906 */
907 void PF_stuffcmd (void)
908 {
909         int             entnum;
910         char    *str;
911         client_t        *old;
912
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);
917
918         old = host_client;
919         host_client = &svs.clients[entnum-1];
920         Host_ClientCommands ("%s", str);
921         host_client = old;
922 }
923
924 /*
925 =================
926 PF_localcmd
927
928 Sends text over to the client's execution buffer
929
930 localcmd (string)
931 =================
932 */
933 void PF_localcmd (void)
934 {
935         char    *str;
936
937         str = G_STRING(OFS_PARM0);
938         Cbuf_AddText (str);
939 }
940
941 /*
942 =================
943 PF_cvar
944
945 float cvar (string)
946 =================
947 */
948 void PF_cvar (void)
949 {
950         char    *str;
951
952         str = G_STRING(OFS_PARM0);
953
954         G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
955 }
956
957 /*
958 =================
959 PF_cvar_set
960
961 float cvar (string)
962 =================
963 */
964 void PF_cvar_set (void)
965 {
966         char    *var, *val;
967
968         var = G_STRING(OFS_PARM0);
969         val = G_STRING(OFS_PARM1);
970
971         Cvar_Set (var, val);
972 }
973
974 /*
975 =================
976 PF_findradius
977
978 Returns a chain of entities that have origins within a spherical area
979
980 findradius (origin, radius)
981 =================
982 */
983 void PF_findradius (void)
984 {
985         edict_t *ent, *chain;
986         float radius;
987         float radius2;
988         float *org;
989         float eorg[3];
990         int i;
991
992         chain = (edict_t *)sv.edicts;
993
994         org = G_VECTOR(OFS_PARM0);
995         radius = G_FLOAT(OFS_PARM1);
996         radius2 = radius * radius;
997
998         ent = NEXT_EDICT(sv.edicts);
999         for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1000         {
1001                 pr_xfunction->builtinsprofile++;
1002                 if (ent->free)
1003                         continue;
1004                 if (ent->v->solid == SOLID_NOT)
1005                         continue;
1006
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)
1013                         continue;
1014
1015                 ent->v->chain = EDICT_TO_PROG(chain);
1016                 chain = ent;
1017         }
1018
1019         RETURN_EDICT(chain);
1020 }
1021
1022
1023 /*
1024 =========
1025 PF_dprint
1026 =========
1027 */
1028 void PF_dprint (void)
1029 {
1030         Con_DPrintf ("%s",PF_VarString(0));
1031 }
1032
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;
1038
1039 static char *PR_GetTempString(void)
1040 {
1041         char *s;
1042         s = pr_string_temp[pr_string_tempindex];
1043         pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
1044         return s;
1045 }
1046
1047 void PF_ftos (void)
1048 {
1049         float v;
1050         char *s;
1051         v = G_FLOAT(OFS_PARM0);
1052
1053         s = PR_GetTempString();
1054         // LordHavoc: ftos improvement
1055         sprintf (s, "%g", v);
1056         G_INT(OFS_RETURN) = PR_SetString(s);
1057 }
1058
1059 void PF_fabs (void)
1060 {
1061         float   v;
1062         v = G_FLOAT(OFS_PARM0);
1063         G_FLOAT(OFS_RETURN) = fabs(v);
1064 }
1065
1066 void PF_vtos (void)
1067 {
1068         char *s;
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);
1072 }
1073
1074 void PF_etos (void)
1075 {
1076         char *s;
1077         s = PR_GetTempString();
1078         sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1079         G_INT(OFS_RETURN) = PR_SetString(s);
1080 }
1081
1082 void PF_Spawn (void)
1083 {
1084         edict_t *ed;
1085         pr_xfunction->builtinsprofile += 20;
1086         ed = ED_Alloc();
1087         RETURN_EDICT(ed);
1088 }
1089
1090 void PF_Remove (void)
1091 {
1092         edict_t *ed;
1093         pr_xfunction->builtinsprofile += 20;
1094
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");
1100         ED_Free (ed);
1101 }
1102
1103
1104 // entity (entity start, .string field, string match) find = #5;
1105 void PF_Find (void)
1106 {
1107         int             e;
1108         int             f;
1109         char    *s, *t;
1110         edict_t *ed;
1111
1112         e = G_EDICTNUM(OFS_PARM0);
1113         f = G_INT(OFS_PARM1);
1114         s = G_STRING(OFS_PARM2);
1115         if (!s || !s[0])
1116         {
1117                 RETURN_EDICT(sv.edicts);
1118                 return;
1119         }
1120
1121         for (e++ ; e < sv.num_edicts ; e++)
1122         {
1123                 pr_xfunction->builtinsprofile++;
1124                 ed = EDICT_NUM(e);
1125                 if (ed->free)
1126                         continue;
1127                 t = E_STRING(ed,f);
1128                 if (!t)
1129                         continue;
1130                 if (!strcmp(t,s))
1131                 {
1132                         RETURN_EDICT(ed);
1133                         return;
1134                 }
1135         }
1136
1137         RETURN_EDICT(sv.edicts);
1138 }
1139
1140 // LordHavoc: added this for searching float, int, and entity reference fields
1141 void PF_FindFloat (void)
1142 {
1143         int             e;
1144         int             f;
1145         float   s;
1146         edict_t *ed;
1147
1148         e = G_EDICTNUM(OFS_PARM0);
1149         f = G_INT(OFS_PARM1);
1150         s = G_FLOAT(OFS_PARM2);
1151
1152         for (e++ ; e < sv.num_edicts ; e++)
1153         {
1154                 pr_xfunction->builtinsprofile++;
1155                 ed = EDICT_NUM(e);
1156                 if (ed->free)
1157                         continue;
1158                 if (E_FLOAT(ed,f) == s)
1159                 {
1160                         RETURN_EDICT(ed);
1161                         return;
1162                 }
1163         }
1164
1165         RETURN_EDICT(sv.edicts);
1166 }
1167
1168 // chained search for strings in entity fields
1169 // entity(.string field, string match) findchain = #402;
1170 void PF_findchain (void)
1171 {
1172         int             i;
1173         int             f;
1174         char    *s, *t;
1175         edict_t *ent, *chain;
1176
1177         chain = (edict_t *)sv.edicts;
1178
1179         f = G_INT(OFS_PARM0);
1180         s = G_STRING(OFS_PARM1);
1181         if (!s || !s[0])
1182         {
1183                 RETURN_EDICT(sv.edicts);
1184                 return;
1185         }
1186
1187         ent = NEXT_EDICT(sv.edicts);
1188         for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1189         {
1190                 pr_xfunction->builtinsprofile++;
1191                 if (ent->free)
1192                         continue;
1193                 t = E_STRING(ent,f);
1194                 if (!t)
1195                         continue;
1196                 if (strcmp(t,s))
1197                         continue;
1198
1199                 ent->v->chain = EDICT_TO_PROG(chain);
1200                 chain = ent;
1201         }
1202
1203         RETURN_EDICT(chain);
1204 }
1205
1206 // LordHavoc: chained search for float, int, and entity reference fields
1207 // entity(.string field, float match) findchainfloat = #403;
1208 void PF_findchainfloat (void)
1209 {
1210         int             i;
1211         int             f;
1212         float   s;
1213         edict_t *ent, *chain;
1214
1215         chain = (edict_t *)sv.edicts;
1216
1217         f = G_INT(OFS_PARM0);
1218         s = G_FLOAT(OFS_PARM1);
1219
1220         ent = NEXT_EDICT(sv.edicts);
1221         for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1222         {
1223                 pr_xfunction->builtinsprofile++;
1224                 if (ent->free)
1225                         continue;
1226                 if (E_FLOAT(ent,f) != s)
1227                         continue;
1228
1229                 ent->v->chain = EDICT_TO_PROG(chain);
1230                 chain = ent;
1231         }
1232
1233         RETURN_EDICT(chain);
1234 }
1235
1236 void PR_CheckEmptyString (char *s)
1237 {
1238         if (s[0] <= ' ')
1239                 Host_Error ("Bad string");
1240 }
1241
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);
1245 }
1246
1247 void PF_precache_sound (void)
1248 {
1249         char    *s;
1250         int             i;
1251
1252         if (sv.state != ss_loading)
1253                 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1254
1255         s = G_STRING(OFS_PARM0);
1256         G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1257         PR_CheckEmptyString (s);
1258
1259         for (i=0 ; i<MAX_SOUNDS ; i++)
1260         {
1261                 if (!sv.sound_precache[i])
1262                 {
1263                         sv.sound_precache[i] = s;
1264                         return;
1265                 }
1266                 if (!strcmp(sv.sound_precache[i], s))
1267                         return;
1268         }
1269         Host_Error ("PF_precache_sound: overflow");
1270 }
1271
1272 void PF_precache_model (void)
1273 {
1274         char    *s;
1275         int             i;
1276
1277         if (sv.state != ss_loading)
1278                 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1279
1280         s = G_STRING(OFS_PARM0);
1281         if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
1282                 return;
1283         G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1284         PR_CheckEmptyString (s);
1285
1286         for (i=0 ; i<MAX_MODELS ; i++)
1287         {
1288                 if (!sv.model_precache[i])
1289                 {
1290                         sv.model_precache[i] = s;
1291                         sv.models[i] = Mod_ForName (s, true, false, false);
1292                         return;
1293                 }
1294                 if (!strcmp(sv.model_precache[i], s))
1295                         return;
1296         }
1297         Host_Error ("PF_precache_model: overflow");
1298 }
1299
1300
1301 void PF_coredump (void)
1302 {
1303         ED_PrintEdicts ();
1304 }
1305
1306 void PF_traceon (void)
1307 {
1308         pr_trace = true;
1309 }
1310
1311 void PF_traceoff (void)
1312 {
1313         pr_trace = false;
1314 }
1315
1316 void PF_eprint (void)
1317 {
1318         ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1319 }
1320
1321 /*
1322 ===============
1323 PF_walkmove
1324
1325 float(float yaw, float dist) walkmove
1326 ===============
1327 */
1328 void PF_walkmove (void)
1329 {
1330         edict_t *ent;
1331         float   yaw, dist;
1332         vec3_t  move;
1333         mfunction_t     *oldf;
1334         int     oldself;
1335
1336         ent = PROG_TO_EDICT(pr_global_struct->self);
1337         yaw = G_FLOAT(OFS_PARM0);
1338         dist = G_FLOAT(OFS_PARM1);
1339
1340         if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1341         {
1342                 G_FLOAT(OFS_RETURN) = 0;
1343                 return;
1344         }
1345
1346         yaw = yaw*M_PI*2 / 360;
1347
1348         move[0] = cos(yaw)*dist;
1349         move[1] = sin(yaw)*dist;
1350         move[2] = 0;
1351
1352 // save program state, because SV_movestep may call other progs
1353         oldf = pr_xfunction;
1354         oldself = pr_global_struct->self;
1355
1356         G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1357
1358
1359 // restore program state
1360         pr_xfunction = oldf;
1361         pr_global_struct->self = oldself;
1362 }
1363
1364 /*
1365 ===============
1366 PF_droptofloor
1367
1368 void() droptofloor
1369 ===============
1370 */
1371 void PF_droptofloor (void)
1372 {
1373         edict_t         *ent;
1374         vec3_t          end;
1375         trace_t         trace;
1376
1377         ent = PROG_TO_EDICT(pr_global_struct->self);
1378
1379         VectorCopy (ent->v->origin, end);
1380         end[2] -= 256;
1381
1382         trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1383
1384         if (trace.fraction == 1)
1385                 G_FLOAT(OFS_RETURN) = 0;
1386         else
1387         {
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;
1395         }
1396 }
1397
1398 /*
1399 ===============
1400 PF_lightstyle
1401
1402 void(float style, string value) lightstyle
1403 ===============
1404 */
1405 void PF_lightstyle (void)
1406 {
1407         int             style;
1408         char    *val;
1409         client_t        *client;
1410         int                     j;
1411
1412         style = G_FLOAT(OFS_PARM0);
1413         val = G_STRING(OFS_PARM1);
1414
1415 // change the string in sv
1416         sv.lightstyles[style] = val;
1417
1418 // send message to all clients on this server
1419         if (sv.state != ss_active)
1420                 return;
1421
1422         for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1423                 if (client->active || client->spawned)
1424                 {
1425                         MSG_WriteChar (&client->message, svc_lightstyle);
1426                         MSG_WriteChar (&client->message,style);
1427                         MSG_WriteString (&client->message, val);
1428                 }
1429 }
1430
1431 void PF_rint (void)
1432 {
1433         float   f;
1434         f = G_FLOAT(OFS_PARM0);
1435         if (f > 0)
1436                 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1437         else
1438                 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1439 }
1440 void PF_floor (void)
1441 {
1442         G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1443 }
1444 void PF_ceil (void)
1445 {
1446         G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1447 }
1448
1449
1450 /*
1451 =============
1452 PF_checkbottom
1453 =============
1454 */
1455 void PF_checkbottom (void)
1456 {
1457         G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1458 }
1459
1460 /*
1461 =============
1462 PF_pointcontents
1463 =============
1464 */
1465 void PF_pointcontents (void)
1466 {
1467         G_FLOAT(OFS_RETURN) = Mod_PointContents(G_VECTOR(OFS_PARM0), sv.worldmodel);
1468 }
1469
1470 /*
1471 =============
1472 PF_nextent
1473
1474 entity nextent(entity)
1475 =============
1476 */
1477 void PF_nextent (void)
1478 {
1479         int             i;
1480         edict_t *ent;
1481
1482         i = G_EDICTNUM(OFS_PARM0);
1483         while (1)
1484         {
1485                 pr_xfunction->builtinsprofile++;
1486                 i++;
1487                 if (i == sv.num_edicts)
1488                 {
1489                         RETURN_EDICT(sv.edicts);
1490                         return;
1491                 }
1492                 ent = EDICT_NUM(i);
1493                 if (!ent->free)
1494                 {
1495                         RETURN_EDICT(ent);
1496                         return;
1497                 }
1498         }
1499 }
1500
1501 /*
1502 =============
1503 PF_aim
1504
1505 Pick a vector for the player to shoot along
1506 vector aim(entity, missilespeed)
1507 =============
1508 */
1509 void PF_aim (void)
1510 {
1511         edict_t *ent, *check, *bestent;
1512         vec3_t  start, dir, end, bestdir;
1513         int             i, j;
1514         trace_t tr;
1515         float   dist, bestdist;
1516         float   speed;
1517
1518         ent = G_EDICT(OFS_PARM0);
1519         speed = G_FLOAT(OFS_PARM1);
1520
1521         VectorCopy (ent->v->origin, start);
1522         start[2] += 20;
1523
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) )
1530         {
1531                 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1532                 return;
1533         }
1534
1535
1536 // try all possible entities
1537         VectorCopy (dir, bestdir);
1538         bestdist = sv_aim.value;
1539         bestent = NULL;
1540
1541         check = NEXT_EDICT(sv.edicts);
1542         for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1543         {
1544                 pr_xfunction->builtinsprofile++;
1545                 if (check->v->takedamage != DAMAGE_AIM)
1546                         continue;
1547                 if (check == ent)
1548                         continue;
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
1562                         bestdist = dist;
1563                         bestent = check;
1564                 }
1565         }
1566
1567         if (bestent)
1568         {
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);
1572                 end[2] = dir[2];
1573                 VectorNormalize (end);
1574                 VectorCopy (end, G_VECTOR(OFS_RETURN));
1575         }
1576         else
1577         {
1578                 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1579         }
1580 }
1581
1582 /*
1583 ==============
1584 PF_changeyaw
1585
1586 This was a major timewaster in progs, so it was converted to C
1587 ==============
1588 */
1589 void PF_changeyaw (void)
1590 {
1591         edict_t         *ent;
1592         float           ideal, current, move, speed;
1593
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;
1598
1599         if (current == ideal)
1600                 return;
1601         move = ideal - current;
1602         if (ideal > current)
1603         {
1604                 if (move >= 180)
1605                         move = move - 360;
1606         }
1607         else
1608         {
1609                 if (move <= -180)
1610                         move = move + 360;
1611         }
1612         if (move > 0)
1613         {
1614                 if (move > speed)
1615                         move = speed;
1616         }
1617         else
1618         {
1619                 if (move < -speed)
1620                         move = -speed;
1621         }
1622
1623         ent->v->angles[1] = ANGLEMOD (current + move);
1624 }
1625
1626 /*
1627 ==============
1628 PF_changepitch
1629 ==============
1630 */
1631 void PF_changepitch (void)
1632 {
1633         edict_t         *ent;
1634         float           ideal, current, move, speed;
1635         eval_t          *val;
1636
1637         ent = G_EDICT(OFS_PARM0);
1638         current = ANGLEMOD( ent->v->angles[0] );
1639         if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1640                 ideal = val->_float;
1641         else
1642         {
1643                 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1644                 return;
1645         }
1646         if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1647                 speed = val->_float;
1648         else
1649         {
1650                 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1651                 return;
1652         }
1653
1654         if (current == ideal)
1655                 return;
1656         move = ideal - current;
1657         if (ideal > current)
1658         {
1659                 if (move >= 180)
1660                         move = move - 360;
1661         }
1662         else
1663         {
1664                 if (move <= -180)
1665                         move = move + 360;
1666         }
1667         if (move > 0)
1668         {
1669                 if (move > speed)
1670                         move = speed;
1671         }
1672         else
1673         {
1674                 if (move < -speed)
1675                         move = -speed;
1676         }
1677
1678         ent->v->angles[0] = ANGLEMOD (current + move);
1679 }
1680
1681 /*
1682 ===============================================================================
1683
1684 MESSAGE WRITING
1685
1686 ===============================================================================
1687 */
1688
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
1693
1694 sizebuf_t *WriteDest (void)
1695 {
1696         int             entnum;
1697         int             dest;
1698         edict_t *ent;
1699
1700         dest = G_FLOAT(OFS_PARM0);
1701         switch (dest)
1702         {
1703         case MSG_BROADCAST:
1704                 return &sv.datagram;
1705
1706         case MSG_ONE:
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;
1712
1713         case MSG_ALL:
1714                 return &sv.reliable_datagram;
1715
1716         case MSG_INIT:
1717                 return &sv.signon;
1718
1719         default:
1720                 Host_Error ("WriteDest: bad destination");
1721                 break;
1722         }
1723
1724         return NULL;
1725 }
1726
1727 void PF_WriteByte (void)
1728 {
1729         MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1730 }
1731
1732 void PF_WriteChar (void)
1733 {
1734         MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1735 }
1736
1737 void PF_WriteShort (void)
1738 {
1739         MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1740 }
1741
1742 void PF_WriteLong (void)
1743 {
1744         MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1745 }
1746
1747 void PF_WriteAngle (void)
1748 {
1749         MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1750 }
1751
1752 void PF_WriteCoord (void)
1753 {
1754         MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1755 }
1756
1757 void PF_WriteString (void)
1758 {
1759         MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1760 }
1761
1762
1763 void PF_WriteEntity (void)
1764 {
1765         MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1766 }
1767
1768 //=============================================================================
1769
1770 void PF_makestatic (void)
1771 {
1772         edict_t *ent;
1773         int i, large;
1774
1775         ent = G_EDICT(OFS_PARM0);
1776
1777         large = false;
1778         if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1779                 large = true;
1780
1781         if (large)
1782         {
1783                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1784                 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1785                 MSG_WriteShort (&sv.signon, ent->v->frame);
1786         }
1787         else
1788         {
1789                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1790                 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1791                 MSG_WriteByte (&sv.signon, ent->v->frame);
1792         }
1793
1794         MSG_WriteByte (&sv.signon, ent->v->colormap);
1795         MSG_WriteByte (&sv.signon, ent->v->skin);
1796         for (i=0 ; i<3 ; i++)
1797         {
1798                 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1799                 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1800         }
1801
1802 // throw the entity away now
1803         ED_Free (ent);
1804 }
1805
1806 //=============================================================================
1807
1808 /*
1809 ==============
1810 PF_setspawnparms
1811 ==============
1812 */
1813 void PF_setspawnparms (void)
1814 {
1815         edict_t *ent;
1816         int             i;
1817         client_t        *client;
1818
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");
1823
1824         // copy spawn parms out of the client_t
1825         client = svs.clients + (i-1);
1826
1827         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1828                 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1829 }
1830
1831 /*
1832 ==============
1833 PF_changelevel
1834 ==============
1835 */
1836 void PF_changelevel (void)
1837 {
1838         char    *s;
1839
1840 // make sure we don't issue two changelevels
1841         if (svs.changelevel_issued)
1842                 return;
1843         svs.changelevel_issued = true;
1844
1845         s = G_STRING(OFS_PARM0);
1846         Cbuf_AddText (va("changelevel %s\n",s));
1847 }
1848
1849 void PF_sin (void)
1850 {
1851         G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1852 }
1853
1854 void PF_cos (void)
1855 {
1856         G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1857 }
1858
1859 void PF_sqrt (void)
1860 {
1861         G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1862 }
1863
1864 /*
1865 =================
1866 PF_RandomVec
1867
1868 Returns a vector of length < 1
1869
1870 randomvec()
1871 =================
1872 */
1873 void PF_randomvec (void)
1874 {
1875         vec3_t          temp;
1876         do
1877         {
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;
1881         }
1882         while (DotProduct(temp, temp) >= 1);
1883         VectorCopy (temp, G_VECTOR(OFS_RETURN));
1884 }
1885
1886 void SV_LightPoint (vec3_t color, vec3_t p);
1887 /*
1888 =================
1889 PF_GetLight
1890
1891 Returns a color vector indicating the lighting at the requested point.
1892
1893 (Internal Operation note: actually measures the light beneath the point, just like
1894                           the model lighting on the client)
1895
1896 getlight(vector)
1897 =================
1898 */
1899 void PF_GetLight (void)
1900 {
1901         vec3_t          color;
1902         vec_t*          p;
1903         p = G_VECTOR(OFS_PARM0);
1904         SV_LightPoint (color, p);
1905         VectorCopy (color, G_VECTOR(OFS_RETURN));
1906 }
1907
1908 #define MAX_QC_CVARS 128
1909 cvar_t qc_cvar[MAX_QC_CVARS];
1910 int currentqc_cvar;
1911
1912 void PF_registercvar (void)
1913 {
1914         char *name, *value;
1915         cvar_t *variable;
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))
1921                 return;
1922
1923 // check for overlap with a command
1924         if (Cmd_Exists (name))
1925         {
1926                 Con_Printf ("PF_registercvar: %s is a command\n", name);
1927                 return;
1928         }
1929
1930         if (currentqc_cvar >= MAX_QC_CVARS)
1931                 Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1932
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);
1940
1941         Cvar_RegisterVariable(variable);
1942         G_FLOAT(OFS_RETURN) = 1; // success
1943 }
1944
1945 /*
1946 =================
1947 PF_min
1948
1949 returns the minimum of two supplied floats
1950
1951 min(a, b)
1952 =================
1953 */
1954 void PF_min (void)
1955 {
1956         // LordHavoc: 3+ argument enhancement suggested by FrikaC
1957         if (pr_argc == 2)
1958                 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
1959         else if (pr_argc >= 3)
1960         {
1961                 int i;
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;
1967         }
1968         else
1969                 Host_Error("min: must supply at least 2 floats\n");
1970 }
1971
1972 /*
1973 =================
1974 PF_max
1975
1976 returns the maximum of two supplied floats
1977
1978 max(a, b)
1979 =================
1980 */
1981 void PF_max (void)
1982 {
1983         // LordHavoc: 3+ argument enhancement suggested by FrikaC
1984         if (pr_argc == 2)
1985                 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
1986         else if (pr_argc >= 3)
1987         {
1988                 int i;
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;
1994         }
1995         else
1996                 Host_Error("max: must supply at least 2 floats\n");
1997 }
1998
1999 /*
2000 =================
2001 PF_bound
2002
2003 returns number bounded by supplied range
2004
2005 min(min, value, max)
2006 =================
2007 */
2008 void PF_bound (void)
2009 {
2010         G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2011 }
2012
2013 /*
2014 =================
2015 PF_pow
2016
2017 returns a raised to power b
2018
2019 pow(a, b)
2020 =================
2021 */
2022 void PF_pow (void)
2023 {
2024         G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2025 }
2026
2027 /*
2028 =================
2029 PF_copyentity
2030
2031 copies data from one entity to another
2032
2033 copyentity(src, dst)
2034 =================
2035 */
2036 void PF_copyentity (void)
2037 {
2038         edict_t *in, *out;
2039         in = G_EDICT(OFS_PARM0);
2040         out = G_EDICT(OFS_PARM1);
2041         memcpy(out->v, in->v, progs->entityfields * 4);
2042 }
2043
2044 /*
2045 =================
2046 PF_setcolors
2047
2048 sets the color of a client and broadcasts the update to all connected clients
2049
2050 setcolors(clientent, value)
2051 =================
2052 */
2053 void PF_setcolors (void)
2054 {
2055         client_t        *client;
2056         int                     entnum, i;
2057
2058         entnum = G_EDICTNUM(OFS_PARM0);
2059         i = G_FLOAT(OFS_PARM1);
2060
2061         if (entnum < 1 || entnum > svs.maxclients)
2062         {
2063                 Con_Printf ("tried to setcolor a non-client\n");
2064                 return;
2065         }
2066
2067         client = &svs.clients[entnum-1];
2068         client->colors = i;
2069         client->edict->v->team = (i & 15) + 1;
2070
2071         MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2072         MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2073         MSG_WriteByte (&sv.reliable_datagram, i);
2074 }
2075
2076 /*
2077 =================
2078 PF_effect
2079
2080 effect(origin, modelname, startframe, framecount, framerate)
2081 =================
2082 */
2083 void PF_effect (void)
2084 {
2085         char *s;
2086         s = G_STRING(OFS_PARM1);
2087         if (!s || !s[0])
2088                 Host_Error("effect: no model specified\n");
2089
2090         SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2091 }
2092
2093 void PF_te_blood (void)
2094 {
2095         if (G_FLOAT(OFS_PARM2) < 1)
2096                 return;
2097         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2098         MSG_WriteByte(&sv.datagram, TE_BLOOD);
2099         // origin
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]);
2103         // velocity
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));
2107         // count
2108         MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2109 }
2110
2111 void PF_te_bloodshower (void)
2112 {
2113         if (G_FLOAT(OFS_PARM3) < 1)
2114                 return;
2115         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2116         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2117         // min
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]);
2121         // max
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]);
2125         // speed
2126         MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2127         // count
2128         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2129 }
2130
2131 void PF_te_explosionrgb (void)
2132 {
2133         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2134         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2135         // origin
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]);
2139         // color
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));
2143 }
2144
2145 void PF_te_particlecube (void)
2146 {
2147         if (G_FLOAT(OFS_PARM3) < 1)
2148                 return;
2149         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2150         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2151         // min
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]);
2155         // max
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]);
2159         // velocity
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]);
2163         // count
2164         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2165         // color
2166         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2167         // gravity true/false
2168         MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2169         // randomvel
2170         MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2171 }
2172
2173 void PF_te_particlerain (void)
2174 {
2175         if (G_FLOAT(OFS_PARM3) < 1)
2176                 return;
2177         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2178         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2179         // min
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]);
2183         // max
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]);
2187         // velocity
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]);
2191         // count
2192         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2193         // color
2194         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2195 }
2196
2197 void PF_te_particlesnow (void)
2198 {
2199         if (G_FLOAT(OFS_PARM3) < 1)
2200                 return;
2201         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2202         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2203         // min
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]);
2207         // max
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]);
2211         // velocity
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]);
2215         // count
2216         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2217         // color
2218         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2219 }
2220
2221 void PF_te_spark (void)
2222 {
2223         if (G_FLOAT(OFS_PARM2) < 1)
2224                 return;
2225         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226         MSG_WriteByte(&sv.datagram, TE_SPARK);
2227         // origin
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]);
2231         // velocity
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));
2235         // count
2236         MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2237 }
2238
2239 void PF_te_gunshotquad (void)
2240 {
2241         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2243         // origin
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]);
2247 }
2248
2249 void PF_te_spikequad (void)
2250 {
2251         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2253         // origin
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]);
2257 }
2258
2259 void PF_te_superspikequad (void)
2260 {
2261         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2262         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2263         // origin
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]);
2267 }
2268
2269 void PF_te_explosionquad (void)
2270 {
2271         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2272         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2273         // origin
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]);
2277 }
2278
2279 void PF_te_smallflash (void)
2280 {
2281         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2282         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2283         // origin
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]);
2287 }
2288
2289 void PF_te_customflash (void)
2290 {
2291         if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2292                 return;
2293         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2294         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2295         // origin
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]);
2299         // radius
2300         MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2301         // lifetime
2302         MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2303         // color
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));
2307 }
2308
2309 void PF_te_gunshot (void)
2310 {
2311         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2312         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2313         // origin
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]);
2317 }
2318
2319 void PF_te_spike (void)
2320 {
2321         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2322         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2323         // origin
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]);
2327 }
2328
2329 void PF_te_superspike (void)
2330 {
2331         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2332         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2333         // origin
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]);
2337 }
2338
2339 void PF_te_explosion (void)
2340 {
2341         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2342         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2343         // origin
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]);
2347 }
2348
2349 void PF_te_tarexplosion (void)
2350 {
2351         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2352         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2353         // origin
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]);
2357 }
2358
2359 void PF_te_wizspike (void)
2360 {
2361         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2362         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2363         // origin
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]);
2367 }
2368
2369 void PF_te_knightspike (void)
2370 {
2371         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2372         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2373         // origin
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]);
2377 }
2378
2379 void PF_te_lavasplash (void)
2380 {
2381         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2382         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2383         // origin
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]);
2387 }
2388
2389 void PF_te_teleport (void)
2390 {
2391         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2392         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2393         // origin
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]);
2397 }
2398
2399 void PF_te_explosion2 (void)
2400 {
2401         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2402         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2403         // origin
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]);
2407         // color
2408         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2409 }
2410
2411 void PF_te_lightning1 (void)
2412 {
2413         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2414         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2415         // owner entity
2416         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2417         // start
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]);
2421         // end
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]);
2425 }
2426
2427 void PF_te_lightning2 (void)
2428 {
2429         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2431         // owner entity
2432         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2433         // start
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]);
2437         // end
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]);
2441 }
2442
2443 void PF_te_lightning3 (void)
2444 {
2445         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2446         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2447         // owner entity
2448         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2449         // start
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]);
2453         // end
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]);
2457 }
2458
2459 void PF_te_beam (void)
2460 {
2461         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2462         MSG_WriteByte(&sv.datagram, TE_BEAM);
2463         // owner entity
2464         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2465         // start
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]);
2469         // end
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]);
2473 }
2474
2475 void PF_te_plasmaburn (void)
2476 {
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]);
2482 }
2483
2484 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2485 {
2486         int i, j;
2487         vec3_t v1, clipplanenormal, normal;
2488         vec_t clipplanedist, clipdist;
2489         VectorCopy(p, out);
2490         if (surf->flags & SURF_PLANEBACK)
2491                 VectorNegate(surf->plane->normal, normal);
2492         else
2493                 VectorCopy(surf->plane->normal, normal);
2494         for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2495         {
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;
2501                 if (clipdist > 0)
2502                 {
2503                         clipdist = -clipdist;
2504                         VectorMA(out, clipdist, clipplanenormal, out);
2505                 }
2506         }
2507 }
2508
2509 static msurface_t *getsurface(edict_t *ed, int surfnum)
2510 {
2511         int modelindex;
2512         model_t *model;
2513         if (!ed || ed->free)
2514                 return NULL;
2515         modelindex = ed->v->modelindex;
2516         if (modelindex < 1 || modelindex >= MAX_MODELS)
2517                 return NULL;
2518         model = sv.models[modelindex];
2519         if (model->type != mod_brush)
2520                 return NULL;
2521         if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2522                 return NULL;
2523         return model->surfaces + surfnum + model->firstmodelsurface;
2524 }
2525
2526
2527 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2528 void PF_getsurfacenumpoints(void)
2529 {
2530         msurface_t *surf;
2531         // return 0 if no such surface
2532         if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2533         {
2534                 G_FLOAT(OFS_RETURN) = 0;
2535                 return;
2536         }
2537
2538         G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2539 }
2540 //PF_getsurfacepoint,     // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2541 void PF_getsurfacepoint(void)
2542 {
2543         edict_t *ed;
2544         msurface_t *surf;
2545         int pointnum;
2546         VectorClear(G_VECTOR(OFS_RETURN));
2547         ed = G_EDICT(OFS_PARM0);
2548         if (!ed || ed->free)
2549                 return;
2550         if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2551                 return;
2552         pointnum = G_FLOAT(OFS_PARM2);
2553         if (pointnum < 0 || pointnum >= surf->poly_numverts)
2554                 return;
2555         // FIXME: implement rotation/scaling
2556         VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2557 }
2558 //PF_getsurfacenormal,    // #436 vector(entity e, float s) getsurfacenormal = #436;
2559 void PF_getsurfacenormal(void)
2560 {
2561         msurface_t *surf;
2562         VectorClear(G_VECTOR(OFS_RETURN));
2563         if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2564                 return;
2565         // FIXME: implement rotation/scaling
2566         if (surf->flags & SURF_PLANEBACK)
2567                 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2568         else
2569                 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2570 }
2571 //PF_getsurfacetexture,   // #437 string(entity e, float s) getsurfacetexture = #437;
2572 void PF_getsurfacetexture(void)
2573 {
2574         msurface_t *surf;
2575         G_INT(OFS_RETURN) = 0;
2576         if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2577                 return;
2578         G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2579 }
2580 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2581 void PF_getsurfacenearpoint(void)
2582 {
2583         int surfnum, best, modelindex;
2584         vec3_t clipped, p;
2585         vec_t dist, bestdist;
2586         edict_t *ed;
2587         model_t *model;
2588         msurface_t *surf;
2589         vec_t *point;
2590         G_FLOAT(OFS_RETURN) = -1;
2591         ed = G_EDICT(OFS_PARM0);
2592         point = G_VECTOR(OFS_PARM1);
2593
2594         if (!ed || ed->free)
2595                 return;
2596         modelindex = ed->v->modelindex;
2597         if (modelindex < 1 || modelindex >= MAX_MODELS)
2598                 return;
2599         model = sv.models[modelindex];
2600         if (model->type != mod_brush)
2601                 return;
2602
2603         // FIXME: implement rotation/scaling
2604         VectorSubtract(point, ed->v->origin, p);
2605         best = -1;
2606         bestdist = 1000000000;
2607         for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2608         {
2609                 surf = model->surfaces + surfnum + model->firstmodelsurface;
2610                 dist = PlaneDiff(p, surf->plane);
2611                 dist = dist * dist;
2612                 if (dist < bestdist)
2613                 {
2614                         clippointtosurface(surf, p, clipped);
2615                         VectorSubtract(clipped, p, clipped);
2616                         dist += DotProduct(clipped, clipped);
2617                         if (dist < bestdist)
2618                         {
2619                                 best = surfnum;
2620                                 bestdist = dist;
2621                         }
2622                 }
2623         }
2624         G_FLOAT(OFS_RETURN) = best;
2625 }
2626 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2627 void PF_getsurfaceclippedpoint(void)
2628 {
2629         edict_t *ed;
2630         msurface_t *surf;
2631         vec3_t p, out;
2632         VectorClear(G_VECTOR(OFS_RETURN));
2633         ed = G_EDICT(OFS_PARM0);
2634         if (!ed || ed->free)
2635                 return;
2636         if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2637                 return;
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));
2643 }
2644
2645 void PF_Fixme (void)
2646 {
2647         Host_Error ("unimplemented QC builtin"); // LordHavoc: was misspelled (bulitin)
2648 }
2649
2650
2651
2652 builtin_t pr_builtin[] =
2653 {
2654 PF_Fixme,
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;
2682 PF_coredump,
2683 PF_traceon,
2684 PF_traceoff,
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
2688 PF_droptofloor,
2689 PF_lightstyle,
2690 PF_rint,
2691 PF_floor,
2692 PF_ceil,
2693 PF_Fixme,
2694 PF_checkbottom,
2695 PF_pointcontents,
2696 PF_Fixme,
2697 PF_fabs,
2698 PF_aim,
2699 PF_cvar,
2700 PF_localcmd,
2701 PF_nextent,
2702 PF_particle,
2703 PF_changeyaw,
2704 PF_Fixme,
2705 PF_vectoangles,
2706
2707 PF_WriteByte,
2708 PF_WriteChar,
2709 PF_WriteShort,
2710 PF_WriteLong,
2711 PF_WriteCoord,
2712 PF_WriteAngle,
2713 PF_WriteString,
2714 PF_WriteEntity,
2715
2716 PF_sin,
2717 PF_cos,
2718 PF_sqrt,
2719 PF_changepitch,
2720 PF_TraceToss,
2721 PF_etos,
2722 PF_Fixme,
2723
2724 SV_MoveToGoal,
2725 PF_precache_file,
2726 PF_makestatic,
2727
2728 PF_changelevel,
2729 PF_Fixme,
2730
2731 PF_cvar_set,
2732 PF_centerprint,
2733
2734 PF_ambientsound,
2735
2736 PF_precache_model,
2737 PF_precache_sound,              // precache_sound2 is different only for qcc
2738 PF_precache_file,
2739
2740 PF_setspawnparms,
2741
2742 PF_Fixme,                               // #79 LordHavoc: dunno who owns 79-89, so these are just padding
2743 PF_Fixme,                               // #80
2744 PF_Fixme,                               // #81
2745 PF_Fixme,                               // #82
2746 PF_Fixme,                               // #83
2747 PF_Fixme,                               // #84
2748 PF_Fixme,                               // #85
2749 PF_Fixme,                               // #86
2750 PF_Fixme,                               // #87
2751 PF_Fixme,                               // #88
2752 PF_Fixme,                               // #89
2753
2754 PF_tracebox,                    // #90 LordHavoc builtin range (9x)
2755 PF_randomvec,                   // #91
2756 PF_GetLight,                    // #92
2757 PF_registercvar,                // #93
2758 PF_min,                                 // #94
2759 PF_max,                                 // #95
2760 PF_bound,                               // #96
2761 PF_pow,                                 // #97
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
2766 aa // #200
2767 aa // #300
2768 aa // #400
2769 PF_copyentity,                  // #400 LordHavoc: builtin range (4xx)
2770 PF_setcolors,                   // #401
2771 PF_findchain,                   // #402
2772 PF_findchainfloat,              // #403
2773 PF_effect,                              // #404
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
2800 PF_te_beam,                             // #431
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;
2809 };
2810
2811 builtin_t *pr_builtins = pr_builtin;
2812 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
2813