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