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