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