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 "qwsvdef.h"
22
23 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
24 #define RETURN_STRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(s))
25
26 /*
27 ===============================================================================
28
29 BUILT-IN FUNCTIONS
30
31 ===============================================================================
32 */
33
PF_VarString(int first)34 char *PF_VarString (int first)
35 {
36 int i;
37 static char out[256];
38
39 out[0] = 0;
40 for (i=first ; i<pr_argc ; i++)
41 {
42 strcat (out, G_STRING((OFS_PARM0+i*3)));
43 }
44 return out;
45 }
46
47
48 /*
49 =================
50 PF_errror
51
52 This is a TERMINAL error, which will kill off the entire server.
53 Dumps self.
54
55 error(value)
56 =================
57 */
PF_error(void)58 void PF_error (void)
59 {
60 char *s;
61 edict_t *ed;
62
63 s = PF_VarString(0);
64 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
65 ed = PROG_TO_EDICT(pr_global_struct->self);
66 ED_Print (ed);
67
68 SV_Error ("Program error");
69 }
70
71 /*
72 =================
73 PF_objerror
74
75 Dumps out self, then an error message. The program is aborted and self is
76 removed, but the level can continue.
77
78 objerror(value)
79 =================
80 */
PF_objerror(void)81 void PF_objerror (void)
82 {
83 char *s;
84 edict_t *ed;
85
86 s = PF_VarString(0);
87 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
88 ed = PROG_TO_EDICT(pr_global_struct->self);
89 ED_Print (ed);
90 ED_Free (ed);
91
92 SV_Error ("Program error");
93 }
94
95
96
97 /*
98 ==============
99 PF_makevectors
100
101 Writes new values for v_forward, v_up, and v_right based on angles
102 makevectors(vector)
103 ==============
104 */
PF_makevectors(void)105 void PF_makevectors (void)
106 {
107 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
108 }
109
110 /*
111 =================
112 PF_setorigin
113
114 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.
115
116 setorigin (entity, origin)
117 =================
118 */
PF_setorigin(void)119 void PF_setorigin (void)
120 {
121 edict_t *e;
122 float *org;
123
124 e = G_EDICT(OFS_PARM0);
125 org = G_VECTOR(OFS_PARM1);
126 VectorCopy (org, e->v.origin);
127 SV_LinkEdict (e, false);
128 }
129
130
131 /*
132 =================
133 PF_setsize
134
135 the size box is rotated by the current angle
136
137 setsize (entity, minvector, maxvector)
138 =================
139 */
PF_setsize(void)140 void PF_setsize (void)
141 {
142 edict_t *e;
143 float *min, *max;
144
145 e = G_EDICT(OFS_PARM0);
146 min = G_VECTOR(OFS_PARM1);
147 max = G_VECTOR(OFS_PARM2);
148 VectorCopy (min, e->v.mins);
149 VectorCopy (max, e->v.maxs);
150 VectorSubtract (max, min, e->v.size);
151 SV_LinkEdict (e, false);
152 }
153
154
155 /*
156 =================
157 PF_setmodel
158
159 setmodel(entity, model)
160 Also sets size, mins, and maxs for inline bmodels
161 =================
162 */
PF_setmodel(void)163 void PF_setmodel (void)
164 {
165 edict_t *e;
166 char *m, **check;
167 int i;
168 model_t *mod;
169
170 e = G_EDICT(OFS_PARM0);
171 m = G_STRING(OFS_PARM1);
172
173 // check to see if model was properly precached
174 for (i=0, check = sv.model_precache ; *check ; i++, check++)
175 if (!strcmp(*check, m))
176 break;
177
178 if (!*check)
179 PR_RunError ("no precache: %s\n", m);
180
181 e->v.model = PR_SetString(m);
182 e->v.modelindex = i;
183
184 // if it is an inline model, get the size information for it
185 if (m[0] == '*')
186 {
187 mod = Mod_ForName (m, true);
188 VectorCopy (mod->mins, e->v.mins);
189 VectorCopy (mod->maxs, e->v.maxs);
190 VectorSubtract (mod->maxs, mod->mins, e->v.size);
191 SV_LinkEdict (e, false);
192 }
193
194 }
195
196 /*
197 =================
198 PF_bprint
199
200 broadcast print to everyone on server
201
202 bprint(value)
203 =================
204 */
PF_bprint(void)205 void PF_bprint (void)
206 {
207 char *s;
208 int level;
209
210 level = G_FLOAT(OFS_PARM0);
211
212 s = PF_VarString(1);
213 SV_BroadcastPrintf (level, "%s", s);
214 }
215
216 /*
217 =================
218 PF_sprint
219
220 single print to a specific client
221
222 sprint(clientent, value)
223 =================
224 */
PF_sprint(void)225 void PF_sprint (void)
226 {
227 char *s;
228 client_t *client;
229 int entnum;
230 int level;
231
232 entnum = G_EDICTNUM(OFS_PARM0);
233 level = G_FLOAT(OFS_PARM1);
234
235 s = PF_VarString(2);
236
237 if (entnum < 1 || entnum > MAX_CLIENTS)
238 {
239 Con_Printf ("tried to sprint to a non-client\n");
240 return;
241 }
242
243 client = &svs.clients[entnum-1];
244
245 SV_ClientPrintf (client, level, "%s", s);
246 }
247
248
249 /*
250 =================
251 PF_centerprint
252
253 single print to a specific client
254
255 centerprint(clientent, value)
256 =================
257 */
PF_centerprint(void)258 void PF_centerprint (void)
259 {
260 char *s;
261 int entnum;
262 client_t *cl;
263
264 entnum = G_EDICTNUM(OFS_PARM0);
265 s = PF_VarString(1);
266
267 if (entnum < 1 || entnum > MAX_CLIENTS)
268 {
269 Con_Printf ("tried to sprint to a non-client\n");
270 return;
271 }
272
273 cl = &svs.clients[entnum-1];
274
275 ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
276 ClientReliableWrite_String (cl, s);
277 }
278
279
280 /*
281 =================
282 PF_normalize
283
284 vector normalize(vector)
285 =================
286 */
PF_normalize(void)287 void PF_normalize (void)
288 {
289 float *value1;
290 vec3_t newvalue;
291 float new;
292
293 value1 = G_VECTOR(OFS_PARM0);
294
295 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
296 new = sqrt(new);
297
298 if (new == 0)
299 newvalue[0] = newvalue[1] = newvalue[2] = 0;
300 else
301 {
302 new = 1/new;
303 newvalue[0] = value1[0] * new;
304 newvalue[1] = value1[1] * new;
305 newvalue[2] = value1[2] * new;
306 }
307
308 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
309 }
310
311 /*
312 =================
313 PF_vlen
314
315 scalar vlen(vector)
316 =================
317 */
PF_vlen(void)318 void PF_vlen (void)
319 {
320 float *value1;
321 float new;
322
323 value1 = G_VECTOR(OFS_PARM0);
324
325 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
326 new = sqrt(new);
327
328 G_FLOAT(OFS_RETURN) = new;
329 }
330
331 /*
332 =================
333 PF_vectoyaw
334
335 float vectoyaw(vector)
336 =================
337 */
PF_vectoyaw(void)338 void PF_vectoyaw (void)
339 {
340 float *value1;
341 float yaw;
342
343 value1 = G_VECTOR(OFS_PARM0);
344
345 if (value1[1] == 0 && value1[0] == 0)
346 yaw = 0;
347 else
348 {
349 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
350 if (yaw < 0)
351 yaw += 360;
352 }
353
354 G_FLOAT(OFS_RETURN) = yaw;
355 }
356
357
358 /*
359 =================
360 PF_vectoangles
361
362 vector vectoangles(vector)
363 =================
364 */
PF_vectoangles(void)365 void PF_vectoangles (void)
366 {
367 float *value1;
368 float forward;
369 float yaw, pitch;
370
371 value1 = G_VECTOR(OFS_PARM0);
372
373 if (value1[1] == 0 && value1[0] == 0)
374 {
375 yaw = 0;
376 if (value1[2] > 0)
377 pitch = 90;
378 else
379 pitch = 270;
380 }
381 else
382 {
383 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
384 if (yaw < 0)
385 yaw += 360;
386
387 forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
388 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
389 if (pitch < 0)
390 pitch += 360;
391 }
392
393 G_FLOAT(OFS_RETURN+0) = pitch;
394 G_FLOAT(OFS_RETURN+1) = yaw;
395 G_FLOAT(OFS_RETURN+2) = 0;
396 }
397
398 /*
399 =================
400 PF_Random
401
402 Returns a number from 0<= num < 1
403
404 random()
405 =================
406 */
PF_random(void)407 void PF_random (void)
408 {
409 float num;
410
411 num = (rand ()&0x7fff) / ((float)0x7fff);
412
413 G_FLOAT(OFS_RETURN) = num;
414 }
415
416
417 /*
418 =================
419 PF_ambientsound
420
421 =================
422 */
PF_ambientsound(void)423 void PF_ambientsound (void)
424 {
425 char **check;
426 char *samp;
427 float *pos;
428 float vol, attenuation;
429 int i, soundnum;
430
431 pos = G_VECTOR (OFS_PARM0);
432 samp = G_STRING(OFS_PARM1);
433 vol = G_FLOAT(OFS_PARM2);
434 attenuation = G_FLOAT(OFS_PARM3);
435
436 // check to see if samp was properly precached
437 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
438 if (!strcmp(*check,samp))
439 break;
440
441 if (!*check)
442 {
443 Con_Printf ("no precache: %s\n", samp);
444 return;
445 }
446
447 // add an svc_spawnambient command to the level signon packet
448
449 MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
450 for (i=0 ; i<3 ; i++)
451 MSG_WriteCoord(&sv.signon, pos[i]);
452
453 MSG_WriteByte (&sv.signon, soundnum);
454
455 MSG_WriteByte (&sv.signon, vol*255);
456 MSG_WriteByte (&sv.signon, attenuation*64);
457
458 }
459
460 /*
461 =================
462 PF_sound
463
464 Each entity can have eight independant sound sources, like voice,
465 weapon, feet, etc.
466
467 Channel 0 is an auto-allocate channel, the others override anything
468 allready running on that entity/channel pair.
469
470 An attenuation of 0 will play full volume everywhere in the level.
471 Larger attenuations will drop off.
472
473 =================
474 */
PF_sound(void)475 void PF_sound (void)
476 {
477 char *sample;
478 int channel;
479 edict_t *entity;
480 int volume;
481 float attenuation;
482
483 entity = G_EDICT(OFS_PARM0);
484 channel = G_FLOAT(OFS_PARM1);
485 sample = G_STRING(OFS_PARM2);
486 volume = G_FLOAT(OFS_PARM3) * 255;
487 attenuation = G_FLOAT(OFS_PARM4);
488
489 SV_StartSound (entity, channel, sample, volume, attenuation);
490 }
491
492 /*
493 =================
494 PF_break
495
496 break()
497 =================
498 */
PF_break(void)499 void PF_break (void)
500 {
501 Con_Printf ("break statement\n");
502 *(int *)-4 = 0; // dump to debugger
503 // PR_RunError ("break statement");
504 }
505
506 /*
507 =================
508 PF_traceline
509
510 Used for use tracing and shot targeting
511 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
512 if the tryents flag is set.
513
514 traceline (vector1, vector2, tryents)
515 =================
516 */
PF_traceline(void)517 void PF_traceline (void)
518 {
519 float *v1, *v2;
520 trace_t trace;
521 int nomonsters;
522 edict_t *ent;
523
524 v1 = G_VECTOR(OFS_PARM0);
525 v2 = G_VECTOR(OFS_PARM1);
526 nomonsters = G_FLOAT(OFS_PARM2);
527 ent = G_EDICT(OFS_PARM3);
528
529 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
530
531 pr_global_struct->trace_allsolid = trace.allsolid;
532 pr_global_struct->trace_startsolid = trace.startsolid;
533 pr_global_struct->trace_fraction = trace.fraction;
534 pr_global_struct->trace_inwater = trace.inwater;
535 pr_global_struct->trace_inopen = trace.inopen;
536 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
537 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
538 pr_global_struct->trace_plane_dist = trace.plane.dist;
539 if (trace.ent)
540 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
541 else
542 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
543 }
544
545 /*
546 =================
547 PF_checkpos
548
549 Returns true if the given entity can move to the given position from it's
550 current position by walking or rolling.
551 FIXME: make work...
552 scalar checkpos (entity, vector)
553 =================
554 */
PF_checkpos(void)555 void PF_checkpos (void)
556 {
557 }
558
559 //============================================================================
560
561 byte checkpvs[MAX_MAP_LEAFS/8];
562
PF_newcheckclient(int check)563 int PF_newcheckclient (int check)
564 {
565 int i;
566 byte *pvs;
567 edict_t *ent;
568 mleaf_t *leaf;
569 vec3_t org;
570
571 // cycle to the next one
572
573 if (check < 1)
574 check = 1;
575 if (check > MAX_CLIENTS)
576 check = MAX_CLIENTS;
577
578 if (check == MAX_CLIENTS)
579 i = 1;
580 else
581 i = check + 1;
582
583 for ( ; ; i++)
584 {
585 if (i == MAX_CLIENTS+1)
586 i = 1;
587
588 ent = EDICT_NUM(i);
589
590 if (i == check)
591 break; // didn't find anything else
592
593 if (ent->free)
594 continue;
595 if (ent->v.health <= 0)
596 continue;
597 if ((int)ent->v.flags & FL_NOTARGET)
598 continue;
599
600 // anything that is a client, or has a client as an enemy
601 break;
602 }
603
604 // get the PVS for the entity
605 VectorAdd (ent->v.origin, ent->v.view_ofs, org);
606 leaf = Mod_PointInLeaf (org, sv.worldmodel);
607 pvs = Mod_LeafPVS (leaf, sv.worldmodel);
608 memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
609
610 return i;
611 }
612
613 /*
614 =================
615 PF_checkclient
616
617 Returns a client (or object that has a client enemy) that would be a
618 valid target.
619
620 If there are more than one valid options, they are cycled each frame
621
622 If (self.origin + self.viewofs) is not in the PVS of the current target,
623 it is not returned at all.
624
625 name checkclient ()
626 =================
627 */
628 #define MAX_CHECK 16
629 int c_invis, c_notvis;
PF_checkclient(void)630 void PF_checkclient (void)
631 {
632 edict_t *ent, *self;
633 mleaf_t *leaf;
634 int l;
635 vec3_t view;
636
637 // find a new check if on a new frame
638 if (sv.time - sv.lastchecktime >= 0.1)
639 {
640 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
641 sv.lastchecktime = sv.time;
642 }
643
644 // return check if it might be visible
645 ent = EDICT_NUM(sv.lastcheck);
646 if (ent->free || ent->v.health <= 0)
647 {
648 RETURN_EDICT(sv.edicts);
649 return;
650 }
651
652 // if current entity can't possibly see the check entity, return 0
653 self = PROG_TO_EDICT(pr_global_struct->self);
654 VectorAdd (self->v.origin, self->v.view_ofs, view);
655 leaf = Mod_PointInLeaf (view, sv.worldmodel);
656 l = (leaf - sv.worldmodel->leafs) - 1;
657 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
658 {
659 c_notvis++;
660 RETURN_EDICT(sv.edicts);
661 return;
662 }
663
664 // might be able to see it
665 c_invis++;
666 RETURN_EDICT(ent);
667 }
668
669 //============================================================================
670
671
672 /*
673 =================
674 PF_stuffcmd
675
676 Sends text over to the client's execution buffer
677
678 stuffcmd (clientent, value)
679 =================
680 */
PF_stuffcmd(void)681 void PF_stuffcmd (void)
682 {
683 int entnum;
684 char *str;
685 client_t *cl;
686
687 entnum = G_EDICTNUM(OFS_PARM0);
688 if (entnum < 1 || entnum > MAX_CLIENTS)
689 PR_RunError ("Parm 0 not a client");
690 str = G_STRING(OFS_PARM1);
691
692 cl = &svs.clients[entnum-1];
693
694 if (strcmp(str, "disconnect\n") == 0) {
695 // so long and thanks for all the fish
696 cl->drop = true;
697 return;
698 }
699
700 ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(str));
701 ClientReliableWrite_String (cl, str);
702 }
703
704 /*
705 =================
706 PF_localcmd
707
708 Sends text over to the client's execution buffer
709
710 localcmd (string)
711 =================
712 */
PF_localcmd(void)713 void PF_localcmd (void)
714 {
715 char *str;
716
717 str = G_STRING(OFS_PARM0);
718 Cbuf_AddText (str);
719 }
720
721 /*
722 =================
723 PF_cvar
724
725 float cvar (string)
726 =================
727 */
PF_cvar(void)728 void PF_cvar (void)
729 {
730 char *str;
731
732 str = G_STRING(OFS_PARM0);
733
734 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
735 }
736
737 /*
738 =================
739 PF_cvar_set
740
741 float cvar (string)
742 =================
743 */
PF_cvar_set(void)744 void PF_cvar_set (void)
745 {
746 char *var, *val;
747
748 var = G_STRING(OFS_PARM0);
749 val = G_STRING(OFS_PARM1);
750
751 Cvar_Set (var, val);
752 }
753
754 /*
755 =================
756 PF_findradius
757
758 Returns a chain of entities that have origins within a spherical area
759
760 findradius (origin, radius)
761 =================
762 */
PF_findradius(void)763 void PF_findradius (void)
764 {
765 edict_t *ent, *chain;
766 float rad;
767 float *org;
768 vec3_t eorg;
769 int i, j;
770
771 chain = (edict_t *)sv.edicts;
772
773 org = G_VECTOR(OFS_PARM0);
774 rad = G_FLOAT(OFS_PARM1);
775
776 ent = NEXT_EDICT(sv.edicts);
777 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
778 {
779 if (ent->free)
780 continue;
781 if (ent->v.solid == SOLID_NOT)
782 continue;
783 for (j=0 ; j<3 ; j++)
784 eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
785 if (Length(eorg) > rad)
786 continue;
787
788 ent->v.chain = EDICT_TO_PROG(chain);
789 chain = ent;
790 }
791
792 RETURN_EDICT(chain);
793 }
794
795
796 /*
797 =========
798 PF_dprint
799 =========
800 */
PF_dprint(void)801 void PF_dprint (void)
802 {
803 Con_Printf ("%s",PF_VarString(0));
804 }
805
806 char pr_string_temp[128];
807
PF_ftos(void)808 void PF_ftos (void)
809 {
810 float v;
811 v = G_FLOAT(OFS_PARM0);
812
813 if (v == (int)v)
814 sprintf (pr_string_temp, "%d",(int)v);
815 else
816 sprintf (pr_string_temp, "%5.1f",v);
817 G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
818 }
819
PF_fabs(void)820 void PF_fabs (void)
821 {
822 float v;
823 v = G_FLOAT(OFS_PARM0);
824 G_FLOAT(OFS_RETURN) = fabs(v);
825 }
826
PF_vtos(void)827 void PF_vtos (void)
828 {
829 sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
830 G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
831 }
832
PF_Spawn(void)833 void PF_Spawn (void)
834 {
835 edict_t *ed;
836 ed = ED_Alloc();
837 RETURN_EDICT(ed);
838 }
839
PF_Remove(void)840 void PF_Remove (void)
841 {
842 edict_t *ed;
843
844 ed = G_EDICT(OFS_PARM0);
845 ED_Free (ed);
846 }
847
848
849 // entity (entity start, .string field, string match) find = #5;
PF_Find(void)850 void PF_Find (void)
851 {
852 int e;
853 int f;
854 char *s, *t;
855 edict_t *ed;
856
857 e = G_EDICTNUM(OFS_PARM0);
858 f = G_INT(OFS_PARM1);
859 s = G_STRING(OFS_PARM2);
860 if (!s)
861 PR_RunError ("PF_Find: bad search string");
862
863 for (e++ ; e < sv.num_edicts ; e++)
864 {
865 ed = EDICT_NUM(e);
866 if (ed->free)
867 continue;
868 t = E_STRING(ed,f);
869 if (!t)
870 continue;
871 if (!strcmp(t,s))
872 {
873 RETURN_EDICT(ed);
874 return;
875 }
876 }
877
878 RETURN_EDICT(sv.edicts);
879 }
880
PR_CheckEmptyString(char * s)881 void PR_CheckEmptyString (char *s)
882 {
883 if (s[0] <= ' ')
884 PR_RunError ("Bad string");
885 }
886
PF_precache_file(void)887 void PF_precache_file (void)
888 { // precache_file is only used to copy files with qcc, it does nothing
889 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
890 }
891
PF_precache_sound(void)892 void PF_precache_sound (void)
893 {
894 char *s;
895 int i;
896
897 if (sv.state != ss_loading)
898 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
899
900 s = G_STRING(OFS_PARM0);
901 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
902 PR_CheckEmptyString (s);
903
904 for (i=0 ; i<MAX_SOUNDS ; i++)
905 {
906 if (!sv.sound_precache[i])
907 {
908 sv.sound_precache[i] = s;
909 return;
910 }
911 if (!strcmp(sv.sound_precache[i], s))
912 return;
913 }
914 PR_RunError ("PF_precache_sound: overflow");
915 }
916
PF_precache_model(void)917 void PF_precache_model (void)
918 {
919 char *s;
920 int i;
921
922 if (sv.state != ss_loading)
923 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
924
925 s = G_STRING(OFS_PARM0);
926 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
927 PR_CheckEmptyString (s);
928
929 for (i=0 ; i<MAX_MODELS ; i++)
930 {
931 if (!sv.model_precache[i])
932 {
933 sv.model_precache[i] = s;
934 return;
935 }
936 if (!strcmp(sv.model_precache[i], s))
937 return;
938 }
939 PR_RunError ("PF_precache_model: overflow");
940 }
941
942
PF_coredump(void)943 void PF_coredump (void)
944 {
945 ED_PrintEdicts ();
946 }
947
PF_traceon(void)948 void PF_traceon (void)
949 {
950 pr_trace = true;
951 }
952
PF_traceoff(void)953 void PF_traceoff (void)
954 {
955 pr_trace = false;
956 }
957
PF_eprint(void)958 void PF_eprint (void)
959 {
960 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
961 }
962
963 /*
964 ===============
965 PF_walkmove
966
967 float(float yaw, float dist) walkmove
968 ===============
969 */
PF_walkmove(void)970 void PF_walkmove (void)
971 {
972 edict_t *ent;
973 float yaw, dist;
974 vec3_t move;
975 dfunction_t *oldf;
976 int oldself;
977
978 ent = PROG_TO_EDICT(pr_global_struct->self);
979 yaw = G_FLOAT(OFS_PARM0);
980 dist = G_FLOAT(OFS_PARM1);
981
982 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
983 {
984 G_FLOAT(OFS_RETURN) = 0;
985 return;
986 }
987
988 yaw = yaw*M_PI*2 / 360;
989
990 move[0] = cos(yaw)*dist;
991 move[1] = sin(yaw)*dist;
992 move[2] = 0;
993
994 // save program state, because SV_movestep may call other progs
995 oldf = pr_xfunction;
996 oldself = pr_global_struct->self;
997
998 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
999
1000
1001 // restore program state
1002 pr_xfunction = oldf;
1003 pr_global_struct->self = oldself;
1004 }
1005
1006 /*
1007 ===============
1008 PF_droptofloor
1009
1010 void() droptofloor
1011 ===============
1012 */
PF_droptofloor(void)1013 void PF_droptofloor (void)
1014 {
1015 edict_t *ent;
1016 vec3_t end;
1017 trace_t trace;
1018
1019 ent = PROG_TO_EDICT(pr_global_struct->self);
1020
1021 VectorCopy (ent->v.origin, end);
1022 end[2] -= 256;
1023
1024 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1025
1026 if (trace.fraction == 1 || trace.allsolid)
1027 G_FLOAT(OFS_RETURN) = 0;
1028 else
1029 {
1030 VectorCopy (trace.endpos, ent->v.origin);
1031 SV_LinkEdict (ent, false);
1032 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1033 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1034 G_FLOAT(OFS_RETURN) = 1;
1035 }
1036 }
1037
1038 /*
1039 ===============
1040 PF_lightstyle
1041
1042 void(float style, string value) lightstyle
1043 ===============
1044 */
PF_lightstyle(void)1045 void PF_lightstyle (void)
1046 {
1047 int style;
1048 char *val;
1049 client_t *client;
1050 int j;
1051
1052 style = G_FLOAT(OFS_PARM0);
1053 val = G_STRING(OFS_PARM1);
1054
1055 // change the string in sv
1056 sv.lightstyles[style] = val;
1057
1058 // send message to all clients on this server
1059 if (sv.state != ss_active)
1060 return;
1061
1062 for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
1063 if ( client->state == cs_spawned )
1064 {
1065 ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3);
1066 ClientReliableWrite_Char (client, style);
1067 ClientReliableWrite_String (client, val);
1068 }
1069 }
1070
PF_rint(void)1071 void PF_rint (void)
1072 {
1073 float f;
1074 f = G_FLOAT(OFS_PARM0);
1075 if (f > 0)
1076 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1077 else
1078 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1079 }
PF_floor(void)1080 void PF_floor (void)
1081 {
1082 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1083 }
PF_ceil(void)1084 void PF_ceil (void)
1085 {
1086 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1087 }
1088
1089
1090 /*
1091 =============
1092 PF_checkbottom
1093 =============
1094 */
PF_checkbottom(void)1095 void PF_checkbottom (void)
1096 {
1097 edict_t *ent;
1098
1099 ent = G_EDICT(OFS_PARM0);
1100
1101 G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
1102 }
1103
1104 /*
1105 =============
1106 PF_pointcontents
1107 =============
1108 */
PF_pointcontents(void)1109 void PF_pointcontents (void)
1110 {
1111 float *v;
1112
1113 v = G_VECTOR(OFS_PARM0);
1114
1115 G_FLOAT(OFS_RETURN) = SV_PointContents (v);
1116 }
1117
1118 /*
1119 =============
1120 PF_nextent
1121
1122 entity nextent(entity)
1123 =============
1124 */
PF_nextent(void)1125 void PF_nextent (void)
1126 {
1127 int i;
1128 edict_t *ent;
1129
1130 i = G_EDICTNUM(OFS_PARM0);
1131 while (1)
1132 {
1133 i++;
1134 if (i == sv.num_edicts)
1135 {
1136 RETURN_EDICT(sv.edicts);
1137 return;
1138 }
1139 ent = EDICT_NUM(i);
1140 if (!ent->free)
1141 {
1142 RETURN_EDICT(ent);
1143 return;
1144 }
1145 }
1146 }
1147
1148 /*
1149 =============
1150 PF_aim
1151
1152 Pick a vector for the player to shoot along
1153 vector aim(entity, missilespeed)
1154 =============
1155 */
1156 //cvar_t sv_aim = {"sv_aim", "0.93"};
1157 cvar_t sv_aim = {"sv_aim", "2"};
PF_aim(void)1158 void PF_aim (void)
1159 {
1160 edict_t *ent, *check, *bestent;
1161 vec3_t start, dir, end, bestdir;
1162 int i, j;
1163 trace_t tr;
1164 float dist, bestdist;
1165 float speed;
1166 char *noaim;
1167
1168 ent = G_EDICT(OFS_PARM0);
1169 speed = G_FLOAT(OFS_PARM1);
1170
1171 VectorCopy (ent->v.origin, start);
1172 start[2] += 20;
1173
1174 // noaim option
1175 i = NUM_FOR_EDICT(ent);
1176 if (i>0 && i<MAX_CLIENTS)
1177 {
1178 noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "noaim");
1179 if (atoi(noaim) > 0)
1180 {
1181 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1182 return;
1183 }
1184 }
1185
1186 // try sending a trace straight
1187 VectorCopy (pr_global_struct->v_forward, dir);
1188 VectorMA (start, 2048, dir, end);
1189 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1190 if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1191 && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1192 {
1193 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1194 return;
1195 }
1196
1197
1198 // try all possible entities
1199 VectorCopy (dir, bestdir);
1200 bestdist = sv_aim.value;
1201 bestent = NULL;
1202
1203 check = NEXT_EDICT(sv.edicts);
1204 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1205 {
1206 if (check->v.takedamage != DAMAGE_AIM)
1207 continue;
1208 if (check == ent)
1209 continue;
1210 if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1211 continue; // don't aim at teammate
1212 for (j=0 ; j<3 ; j++)
1213 end[j] = check->v.origin[j]
1214 + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1215 VectorSubtract (end, start, dir);
1216 VectorNormalize (dir);
1217 dist = DotProduct (dir, pr_global_struct->v_forward);
1218 if (dist < bestdist)
1219 continue; // to far to turn
1220 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1221 if (tr.ent == check)
1222 { // can shoot at this one
1223 bestdist = dist;
1224 bestent = check;
1225 }
1226 }
1227
1228 if (bestent)
1229 {
1230 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1231 dist = DotProduct (dir, pr_global_struct->v_forward);
1232 VectorScale (pr_global_struct->v_forward, dist, end);
1233 end[2] = dir[2];
1234 VectorNormalize (end);
1235 VectorCopy (end, G_VECTOR(OFS_RETURN));
1236 }
1237 else
1238 {
1239 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1240 }
1241 }
1242
1243 /*
1244 ==============
1245 PF_changeyaw
1246
1247 This was a major timewaster in progs, so it was converted to C
1248 ==============
1249 */
PF_changeyaw(void)1250 void PF_changeyaw (void)
1251 {
1252 edict_t *ent;
1253 float ideal, current, move, speed;
1254
1255 ent = PROG_TO_EDICT(pr_global_struct->self);
1256 current = anglemod( ent->v.angles[1] );
1257 ideal = ent->v.ideal_yaw;
1258 speed = ent->v.yaw_speed;
1259
1260 if (current == ideal)
1261 return;
1262 move = ideal - current;
1263 if (ideal > current)
1264 {
1265 if (move >= 180)
1266 move = move - 360;
1267 }
1268 else
1269 {
1270 if (move <= -180)
1271 move = move + 360;
1272 }
1273 if (move > 0)
1274 {
1275 if (move > speed)
1276 move = speed;
1277 }
1278 else
1279 {
1280 if (move < -speed)
1281 move = -speed;
1282 }
1283
1284 ent->v.angles[1] = anglemod (current + move);
1285 }
1286
1287 /*
1288 ===============================================================================
1289
1290 MESSAGE WRITING
1291
1292 ===============================================================================
1293 */
1294
1295 #define MSG_BROADCAST 0 // unreliable to all
1296 #define MSG_ONE 1 // reliable to one (msg_entity)
1297 #define MSG_ALL 2 // reliable to all
1298 #define MSG_INIT 3 // write to the init string
1299 #define MSG_MULTICAST 4 // for multicast()
1300
WriteDest(void)1301 sizebuf_t *WriteDest (void)
1302 {
1303 int entnum;
1304 int dest;
1305 edict_t *ent;
1306
1307 dest = G_FLOAT(OFS_PARM0);
1308 switch (dest)
1309 {
1310 case MSG_BROADCAST:
1311 return &sv.datagram;
1312
1313 case MSG_ONE:
1314 SV_Error("Shouldn't be at MSG_ONE");
1315 #if 0
1316 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1317 entnum = NUM_FOR_EDICT(ent);
1318 if (entnum < 1 || entnum > MAX_CLIENTS)
1319 PR_RunError ("WriteDest: not a client");
1320 return &svs.clients[entnum-1].netchan.message;
1321 #endif
1322
1323 case MSG_ALL:
1324 return &sv.reliable_datagram;
1325
1326 case MSG_INIT:
1327 if (sv.state != ss_loading)
1328 PR_RunError ("PF_Write_*: MSG_INIT can only be written in spawn functions");
1329 return &sv.signon;
1330
1331 case MSG_MULTICAST:
1332 return &sv.multicast;
1333
1334 default:
1335 PR_RunError ("WriteDest: bad destination");
1336 break;
1337 }
1338
1339 return NULL;
1340 }
1341
Write_GetClient(void)1342 static client_t *Write_GetClient(void)
1343 {
1344 int entnum;
1345 edict_t *ent;
1346
1347 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1348 entnum = NUM_FOR_EDICT(ent);
1349 if (entnum < 1 || entnum > MAX_CLIENTS)
1350 PR_RunError ("WriteDest: not a client");
1351 return &svs.clients[entnum-1];
1352 }
1353
1354
PF_WriteByte(void)1355 void PF_WriteByte (void)
1356 {
1357 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1358 client_t *cl = Write_GetClient();
1359 ClientReliableCheckBlock(cl, 1);
1360 ClientReliableWrite_Byte(cl, G_FLOAT(OFS_PARM1));
1361 } else
1362 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1363 }
1364
PF_WriteChar(void)1365 void PF_WriteChar (void)
1366 {
1367 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1368 client_t *cl = Write_GetClient();
1369 ClientReliableCheckBlock(cl, 1);
1370 ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1));
1371 } else
1372 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1373 }
1374
PF_WriteShort(void)1375 void PF_WriteShort (void)
1376 {
1377 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1378 client_t *cl = Write_GetClient();
1379 ClientReliableCheckBlock(cl, 2);
1380 ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1));
1381 } else
1382 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1383 }
1384
PF_WriteLong(void)1385 void PF_WriteLong (void)
1386 {
1387 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1388 client_t *cl = Write_GetClient();
1389 ClientReliableCheckBlock(cl, 4);
1390 ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1));
1391 } else
1392 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1393 }
1394
PF_WriteAngle(void)1395 void PF_WriteAngle (void)
1396 {
1397 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1398 client_t *cl = Write_GetClient();
1399 ClientReliableCheckBlock(cl, 1);
1400 ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
1401 } else
1402 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1403 }
1404
PF_WriteCoord(void)1405 void PF_WriteCoord (void)
1406 {
1407 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1408 client_t *cl = Write_GetClient();
1409 ClientReliableCheckBlock(cl, 2);
1410 ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1));
1411 } else
1412 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1413 }
1414
PF_WriteString(void)1415 void PF_WriteString (void)
1416 {
1417 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1418 client_t *cl = Write_GetClient();
1419 ClientReliableCheckBlock(cl, 1+strlen(G_STRING(OFS_PARM1)));
1420 ClientReliableWrite_String(cl, G_STRING(OFS_PARM1));
1421 } else
1422 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1423 }
1424
1425
PF_WriteEntity(void)1426 void PF_WriteEntity (void)
1427 {
1428 if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
1429 client_t *cl = Write_GetClient();
1430 ClientReliableCheckBlock(cl, 2);
1431 ClientReliableWrite_Short(cl, G_EDICTNUM(OFS_PARM1));
1432 } else
1433 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1434 }
1435
1436 //=============================================================================
1437
1438 int SV_ModelIndex (char *name);
1439
PF_makestatic(void)1440 void PF_makestatic (void)
1441 {
1442 edict_t *ent;
1443 int i;
1444
1445 ent = G_EDICT(OFS_PARM0);
1446
1447 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1448
1449 MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
1450
1451 MSG_WriteByte (&sv.signon, ent->v.frame);
1452 MSG_WriteByte (&sv.signon, ent->v.colormap);
1453 MSG_WriteByte (&sv.signon, ent->v.skin);
1454 for (i=0 ; i<3 ; i++)
1455 {
1456 MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1457 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1458 }
1459
1460 // throw the entity away now
1461 ED_Free (ent);
1462 }
1463
1464 //=============================================================================
1465
1466 /*
1467 ==============
1468 PF_setspawnparms
1469 ==============
1470 */
PF_setspawnparms(void)1471 void PF_setspawnparms (void)
1472 {
1473 edict_t *ent;
1474 int i;
1475 client_t *client;
1476
1477 ent = G_EDICT(OFS_PARM0);
1478 i = NUM_FOR_EDICT(ent);
1479 if (i < 1 || i > MAX_CLIENTS)
1480 PR_RunError ("Entity is not a client");
1481
1482 // copy spawn parms out of the client_t
1483 client = svs.clients + (i-1);
1484
1485 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1486 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1487 }
1488
1489 /*
1490 ==============
1491 PF_changelevel
1492 ==============
1493 */
PF_changelevel(void)1494 void PF_changelevel (void)
1495 {
1496 char *s;
1497 static int last_spawncount;
1498
1499 // make sure we don't issue two changelevels
1500 if (svs.spawncount == last_spawncount)
1501 return;
1502 last_spawncount = svs.spawncount;
1503
1504 s = G_STRING(OFS_PARM0);
1505 Cbuf_AddText (va("map %s\n",s));
1506 }
1507
1508
1509 /*
1510 ==============
1511 PF_logfrag
1512
1513 logfrag (killer, killee)
1514 ==============
1515 */
PF_logfrag(void)1516 void PF_logfrag (void)
1517 {
1518 edict_t *ent1, *ent2;
1519 int e1, e2;
1520 char *s;
1521
1522 ent1 = G_EDICT(OFS_PARM0);
1523 ent2 = G_EDICT(OFS_PARM1);
1524
1525 e1 = NUM_FOR_EDICT(ent1);
1526 e2 = NUM_FOR_EDICT(ent2);
1527
1528 if (e1 < 1 || e1 > MAX_CLIENTS
1529 || e2 < 1 || e2 > MAX_CLIENTS)
1530 return;
1531
1532 s = va("\\%s\\%s\\\n",svs.clients[e1-1].name, svs.clients[e2-1].name);
1533
1534 SZ_Print (&svs.log[svs.logsequence&1], s);
1535 if (sv_fraglogfile) {
1536 fprintf (sv_fraglogfile, s);
1537 fflush (sv_fraglogfile);
1538 }
1539 }
1540
1541
1542 /*
1543 ==============
1544 PF_infokey
1545
1546 string(entity e, string key) infokey
1547 ==============
1548 */
PF_infokey(void)1549 void PF_infokey (void)
1550 {
1551 edict_t *e;
1552 int e1;
1553 char *value;
1554 char *key;
1555 static char ov[256];
1556
1557 e = G_EDICT(OFS_PARM0);
1558 e1 = NUM_FOR_EDICT(e);
1559 key = G_STRING(OFS_PARM1);
1560
1561 if (e1 == 0) {
1562 if ((value = Info_ValueForKey (svs.info, key)) == NULL ||
1563 !*value)
1564 value = Info_ValueForKey(localinfo, key);
1565 } else if (e1 <= MAX_CLIENTS) {
1566 if (!strcmp(key, "ip"))
1567 value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].netchan.remote_address));
1568 else if (!strcmp(key, "ping")) {
1569 int ping = SV_CalcPing (&svs.clients[e1-1]);
1570 sprintf(ov, "%d", ping);
1571 value = ov;
1572 } else
1573 value = Info_ValueForKey (svs.clients[e1-1].userinfo, key);
1574 } else
1575 value = "";
1576
1577 RETURN_STRING(value);
1578 }
1579
1580 /*
1581 ==============
1582 PF_stof
1583
1584 float(string s) stof
1585 ==============
1586 */
PF_stof(void)1587 void PF_stof (void)
1588 {
1589 char *s;
1590
1591 s = G_STRING(OFS_PARM0);
1592
1593 G_FLOAT(OFS_RETURN) = atof(s);
1594 }
1595
1596
1597 /*
1598 ==============
1599 PF_multicast
1600
1601 void(vector where, float set) multicast
1602 ==============
1603 */
PF_multicast(void)1604 void PF_multicast (void)
1605 {
1606 float *o;
1607 int to;
1608
1609 o = G_VECTOR(OFS_PARM0);
1610 to = G_FLOAT(OFS_PARM1);
1611
1612 SV_Multicast (o, to);
1613 }
1614
1615
PF_Fixme(void)1616 void PF_Fixme (void)
1617 {
1618 PR_RunError ("unimplemented bulitin");
1619 }
1620
1621
1622
1623 builtin_t pr_builtin[] =
1624 {
1625 PF_Fixme,
1626 PF_makevectors, // void(entity e) makevectors = #1;
1627 PF_setorigin, // void(entity e, vector o) setorigin = #2;
1628 PF_setmodel, // void(entity e, string m) setmodel = #3;
1629 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
1630 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
1631 PF_break, // void() break = #6;
1632 PF_random, // float() random = #7;
1633 PF_sound, // void(entity e, float chan, string samp) sound = #8;
1634 PF_normalize, // vector(vector v) normalize = #9;
1635 PF_error, // void(string e) error = #10;
1636 PF_objerror, // void(string e) objerror = #11;
1637 PF_vlen, // float(vector v) vlen = #12;
1638 PF_vectoyaw, // float(vector v) vectoyaw = #13;
1639 PF_Spawn, // entity() spawn = #14;
1640 PF_Remove, // void(entity e) remove = #15;
1641 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
1642 PF_checkclient, // entity() clientlist = #17;
1643 PF_Find, // entity(entity start, .string fld, string match) find = #18;
1644 PF_precache_sound, // void(string s) precache_sound = #19;
1645 PF_precache_model, // void(string s) precache_model = #20;
1646 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
1647 PF_findradius, // entity(vector org, float rad) findradius = #22;
1648 PF_bprint, // void(string s) bprint = #23;
1649 PF_sprint, // void(entity client, string s) sprint = #24;
1650 PF_dprint, // void(string s) dprint = #25;
1651 PF_ftos, // void(string s) ftos = #26;
1652 PF_vtos, // void(string s) vtos = #27;
1653 PF_coredump,
1654 PF_traceon,
1655 PF_traceoff,
1656 PF_eprint, // void(entity e) debug print an entire entity
1657 PF_walkmove, // float(float yaw, float dist) walkmove
1658 PF_Fixme, // float(float yaw, float dist) walkmove
1659 PF_droptofloor,
1660 PF_lightstyle,
1661 PF_rint,
1662 PF_floor,
1663 PF_ceil,
1664 PF_Fixme,
1665 PF_checkbottom,
1666 PF_pointcontents,
1667 PF_Fixme,
1668 PF_fabs,
1669 PF_aim,
1670 PF_cvar,
1671 PF_localcmd,
1672 PF_nextent,
1673 PF_Fixme,
1674 PF_changeyaw,
1675 PF_Fixme,
1676 PF_vectoangles,
1677
1678 PF_WriteByte,
1679 PF_WriteChar,
1680 PF_WriteShort,
1681 PF_WriteLong,
1682 PF_WriteCoord,
1683 PF_WriteAngle,
1684 PF_WriteString,
1685 PF_WriteEntity,
1686
1687 PF_Fixme,
1688 PF_Fixme,
1689 PF_Fixme,
1690 PF_Fixme,
1691 PF_Fixme,
1692 PF_Fixme,
1693 PF_Fixme,
1694
1695 SV_MoveToGoal,
1696 PF_precache_file,
1697 PF_makestatic,
1698
1699 PF_changelevel,
1700 PF_Fixme,
1701
1702 PF_cvar_set,
1703 PF_centerprint,
1704
1705 PF_ambientsound,
1706
1707 PF_precache_model,
1708 PF_precache_sound, // precache_sound2 is different only for qcc
1709 PF_precache_file,
1710
1711 PF_setspawnparms,
1712
1713 PF_logfrag,
1714
1715 PF_infokey,
1716 PF_stof,
1717 PF_multicast
1718 };
1719
1720 builtin_t *pr_builtins = pr_builtin;
1721 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
1722
1723