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