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