]> icculus.org git repositories - divverent/darkplaces.git/blob - pr_cmds.c
e4ba51a93fcb5255775f504610455b0d36361f45
[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 #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 extern qboolean hlbsp;
1302 void PF_precache_model (void)
1303 {
1304         char    *s;
1305         int             i;
1306         
1307         if (sv.state != ss_loading)
1308                 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1309                 
1310         s = G_STRING(OFS_PARM0);
1311         if (hlbsp && ((!s) || (!s[0])))
1312                 return;
1313         G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1314         PR_CheckEmptyString (s);
1315
1316         for (i=0 ; i<MAX_MODELS ; i++)
1317         {
1318                 if (!sv.model_precache[i])
1319                 {
1320                         sv.model_precache[i] = s;
1321                         sv.models[i] = Mod_ForName (s, true);
1322                         return;
1323                 }
1324                 if (!strcmp(sv.model_precache[i], s))
1325                         return;
1326         }
1327         PR_RunError ("PF_precache_model: overflow");
1328 }
1329
1330
1331 void PF_coredump (void)
1332 {
1333         ED_PrintEdicts ();
1334 }
1335
1336 void PF_traceon (void)
1337 {
1338         pr_trace = true;
1339 }
1340
1341 void PF_traceoff (void)
1342 {
1343         pr_trace = false;
1344 }
1345
1346 void PF_eprint (void)
1347 {
1348         ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1349 }
1350
1351 /*
1352 ===============
1353 PF_walkmove
1354
1355 float(float yaw, float dist) walkmove
1356 ===============
1357 */
1358 void PF_walkmove (void)
1359 {
1360         edict_t *ent;
1361         float   yaw, dist;
1362         vec3_t  move;
1363         dfunction_t     *oldf;
1364         int     oldself;
1365         
1366         ent = PROG_TO_EDICT(pr_global_struct->self);
1367         yaw = G_FLOAT(OFS_PARM0);
1368         dist = G_FLOAT(OFS_PARM1);
1369         
1370         if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1371         {
1372                 G_FLOAT(OFS_RETURN) = 0;
1373                 return;
1374         }
1375
1376         yaw = yaw*M_PI*2 / 360;
1377         
1378         move[0] = cos(yaw)*dist;
1379         move[1] = sin(yaw)*dist;
1380         move[2] = 0;
1381
1382 // save program state, because SV_movestep may call other progs
1383         oldf = pr_xfunction;
1384         oldself = pr_global_struct->self;
1385         
1386         G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1387         
1388         
1389 // restore program state
1390         pr_xfunction = oldf;
1391         pr_global_struct->self = oldself;
1392 }
1393
1394 /*
1395 ===============
1396 PF_droptofloor
1397
1398 void() droptofloor
1399 ===============
1400 */
1401 void PF_droptofloor (void)
1402 {
1403         edict_t         *ent;
1404         vec3_t          end;
1405         trace_t         trace;
1406         
1407         ent = PROG_TO_EDICT(pr_global_struct->self);
1408
1409         VectorCopy (ent->v.origin, end);
1410         end[2] -= 256;
1411         
1412         trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1413
1414         if (trace.fraction == 1 || trace.allsolid)
1415                 G_FLOAT(OFS_RETURN) = 0;
1416         else
1417         {
1418                 VectorCopy (trace.endpos, ent->v.origin);
1419                 SV_LinkEdict (ent, false);
1420                 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1421                 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1422                 G_FLOAT(OFS_RETURN) = 1;
1423         }
1424 }
1425
1426 /*
1427 ===============
1428 PF_lightstyle
1429
1430 void(float style, string value) lightstyle
1431 ===============
1432 */
1433 void PF_lightstyle (void)
1434 {
1435         int             style;
1436         char    *val;
1437         client_t        *client;
1438         int                     j;
1439         
1440         style = G_FLOAT(OFS_PARM0);
1441         val = G_STRING(OFS_PARM1);
1442
1443 // change the string in sv
1444         sv.lightstyles[style] = val;
1445         
1446 // send message to all clients on this server
1447         if (sv.state != ss_active)
1448                 return;
1449         
1450         for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1451                 if (client->active || client->spawned)
1452                 {
1453                         MSG_WriteChar (&client->message, svc_lightstyle);
1454                         MSG_WriteChar (&client->message,style);
1455                         MSG_WriteString (&client->message, val);
1456                 }
1457 }
1458
1459 void PF_rint (void)
1460 {
1461         float   f;
1462         f = G_FLOAT(OFS_PARM0);
1463         if (f > 0)
1464                 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1465         else
1466                 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1467 }
1468 void PF_floor (void)
1469 {
1470         G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1471 }
1472 void PF_ceil (void)
1473 {
1474         G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1475 }
1476
1477
1478 /*
1479 =============
1480 PF_checkbottom
1481 =============
1482 */
1483 void PF_checkbottom (void)
1484 {
1485         G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1486 }
1487
1488 /*
1489 =============
1490 PF_pointcontents
1491 =============
1492 */
1493 void PF_pointcontents (void)
1494 {
1495         G_FLOAT(OFS_RETURN) = SV_PointContents (G_VECTOR(OFS_PARM0));
1496 }
1497
1498 /*
1499 =============
1500 PF_nextent
1501
1502 entity nextent(entity)
1503 =============
1504 */
1505 void PF_nextent (void)
1506 {
1507         int             i;
1508         edict_t *ent;
1509         
1510         i = G_EDICTNUM(OFS_PARM0);
1511         while (1)
1512         {
1513                 i++;
1514                 if (i == sv.num_edicts)
1515                 {
1516                         RETURN_EDICT(sv.edicts);
1517                         return;
1518                 }
1519                 ent = EDICT_NUM(i);
1520                 if (!ent->free)
1521                 {
1522                         RETURN_EDICT(ent);
1523                         return;
1524                 }
1525         }
1526 }
1527
1528 /*
1529 =============
1530 PF_aim
1531
1532 Pick a vector for the player to shoot along
1533 vector aim(entity, missilespeed)
1534 =============
1535 */
1536 cvar_t  sv_aim = {"sv_aim", "0.93"};
1537 void PF_aim (void)
1538 {
1539         edict_t *ent, *check, *bestent;
1540         vec3_t  start, dir, end, bestdir;
1541         int             i, j;
1542         trace_t tr;
1543         float   dist, bestdist;
1544         float   speed;
1545         
1546         ent = G_EDICT(OFS_PARM0);
1547         speed = G_FLOAT(OFS_PARM1);
1548
1549         VectorCopy (ent->v.origin, start);
1550         start[2] += 20;
1551
1552 // try sending a trace straight
1553         VectorCopy (pr_global_struct->v_forward, dir);
1554         VectorMA (start, 2048, dir, end);
1555         tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1556         if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1557         && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1558         {
1559                 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1560                 return;
1561         }
1562
1563
1564 // try all possible entities
1565         VectorCopy (dir, bestdir);
1566         bestdist = sv_aim.value;
1567         bestent = NULL;
1568         
1569         check = NEXT_EDICT(sv.edicts);
1570         for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1571         {
1572                 if (check->v.takedamage != DAMAGE_AIM)
1573                         continue;
1574                 if (check == ent)
1575                         continue;
1576                 if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1577                         continue;       // don't aim at teammate
1578                 for (j=0 ; j<3 ; j++)
1579                         end[j] = check->v.origin[j]
1580                         + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1581                 VectorSubtract (end, start, dir);
1582                 VectorNormalize (dir);
1583                 dist = DotProduct (dir, pr_global_struct->v_forward);
1584                 if (dist < bestdist)
1585                         continue;       // to far to turn
1586                 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1587                 if (tr.ent == check)
1588                 {       // can shoot at this one
1589                         bestdist = dist;
1590                         bestent = check;
1591                 }
1592         }
1593         
1594         if (bestent)
1595         {
1596                 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1597                 dist = DotProduct (dir, pr_global_struct->v_forward);
1598                 VectorScale (pr_global_struct->v_forward, dist, end);
1599                 end[2] = dir[2];
1600                 VectorNormalize (end);
1601                 VectorCopy (end, G_VECTOR(OFS_RETURN)); 
1602         }
1603         else
1604         {
1605                 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1606         }
1607 }
1608
1609 /*
1610 ==============
1611 PF_changeyaw
1612
1613 This was a major timewaster in progs, so it was converted to C
1614 ==============
1615 */
1616 void PF_changeyaw (void)
1617 {
1618         edict_t         *ent;
1619         float           ideal, current, move, speed;
1620         
1621         ent = PROG_TO_EDICT(pr_global_struct->self);
1622         current = anglemod( ent->v.angles[1] );
1623         ideal = ent->v.ideal_yaw;
1624         speed = ent->v.yaw_speed;
1625         
1626         if (current == ideal)
1627                 return;
1628         move = ideal - current;
1629         if (ideal > current)
1630         {
1631                 if (move >= 180)
1632                         move = move - 360;
1633         }
1634         else
1635         {
1636                 if (move <= -180)
1637                         move = move + 360;
1638         }
1639         if (move > 0)
1640         {
1641                 if (move > speed)
1642                         move = speed;
1643         }
1644         else
1645         {
1646                 if (move < -speed)
1647                         move = -speed;
1648         }
1649         
1650         ent->v.angles[1] = anglemod (current + move);
1651 }
1652
1653 /*
1654 ==============
1655 PF_changepitch
1656 ==============
1657 */
1658 void PF_changepitch (void)
1659 {
1660         edict_t         *ent;
1661         float           ideal, current, move, speed;
1662         eval_t          *val;
1663         
1664         ent = G_EDICT(OFS_PARM0);
1665         current = anglemod( ent->v.angles[0] );
1666         if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1667                 ideal = val->_float;
1668         else
1669         {
1670                 PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1671                 return;
1672         }
1673         if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1674                 speed = val->_float;
1675         else
1676         {
1677                 PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1678                 return;
1679         }
1680         
1681         if (current == ideal)
1682                 return;
1683         move = ideal - current;
1684         if (ideal > current)
1685         {
1686                 if (move >= 180)
1687                         move = move - 360;
1688         }
1689         else
1690         {
1691                 if (move <= -180)
1692                         move = move + 360;
1693         }
1694         if (move > 0)
1695         {
1696                 if (move > speed)
1697                         move = speed;
1698         }
1699         else
1700         {
1701                 if (move < -speed)
1702                         move = -speed;
1703         }
1704         
1705         ent->v.angles[0] = anglemod (current + move);
1706 }
1707
1708 /*
1709 ===============================================================================
1710
1711 MESSAGE WRITING
1712
1713 ===============================================================================
1714 */
1715
1716 #define MSG_BROADCAST   0               // unreliable to all
1717 #define MSG_ONE                 1               // reliable to one (msg_entity)
1718 #define MSG_ALL                 2               // reliable to all
1719 #define MSG_INIT                3               // write to the init string
1720
1721 sizebuf_t *WriteDest (void)
1722 {
1723         int             entnum;
1724         int             dest;
1725         edict_t *ent;
1726
1727         dest = G_FLOAT(OFS_PARM0);
1728         switch (dest)
1729         {
1730         case MSG_BROADCAST:
1731                 return &sv.datagram;
1732         
1733         case MSG_ONE:
1734                 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1735                 entnum = NUM_FOR_EDICT(ent);
1736                 if (entnum < 1 || entnum > svs.maxclients)
1737                         PR_RunError ("WriteDest: not a client");
1738                 return &svs.clients[entnum-1].message;
1739                 
1740         case MSG_ALL:
1741                 return &sv.reliable_datagram;
1742         
1743         case MSG_INIT:
1744                 return &sv.signon;
1745
1746         default:
1747                 PR_RunError ("WriteDest: bad destination");
1748                 break;
1749         }
1750         
1751         return NULL;
1752 }
1753
1754 void PF_WriteByte (void)
1755 {
1756         MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1757 }
1758
1759 void PF_WriteChar (void)
1760 {
1761         MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1762 }
1763
1764 void PF_WriteShort (void)
1765 {
1766         MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1767 }
1768
1769 void PF_WriteLong (void)
1770 {
1771         MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1772 }
1773
1774 void PF_WriteAngle (void)
1775 {
1776         MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1777 }
1778
1779 void PF_WriteCoord (void)
1780 {
1781         MSG_WriteFloatCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1782 }
1783
1784 void PF_WriteString (void)
1785 {
1786         MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1787 }
1788
1789
1790 void PF_WriteEntity (void)
1791 {
1792         MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1793 }
1794
1795 //=============================================================================
1796
1797 int SV_ModelIndex (char *name);
1798
1799 void PF_makestatic (void)
1800 {
1801         edict_t *ent;
1802         int             i;
1803         
1804         ent = G_EDICT(OFS_PARM0);
1805
1806         i = SV_ModelIndex(pr_strings + ent->v.model);
1807         if (i >= 256)
1808         {
1809                 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1810                 MSG_WriteShort (&sv.signon, i);
1811         }
1812         else
1813         {
1814                 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1815                 MSG_WriteByte (&sv.signon, i);
1816         }
1817
1818         MSG_WriteByte (&sv.signon, ent->v.frame);
1819         MSG_WriteByte (&sv.signon, ent->v.colormap);
1820         MSG_WriteByte (&sv.signon, ent->v.skin);
1821         for (i=0 ; i<3 ; i++)
1822         {
1823                 MSG_WriteFloatCoord(&sv.signon, ent->v.origin[i]);
1824                 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1825         }
1826
1827 // throw the entity away now
1828         ED_Free (ent);
1829 }
1830
1831 //=============================================================================
1832
1833 /*
1834 ==============
1835 PF_setspawnparms
1836 ==============
1837 */
1838 void PF_setspawnparms (void)
1839 {
1840         edict_t *ent;
1841         int             i;
1842         client_t        *client;
1843
1844         ent = G_EDICT(OFS_PARM0);
1845         i = NUM_FOR_EDICT(ent);
1846         if (i < 1 || i > svs.maxclients)
1847                 PR_RunError ("Entity is not a client");
1848
1849         // copy spawn parms out of the client_t
1850         client = svs.clients + (i-1);
1851
1852         for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1853                 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1854 }
1855
1856 /*
1857 ==============
1858 PF_changelevel
1859 ==============
1860 */
1861 void PF_changelevel (void)
1862 {
1863         char    *s;
1864
1865 // make sure we don't issue two changelevels
1866         if (svs.changelevel_issued)
1867                 return;
1868         svs.changelevel_issued = true;
1869         
1870         s = G_STRING(OFS_PARM0);
1871         Cbuf_AddText (va("changelevel %s\n",s));
1872 }
1873
1874 void PF_sin (void)
1875 {
1876         G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1877 }
1878
1879 void PF_cos (void)
1880 {
1881         G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1882 }
1883
1884 void PF_sqrt (void)
1885 {
1886         G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1887 }
1888
1889 /*
1890 =================
1891 PF_RandomVec
1892
1893 Returns a vector of length < 1
1894
1895 randomvec()
1896 =================
1897 */
1898 void PF_randomvec (void)
1899 {
1900         vec3_t          temp;
1901         do
1902         {
1903                 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1904                 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1905                 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1906         }
1907         while (DotProduct(temp, temp) >= 1);
1908         VectorCopy (temp, G_VECTOR(OFS_RETURN));        
1909 }
1910
1911 void SV_LightPoint (vec3_t color, vec3_t p);
1912 /*
1913 =================
1914 PF_GetLight
1915
1916 Returns a color vector indicating the lighting at the requested point.
1917
1918 (Internal Operation note: actually measures the light beneath the point, just like
1919                           the model lighting on the client)
1920
1921 getlight(vector)
1922 =================
1923 */
1924 void PF_GetLight (void)
1925 {
1926         vec3_t          color;
1927         vec_t*          p;
1928         p = G_VECTOR(OFS_PARM0);
1929         SV_LightPoint (color, p);
1930         VectorCopy (color, G_VECTOR(OFS_RETURN));       
1931 }
1932
1933 #define MAX_QC_CVARS 128
1934 cvar_t qc_cvar[MAX_QC_CVARS];
1935 int currentqc_cvar;
1936
1937 void PF_registercvar (void)
1938 {
1939         char    *name, *value;
1940         cvar_t  *variable;
1941         name = G_STRING(OFS_PARM1);
1942         value = G_STRING(OFS_PARM2);
1943         G_FLOAT(OFS_RETURN) = 0;
1944 // first check to see if it has already been defined
1945         if (Cvar_FindVar (name))
1946                 return;
1947         
1948 // check for overlap with a command
1949         if (Cmd_Exists (name))
1950         {
1951                 Con_Printf ("PF_registercvar: %s is a command\n", name);
1952                 return;
1953         }
1954
1955         if (currentqc_cvar >= MAX_QC_CVARS)
1956                 PR_RunError ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1957
1958 // copy the name and value
1959         variable = &qc_cvar[currentqc_cvar++];
1960         variable->name = Z_Malloc (strlen(name)+1);     
1961         strcpy (variable->name, name);
1962         variable->string = Z_Malloc (strlen(value)+1);  
1963         strcpy (variable->string, value);
1964         variable->value = atof (value);
1965         
1966 // link the variable in
1967         variable->next = cvar_vars;
1968         cvar_vars = variable;
1969         G_FLOAT(OFS_RETURN) = 1; // success
1970 }
1971
1972 /*
1973 =================
1974 PF_min
1975
1976 returns the minimum of two supplied floats
1977
1978 min(a, b)
1979 =================
1980 */
1981 void PF_min (void)
1982 {
1983         // LordHavoc: 3+ argument enhancement suggested by FrikaC
1984         if (pr_argc == 2)
1985                 G_FLOAT(OFS_RETURN) = min(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                 PR_RunError("min: must supply at least 2 floats\n");
1997 }
1998
1999 /*
2000 =================
2001 PF_max
2002
2003 returns the maximum of two supplied floats
2004
2005 max(a, b)
2006 =================
2007 */
2008 void PF_max (void)
2009 {
2010         // LordHavoc: 3+ argument enhancement suggested by FrikaC
2011         if (pr_argc == 2)
2012                 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2013         else if (pr_argc >= 3)
2014         {
2015                 int i;
2016                 float f = G_FLOAT(OFS_PARM0);
2017                 for (i = 1;i < pr_argc;i++)
2018                         if (G_FLOAT((OFS_PARM0+i*3)) > f)
2019                                 f = G_FLOAT((OFS_PARM0+i*3));
2020                 G_FLOAT(OFS_RETURN) = f;
2021         }
2022         else
2023                 PR_RunError("max: must supply at least 2 floats\n");
2024 }
2025
2026 /*
2027 =================
2028 PF_bound
2029
2030 returns number bounded by supplied range
2031
2032 min(min, value, max)
2033 =================
2034 */
2035 void PF_bound (void)
2036 {
2037         G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2038 }
2039
2040 /*
2041 =================
2042 PF_pow
2043
2044 returns a raised to power b
2045
2046 pow(a, b)
2047 =================
2048 */
2049 void PF_pow (void)
2050 {
2051         G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2052 }
2053
2054 /*
2055 =================
2056 PF_copyentity
2057
2058 copies data from one entity to another
2059
2060 copyentity(src, dst)
2061 =================
2062 */
2063 void PF_copyentity (void)
2064 {
2065         edict_t *in, *out;
2066         in = G_EDICT(OFS_PARM0);
2067         out = G_EDICT(OFS_PARM1);
2068         memcpy(out, in, pr_edict_size);
2069 }
2070
2071 /*
2072 =================
2073 PF_setcolor
2074
2075 sets the color of a client and broadcasts the update to all connected clients
2076
2077 setcolor(clientent, value)
2078 =================
2079 */
2080 void PF_setcolor (void)
2081 {
2082         client_t        *client;
2083         int                     entnum, i;
2084         
2085         entnum = G_EDICTNUM(OFS_PARM0);
2086         i = G_FLOAT(OFS_PARM1);
2087         
2088         if (entnum < 1 || entnum > svs.maxclients)
2089         {
2090                 Con_Printf ("tried to setcolor a non-client\n");
2091                 return;
2092         }
2093                 
2094         client = &svs.clients[entnum-1];
2095         client->colors = i;
2096         client->edict->v.team = (i & 15) + 1;
2097                 
2098         MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2099         MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2100         MSG_WriteByte (&sv.reliable_datagram, i);
2101 }
2102
2103 /*
2104 =================
2105 PF_effect
2106
2107 effect(origin, modelname, startframe, framecount, framerate)
2108 =================
2109 */
2110 void PF_effect (void)
2111 {
2112         char *s;
2113         s = G_STRING(OFS_PARM1);
2114         if (!s || !s[0])
2115                 PR_RunError("effect: no model specified\n");
2116
2117         SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2118 }
2119
2120 void PF_te_blood (void)
2121 {
2122         if (G_FLOAT(OFS_PARM2) < 1)
2123                 return;
2124         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2125         MSG_WriteByte(&sv.datagram, TE_BLOOD);
2126         // origin
2127         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2128         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2129         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2130         // velocity
2131         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2132         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2133         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2134         // count
2135         MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2136 }
2137
2138 void PF_te_bloodshower (void)
2139 {
2140         if (G_FLOAT(OFS_PARM3) < 1)
2141                 return;
2142         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2143         MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2144         // min
2145         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2146         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2147         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2148         // max
2149         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2150         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2151         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2152         // speed
2153         MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2154         // count
2155         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2156 }
2157
2158 void PF_te_explosionrgb (void)
2159 {
2160         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2161         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2162         // origin
2163         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2164         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2165         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2166         // color
2167         MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2168         MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2169         MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2170 }
2171
2172 void PF_te_particlecube (void)
2173 {
2174         if (G_FLOAT(OFS_PARM3) < 1)
2175                 return;
2176         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2177         MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2178         // min
2179         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2180         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2181         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2182         // max
2183         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2184         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2185         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2186         // velocity
2187         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2188         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2189         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2190         // count
2191         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2192         // color
2193         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2194         // gravity true/false
2195         MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2196         // randomvel
2197         MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2198 }
2199
2200 void PF_te_particlerain (void)
2201 {
2202         if (G_FLOAT(OFS_PARM3) < 1)
2203                 return;
2204         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2205         MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2206         // min
2207         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2208         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2209         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2210         // max
2211         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2212         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2213         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2214         // velocity
2215         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2216         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2217         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2218         // count
2219         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2220         // color
2221         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2222 }
2223
2224 void PF_te_particlesnow (void)
2225 {
2226         if (G_FLOAT(OFS_PARM3) < 1)
2227                 return;
2228         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2229         MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2230         // min
2231         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2232         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2233         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2234         // max
2235         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2236         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2237         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2238         // velocity
2239         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2240         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2241         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2242         // count
2243         MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2244         // color
2245         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2246 }
2247
2248 void PF_te_spark (void)
2249 {
2250         if (G_FLOAT(OFS_PARM2) < 1)
2251                 return;
2252         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2253         MSG_WriteByte(&sv.datagram, TE_SPARK);
2254         // origin
2255         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2256         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2257         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2258         // velocity
2259         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2260         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2261         MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2262         // count
2263         MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2264 }
2265
2266 void PF_te_gunshotquad (void)
2267 {
2268         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2269         MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2270         // origin
2271         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2272         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2273         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2274 }
2275
2276 void PF_te_spikequad (void)
2277 {
2278         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279         MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2280         // origin
2281         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2282         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2283         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2284 }
2285
2286 void PF_te_superspikequad (void)
2287 {
2288         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2289         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2290         // origin
2291         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2292         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2293         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2294 }
2295
2296 void PF_te_explosionquad (void)
2297 {
2298         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299         MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2300         // origin
2301         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2302         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2303         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2304 }
2305
2306 void PF_te_smallflash (void)
2307 {
2308         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2309         MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2310         // origin
2311         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2312         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2313         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2314 }
2315
2316 void PF_te_customflash (void)
2317 {
2318         if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2319                 return;
2320         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2321         MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2322         // origin
2323         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2324         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2325         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2326         // radius
2327         MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2328         // lifetime
2329         MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2330         // color
2331         MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2332         MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2333         MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2334 }
2335
2336 void PF_te_gunshot (void)
2337 {
2338         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2339         MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2340         // origin
2341         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2342         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2343         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2344 }
2345
2346 void PF_te_spike (void)
2347 {
2348         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2349         MSG_WriteByte(&sv.datagram, TE_SPIKE);
2350         // origin
2351         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2352         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2353         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2354 }
2355
2356 void PF_te_superspike (void)
2357 {
2358         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2359         MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2360         // origin
2361         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2362         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2363         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2364 }
2365
2366 void PF_te_explosion (void)
2367 {
2368         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2369         MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2370         // origin
2371         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2372         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2373         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2374 }
2375
2376 void PF_te_tarexplosion (void)
2377 {
2378         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2379         MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2380         // origin
2381         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2382         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2383         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2384 }
2385
2386 void PF_te_wizspike (void)
2387 {
2388         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2389         MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2390         // origin
2391         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2392         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2393         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2394 }
2395
2396 void PF_te_knightspike (void)
2397 {
2398         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2399         MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2400         // origin
2401         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2402         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2403         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2404 }
2405
2406 void PF_te_lavasplash (void)
2407 {
2408         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2409         MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2410         // origin
2411         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2412         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2413         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2414 }
2415
2416 void PF_te_teleport (void)
2417 {
2418         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2419         MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2420         // origin
2421         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2422         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2423         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2424 }
2425
2426 void PF_te_explosion2 (void)
2427 {
2428         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2429         MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2430         // origin
2431         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2432         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2433         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2434         // color
2435         MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2436 }
2437
2438 void PF_te_lightning1 (void)
2439 {
2440         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2441         MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2442         // owner entity
2443         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2444         // start
2445         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2446         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2447         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2448         // end
2449         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2450         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2451         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2452 }
2453
2454 void PF_te_lightning2 (void)
2455 {
2456         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2457         MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2458         // owner entity
2459         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2460         // start
2461         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2462         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2463         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2464         // end
2465         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2466         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2467         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2468 }
2469
2470 void PF_te_lightning3 (void)
2471 {
2472         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2473         MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2474         // owner entity
2475         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2476         // start
2477         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2478         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2479         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2480         // end
2481         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2482         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2483         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2484 }
2485
2486 void PF_te_beam (void)
2487 {
2488         MSG_WriteByte(&sv.datagram, svc_temp_entity);
2489         MSG_WriteByte(&sv.datagram, TE_BEAM);
2490         // owner entity
2491         MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2492         // start
2493         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2494         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2495         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2496         // end
2497         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2498         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2499         MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2500 }
2501
2502 void PF_Fixme (void)
2503 {
2504         PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
2505 }
2506
2507
2508
2509 builtin_t pr_builtin[] =
2510 {
2511 PF_Fixme,
2512 PF_makevectors, // void(entity e)       makevectors             = #1;
2513 PF_setorigin,   // void(entity e, vector o) setorigin   = #2;
2514 PF_setmodel,    // void(entity e, string m) setmodel    = #3;
2515 PF_setsize,     // void(entity e, vector min, vector max) setsize = #4;
2516 PF_Fixme,       // void(entity e, vector min, vector max) setabssize = #5;
2517 PF_break,       // void() break                                         = #6;
2518 PF_random,      // float() random                                               = #7;
2519 PF_sound,       // void(entity e, float chan, string samp) sound = #8;
2520 PF_normalize,   // vector(vector v) normalize                   = #9;
2521 PF_error,       // void(string e) error                         = #10;
2522 PF_objerror,    // void(string e) objerror                              = #11;
2523 PF_vlen,        // float(vector v) vlen                         = #12;
2524 PF_vectoyaw,    // float(vector v) vectoyaw             = #13;
2525 PF_Spawn,       // entity() spawn                                               = #14;
2526 PF_Remove,      // void(entity e) remove                                = #15;
2527 PF_traceline,   // float(vector v1, vector v2, float tryents) traceline = #16;
2528 PF_checkclient, // entity() clientlist                                  = #17;
2529 PF_Find,        // entity(entity start, .string fld, string match) find = #18;
2530 PF_precache_sound,      // void(string s) precache_sound                = #19;
2531 PF_precache_model,      // void(string s) precache_model                = #20;
2532 PF_stuffcmd,    // void(entity client, string s)stuffcmd = #21;
2533 PF_findradius,  // entity(vector org, float rad) findradius = #22;
2534 PF_bprint,      // void(string s) bprint                                = #23;
2535 PF_sprint,      // void(entity client, string s) sprint = #24;
2536 PF_dprint,      // void(string s) dprint                                = #25;
2537 PF_ftos,        // void(string s) ftos                          = #26;
2538 PF_vtos,        // void(string s) vtos                          = #27;
2539 PF_coredump,
2540 PF_traceon,
2541 PF_traceoff,
2542 PF_eprint,      // void(entity e) debug print an entire entity
2543 PF_walkmove, // float(float yaw, float dist) walkmove
2544 PF_Fixme, // float(float yaw, float dist) walkmove
2545 PF_droptofloor,
2546 PF_lightstyle,
2547 PF_rint,
2548 PF_floor,
2549 PF_ceil,
2550 PF_Fixme,
2551 PF_checkbottom,
2552 PF_pointcontents,
2553 PF_Fixme,
2554 PF_fabs,
2555 PF_aim,
2556 PF_cvar,
2557 PF_localcmd,
2558 PF_nextent,
2559 PF_particle,
2560 PF_changeyaw,
2561 PF_Fixme,
2562 PF_vectoangles,
2563
2564 PF_WriteByte,
2565 PF_WriteChar,
2566 PF_WriteShort,
2567 PF_WriteLong,
2568 PF_WriteCoord,
2569 PF_WriteAngle,
2570 PF_WriteString,
2571 PF_WriteEntity,
2572
2573 PF_sin,
2574 PF_cos,
2575 PF_sqrt,
2576 PF_changepitch,
2577 PF_TraceToss,
2578 PF_etos,
2579 PF_Fixme,
2580
2581 SV_MoveToGoal,
2582 PF_precache_file,
2583 PF_makestatic,
2584
2585 PF_changelevel,
2586 PF_Fixme,
2587
2588 PF_cvar_set,
2589 PF_centerprint,
2590
2591 PF_ambientsound,
2592
2593 PF_precache_model,
2594 PF_precache_sound,              // precache_sound2 is different only for qcc
2595 PF_precache_file,
2596
2597 PF_setspawnparms,
2598
2599 PF_Fixme,                               // #79 LordHavoc: dunno who owns 79-89, so these are just padding
2600 PF_Fixme,                               // #80 
2601 PF_Fixme,                               // #81
2602 PF_Fixme,                               // #82
2603 PF_Fixme,                               // #83
2604 PF_Fixme,                               // #84
2605 PF_Fixme,                               // #85
2606 PF_Fixme,                               // #86
2607 PF_Fixme,                               // #87
2608 PF_Fixme,                               // #88
2609 PF_Fixme,                               // #89
2610
2611 PF_tracebox,                    // #90 LordHavoc builtin range (9x)
2612 PF_randomvec,                   // #91
2613 PF_GetLight,                    // #92
2614 PF_registercvar,                // #93
2615 PF_min,                                 // #94
2616 PF_max,                                 // #95
2617 PF_bound,                               // #96
2618 PF_pow,                                 // #97
2619 PF_FindFloat,                   // #98
2620 PF_checkextension,              // #99
2621 #define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme,
2622 #define aa a a a a a a a a a a
2623 aa // #200
2624 aa // #300
2625 aa // #400
2626 PF_copyentity,                  // #400 LordHavoc: builtin range (4xx)
2627 PF_setcolor,                    // #401
2628 PF_findchain,                   // #402
2629 PF_findchainfloat,              // #403
2630 PF_effect,                              // #404
2631 PF_te_blood,                    // #405
2632 PF_te_bloodshower,              // #406
2633 PF_te_explosionrgb,             // #407
2634 PF_te_particlecube,             // #408
2635 PF_te_particlerain,             // #409
2636 PF_te_particlesnow,             // #410
2637 PF_te_spark,                    // #411
2638 PF_te_gunshotquad,              // #412
2639 PF_te_spikequad,                // #413
2640 PF_te_superspikequad,   // #414
2641 PF_te_explosionquad,    // #415
2642 PF_te_smallflash,               // #416
2643 PF_te_customflash,              // #417
2644 PF_te_gunshot,                  // #418
2645 PF_te_spike,                    // #419
2646 PF_te_superspike,               // #420
2647 PF_te_explosion,                // #421
2648 PF_te_tarexplosion,             // #422
2649 PF_te_wizspike,                 // #423
2650 PF_te_knightspike,              // #424
2651 PF_te_lavasplash,               // #425
2652 PF_te_teleport,                 // #426
2653 PF_te_explosion2,               // #427
2654 PF_te_lightning1,               // #428
2655 PF_te_lightning2,               // #429
2656 PF_te_lightning3,               // #430
2657 PF_te_beam,                             // #431
2658 PF_vectorvectors,               // #432
2659 };
2660
2661 builtin_t *pr_builtins = pr_builtin;
2662 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);