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