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