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