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