Replaced Exit() by exit() because Exit() is like abort().
[AROS-Contrib.git] / Games / Quake / pr_cmds.c
blob4c35921e78ba3b202599a1dd0538812609387617
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
21 #include "quakedef.h"
23 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
26 ===============================================================================
28 BUILT-IN FUNCTIONS
30 ===============================================================================
33 char *PF_VarString (int first)
35 int i;
36 static char out[256];
38 out[0] = 0;
39 for (i=first ; i<pr_argc ; i++)
41 strcat (out, G_STRING((OFS_PARM0+i*3)));
43 return out;
48 =================
49 PF_errror
51 This is a TERMINAL error, which will kill off the entire server.
52 Dumps self.
54 error(value)
55 =================
57 void PF_error (void)
59 char *s;
60 edict_t *ed;
62 s = PF_VarString(0);
63 Con_Printf ("======SERVER ERROR in %s:\n%s\n"
64 ,pr_strings + pr_xfunction->s_name,s);
65 ed = PROG_TO_EDICT(pr_global_struct->self);
66 ED_Print (ed);
68 Host_Error ("Program error");
72 =================
73 PF_objerror
75 Dumps out self, then an error message. The program is aborted and self is
76 removed, but the level can continue.
78 objerror(value)
79 =================
81 void PF_objerror (void)
83 char *s;
84 edict_t *ed;
86 s = PF_VarString(0);
87 Con_Printf ("======OBJECT ERROR in %s:\n%s\n"
88 ,pr_strings + pr_xfunction->s_name,s);
89 ed = PROG_TO_EDICT(pr_global_struct->self);
90 ED_Print (ed);
91 ED_Free (ed);
93 Host_Error ("Program error");
99 ==============
100 PF_makevectors
102 Writes new values for v_forward, v_up, and v_right based on angles
103 makevectors(vector)
104 ==============
106 void PF_makevectors (void)
108 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
112 =================
113 PF_setorigin
115 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.
117 setorigin (entity, origin)
118 =================
120 void PF_setorigin (void)
122 edict_t *e;
123 float *org;
125 e = G_EDICT(OFS_PARM0);
126 org = G_VECTOR(OFS_PARM1);
127 VectorCopy (org, e->v.origin);
128 SV_LinkEdict (e, false);
132 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
134 float *angles;
135 vec3_t rmin, rmax;
136 float bounds[2][3];
137 float xvector[2], yvector[2];
138 float a;
139 vec3_t base, transformed;
140 int i, j, k, l;
142 for (i=0 ; i<3 ; i++)
143 if (min[i] > max[i])
144 PR_RunError ("backwards mins/maxs");
146 rotate = false; // FIXME: implement rotation properly again
148 if (!rotate)
150 VectorCopy (min, rmin);
151 VectorCopy (max, rmax);
153 else
155 // find min / max for rotations
156 angles = e->v.angles;
158 a = angles[1]/180 * M_PI;
160 xvector[0] = cos(a);
161 xvector[1] = sin(a);
162 yvector[0] = -sin(a);
163 yvector[1] = cos(a);
165 VectorCopy (min, bounds[0]);
166 VectorCopy (max, bounds[1]);
168 rmin[0] = rmin[1] = rmin[2] = 9999;
169 rmax[0] = rmax[1] = rmax[2] = -9999;
171 for (i=0 ; i<= 1 ; i++)
173 base[0] = bounds[i][0];
174 for (j=0 ; j<= 1 ; j++)
176 base[1] = bounds[j][1];
177 for (k=0 ; k<= 1 ; k++)
179 base[2] = bounds[k][2];
181 // transform the point
182 transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
183 transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
184 transformed[2] = base[2];
186 for (l=0 ; l<3 ; l++)
188 if (transformed[l] < rmin[l])
189 rmin[l] = transformed[l];
190 if (transformed[l] > rmax[l])
191 rmax[l] = transformed[l];
198 // set derived values
199 VectorCopy (rmin, e->v.mins);
200 VectorCopy (rmax, e->v.maxs);
201 VectorSubtract (max, min, e->v.size);
203 SV_LinkEdict (e, false);
207 =================
208 PF_setsize
210 the size box is rotated by the current angle
212 setsize (entity, minvector, maxvector)
213 =================
215 void PF_setsize (void)
217 edict_t *e;
218 float *min, *max;
220 e = G_EDICT(OFS_PARM0);
221 min = G_VECTOR(OFS_PARM1);
222 max = G_VECTOR(OFS_PARM2);
223 SetMinMaxSize (e, min, max, false);
228 =================
229 PF_setmodel
231 setmodel(entity, model)
232 =================
234 void PF_setmodel (void)
236 edict_t *e;
237 char *m, **check;
238 model_t *mod;
239 int i;
241 e = G_EDICT(OFS_PARM0);
242 m = G_STRING(OFS_PARM1);
244 // check to see if model was properly precached
245 for (i=0, check = sv.model_precache ; *check ; i++, check++)
246 if (!strcmp(*check, m))
247 break;
249 if (!*check)
250 PR_RunError ("no precache: %s\n", m);
253 e->v.model = m - pr_strings;
254 e->v.modelindex = i; //SV_ModelIndex (m);
256 mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
258 if (mod)
259 SetMinMaxSize (e, mod->mins, mod->maxs, true);
260 else
261 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
265 =================
266 PF_bprint
268 broadcast print to everyone on server
270 bprint(value)
271 =================
273 void PF_bprint (void)
275 char *s;
277 s = PF_VarString(0);
278 SV_BroadcastPrintf ("%s", s);
282 =================
283 PF_sprint
285 single print to a specific client
287 sprint(clientent, value)
288 =================
290 void PF_sprint (void)
292 char *s;
293 client_t *client;
294 int entnum;
296 entnum = G_EDICTNUM(OFS_PARM0);
297 s = PF_VarString(1);
299 if (entnum < 1 || entnum > svs.maxclients)
301 Con_Printf ("tried to sprint to a non-client\n");
302 return;
305 client = &svs.clients[entnum-1];
307 MSG_WriteChar (&client->message,svc_print);
308 MSG_WriteString (&client->message, s );
313 =================
314 PF_centerprint
316 single print to a specific client
318 centerprint(clientent, value)
319 =================
321 void PF_centerprint (void)
323 char *s;
324 client_t *client;
325 int entnum;
327 entnum = G_EDICTNUM(OFS_PARM0);
328 s = PF_VarString(1);
330 if (entnum < 1 || entnum > svs.maxclients)
332 Con_Printf ("tried to sprint to a non-client\n");
333 return;
336 client = &svs.clients[entnum-1];
338 MSG_WriteChar (&client->message,svc_centerprint);
339 MSG_WriteString (&client->message, s );
344 =================
345 PF_normalize
347 vector normalize(vector)
348 =================
350 void PF_normalize (void)
352 float *value1;
353 vec3_t newvalue;
354 float new;
356 value1 = G_VECTOR(OFS_PARM0);
358 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
359 new = sqrt(new);
361 if (new == 0)
362 newvalue[0] = newvalue[1] = newvalue[2] = 0;
363 else
365 new = 1/new;
366 newvalue[0] = value1[0] * new;
367 newvalue[1] = value1[1] * new;
368 newvalue[2] = value1[2] * new;
371 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
375 =================
376 PF_vlen
378 scalar vlen(vector)
379 =================
381 void PF_vlen (void)
383 float *value1;
384 float new;
386 value1 = G_VECTOR(OFS_PARM0);
388 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
389 new = sqrt(new);
391 G_FLOAT(OFS_RETURN) = new;
395 =================
396 PF_vectoyaw
398 float vectoyaw(vector)
399 =================
401 void PF_vectoyaw (void)
403 float *value1;
404 float yaw;
406 value1 = G_VECTOR(OFS_PARM0);
408 if (value1[1] == 0 && value1[0] == 0)
409 yaw = 0;
410 else
412 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
413 if (yaw < 0)
414 yaw += 360;
417 G_FLOAT(OFS_RETURN) = yaw;
422 =================
423 PF_vectoangles
425 vector vectoangles(vector)
426 =================
428 void PF_vectoangles (void)
430 float *value1;
431 float forward;
432 float yaw, pitch;
434 value1 = G_VECTOR(OFS_PARM0);
436 if (value1[1] == 0 && value1[0] == 0)
438 yaw = 0;
439 if (value1[2] > 0)
440 pitch = 90;
441 else
442 pitch = 270;
444 else
446 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
447 if (yaw < 0)
448 yaw += 360;
450 forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
451 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
452 if (pitch < 0)
453 pitch += 360;
456 G_FLOAT(OFS_RETURN+0) = pitch;
457 G_FLOAT(OFS_RETURN+1) = yaw;
458 G_FLOAT(OFS_RETURN+2) = 0;
462 =================
463 PF_Random
465 Returns a number from 0<= num < 1
467 random()
468 =================
470 void PF_random (void)
472 float num;
474 num = (rand ()&0x7fff) / ((float)0x7fff);
476 G_FLOAT(OFS_RETURN) = num;
480 =================
481 PF_particle
483 particle(origin, color, count)
484 =================
486 void PF_particle (void)
488 float *org, *dir;
489 float color;
490 float count;
492 org = G_VECTOR(OFS_PARM0);
493 dir = G_VECTOR(OFS_PARM1);
494 color = G_FLOAT(OFS_PARM2);
495 count = G_FLOAT(OFS_PARM3);
496 SV_StartParticle (org, dir, color, count);
501 =================
502 PF_ambientsound
504 =================
506 void PF_ambientsound (void)
508 char **check;
509 char *samp;
510 float *pos;
511 float vol, attenuation;
512 int i, soundnum;
514 pos = G_VECTOR (OFS_PARM0);
515 samp = G_STRING(OFS_PARM1);
516 vol = G_FLOAT(OFS_PARM2);
517 attenuation = G_FLOAT(OFS_PARM3);
519 // check to see if samp was properly precached
520 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
521 if (!strcmp(*check,samp))
522 break;
524 if (!*check)
526 Con_Printf ("no precache: %s\n", samp);
527 return;
530 // add an svc_spawnambient command to the level signon packet
532 MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
533 for (i=0 ; i<3 ; i++)
534 MSG_WriteCoord(&sv.signon, pos[i]);
536 MSG_WriteByte (&sv.signon, soundnum);
538 MSG_WriteByte (&sv.signon, vol*255);
539 MSG_WriteByte (&sv.signon, attenuation*64);
544 =================
545 PF_sound
547 Each entity can have eight independant sound sources, like voice,
548 weapon, feet, etc.
550 Channel 0 is an auto-allocate channel, the others override anything
551 allready running on that entity/channel pair.
553 An attenuation of 0 will play full volume everywhere in the level.
554 Larger attenuations will drop off.
556 =================
558 void PF_sound (void)
560 char *sample;
561 int channel;
562 edict_t *entity;
563 int volume;
564 float attenuation;
566 entity = G_EDICT(OFS_PARM0);
567 channel = G_FLOAT(OFS_PARM1);
568 sample = G_STRING(OFS_PARM2);
569 volume = G_FLOAT(OFS_PARM3) * 255;
570 attenuation = G_FLOAT(OFS_PARM4);
572 if (volume < 0 || volume > 255)
573 Sys_Error ("SV_StartSound: volume = %i", volume);
575 if (attenuation < 0 || attenuation > 4)
576 Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
578 if (channel < 0 || channel > 7)
579 Sys_Error ("SV_StartSound: channel = %i", channel);
581 SV_StartSound (entity, channel, sample, volume, attenuation);
585 =================
586 PF_break
588 break()
589 =================
591 void PF_break (void)
593 Con_Printf ("break statement\n");
594 *(int *)-4 = 0; // dump to debugger
595 // PR_RunError ("break statement");
599 =================
600 PF_traceline
602 Used for use tracing and shot targeting
603 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
604 if the tryents flag is set.
606 traceline (vector1, vector2, tryents)
607 =================
609 void PF_traceline (void)
611 float *v1, *v2;
612 trace_t trace;
613 int nomonsters;
614 edict_t *ent;
616 v1 = G_VECTOR(OFS_PARM0);
617 v2 = G_VECTOR(OFS_PARM1);
618 nomonsters = G_FLOAT(OFS_PARM2);
619 ent = G_EDICT(OFS_PARM3);
621 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
623 pr_global_struct->trace_allsolid = trace.allsolid;
624 pr_global_struct->trace_startsolid = trace.startsolid;
625 pr_global_struct->trace_fraction = trace.fraction;
626 pr_global_struct->trace_inwater = trace.inwater;
627 pr_global_struct->trace_inopen = trace.inopen;
628 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
629 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
630 pr_global_struct->trace_plane_dist = trace.plane.dist;
631 if (trace.ent)
632 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
633 else
634 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
638 #ifdef QUAKE2
639 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
641 void PF_TraceToss (void)
643 trace_t trace;
644 edict_t *ent;
645 edict_t *ignore;
647 ent = G_EDICT(OFS_PARM0);
648 ignore = G_EDICT(OFS_PARM1);
650 trace = SV_Trace_Toss (ent, ignore);
652 pr_global_struct->trace_allsolid = trace.allsolid;
653 pr_global_struct->trace_startsolid = trace.startsolid;
654 pr_global_struct->trace_fraction = trace.fraction;
655 pr_global_struct->trace_inwater = trace.inwater;
656 pr_global_struct->trace_inopen = trace.inopen;
657 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
658 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
659 pr_global_struct->trace_plane_dist = trace.plane.dist;
660 if (trace.ent)
661 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
662 else
663 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
665 #endif
669 =================
670 PF_checkpos
672 Returns true if the given entity can move to the given position from it's
673 current position by walking or rolling.
674 FIXME: make work...
675 scalar checkpos (entity, vector)
676 =================
678 void PF_checkpos (void)
682 //============================================================================
684 byte checkpvs[MAX_MAP_LEAFS/8];
686 int PF_newcheckclient (int check)
688 int i;
689 byte *pvs;
690 edict_t *ent;
691 mleaf_t *leaf;
692 vec3_t org;
694 // cycle to the next one
696 if (check < 1)
697 check = 1;
698 if (check > svs.maxclients)
699 check = svs.maxclients;
701 if (check == svs.maxclients)
702 i = 1;
703 else
704 i = check + 1;
706 for ( ; ; i++)
708 if (i == svs.maxclients+1)
709 i = 1;
711 ent = EDICT_NUM(i);
713 if (i == check)
714 break; // didn't find anything else
716 if (ent->free)
717 continue;
718 if (ent->v.health <= 0)
719 continue;
720 if ((int)ent->v.flags & FL_NOTARGET)
721 continue;
723 // anything that is a client, or has a client as an enemy
724 break;
727 // get the PVS for the entity
728 VectorAdd (ent->v.origin, ent->v.view_ofs, org);
729 leaf = Mod_PointInLeaf (org, sv.worldmodel);
730 pvs = Mod_LeafPVS (leaf, sv.worldmodel);
731 memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
733 return i;
737 =================
738 PF_checkclient
740 Returns a client (or object that has a client enemy) that would be a
741 valid target.
743 If there are more than one valid options, they are cycled each frame
745 If (self.origin + self.viewofs) is not in the PVS of the current target,
746 it is not returned at all.
748 name checkclient ()
749 =================
751 #define MAX_CHECK 16
752 int c_invis, c_notvis;
753 void PF_checkclient (void)
755 edict_t *ent, *self;
756 mleaf_t *leaf;
757 int l;
758 vec3_t view;
760 // find a new check if on a new frame
761 if (sv.time - sv.lastchecktime >= 0.1)
763 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
764 sv.lastchecktime = sv.time;
767 // return check if it might be visible
768 ent = EDICT_NUM(sv.lastcheck);
769 if (ent->free || ent->v.health <= 0)
771 RETURN_EDICT(sv.edicts);
772 return;
775 // if current entity can't possibly see the check entity, return 0
776 self = PROG_TO_EDICT(pr_global_struct->self);
777 VectorAdd (self->v.origin, self->v.view_ofs, view);
778 leaf = Mod_PointInLeaf (view, sv.worldmodel);
779 l = (leaf - sv.worldmodel->leafs) - 1;
780 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
782 c_notvis++;
783 RETURN_EDICT(sv.edicts);
784 return;
787 // might be able to see it
788 c_invis++;
789 RETURN_EDICT(ent);
792 //============================================================================
796 =================
797 PF_stuffcmd
799 Sends text over to the client's execution buffer
801 stuffcmd (clientent, value)
802 =================
804 void PF_stuffcmd (void)
806 int entnum;
807 char *str;
808 client_t *old;
810 entnum = G_EDICTNUM(OFS_PARM0);
811 if (entnum < 1 || entnum > svs.maxclients)
812 PR_RunError ("Parm 0 not a client");
813 str = G_STRING(OFS_PARM1);
815 old = host_client;
816 host_client = &svs.clients[entnum-1];
817 Host_ClientCommands ("%s", str);
818 host_client = old;
822 =================
823 PF_localcmd
825 Sends text over to the client's execution buffer
827 localcmd (string)
828 =================
830 void PF_localcmd (void)
832 char *str;
834 str = G_STRING(OFS_PARM0);
835 Cbuf_AddText (str);
839 =================
840 PF_cvar
842 float cvar (string)
843 =================
845 void PF_cvar (void)
847 char *str;
849 str = G_STRING(OFS_PARM0);
851 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
855 =================
856 PF_cvar_set
858 float cvar (string)
859 =================
861 void PF_cvar_set (void)
863 char *var, *val;
865 var = G_STRING(OFS_PARM0);
866 val = G_STRING(OFS_PARM1);
868 Cvar_Set (var, val);
872 =================
873 PF_findradius
875 Returns a chain of entities that have origins within a spherical area
877 findradius (origin, radius)
878 =================
880 void PF_findradius (void)
882 edict_t *ent, *chain;
883 float rad;
884 float *org;
885 vec3_t eorg;
886 int i, j;
888 chain = (edict_t *)sv.edicts;
890 org = G_VECTOR(OFS_PARM0);
891 rad = G_FLOAT(OFS_PARM1);
893 ent = NEXT_EDICT(sv.edicts);
894 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
896 if (ent->free)
897 continue;
898 if (ent->v.solid == SOLID_NOT)
899 continue;
900 for (j=0 ; j<3 ; j++)
901 eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);
902 if (Length(eorg) > rad)
903 continue;
905 ent->v.chain = EDICT_TO_PROG(chain);
906 chain = ent;
909 RETURN_EDICT(chain);
914 =========
915 PF_dprint
916 =========
918 void PF_dprint (void)
920 Con_DPrintf ("%s",PF_VarString(0));
923 char pr_string_temp[128];
925 void PF_ftos (void)
927 float v;
928 v = G_FLOAT(OFS_PARM0);
930 if (v == (int)v)
931 sprintf (pr_string_temp, "%d",(int)v);
932 else
933 sprintf (pr_string_temp, "%5.1f",v);
934 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
937 void PF_fabs (void)
939 float v;
940 v = G_FLOAT(OFS_PARM0);
941 G_FLOAT(OFS_RETURN) = fabs(v);
944 void PF_vtos (void)
946 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]);
947 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
950 #ifdef QUAKE2
951 void PF_etos (void)
953 sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0));
954 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
956 #endif
958 void PF_Spawn (void)
960 edict_t *ed;
961 ed = ED_Alloc();
962 RETURN_EDICT(ed);
965 void PF_Remove (void)
967 edict_t *ed;
969 ed = G_EDICT(OFS_PARM0);
970 ED_Free (ed);
974 // entity (entity start, .string field, string match) find = #5;
975 void PF_Find (void)
976 #ifdef QUAKE2
978 int e;
979 int f;
980 char *s, *t;
981 edict_t *ed;
982 edict_t *first;
983 edict_t *second;
984 edict_t *last;
986 first = second = last = (edict_t *)sv.edicts;
987 e = G_EDICTNUM(OFS_PARM0);
988 f = G_INT(OFS_PARM1);
989 s = G_STRING(OFS_PARM2);
990 if (!s)
991 PR_RunError ("PF_Find: bad search string");
993 for (e++ ; e < sv.num_edicts ; e++)
995 ed = EDICT_NUM(e);
996 if (ed->free)
997 continue;
998 t = E_STRING(ed,f);
999 if (!t)
1000 continue;
1001 if (!strcmp(t,s))
1003 if (first == (edict_t *)sv.edicts)
1004 first = ed;
1005 else if (second == (edict_t *)sv.edicts)
1006 second = ed;
1007 ed->v.chain = EDICT_TO_PROG(last);
1008 last = ed;
1012 if (first != last)
1014 if (last != second)
1015 first->v.chain = last->v.chain;
1016 else
1017 first->v.chain = EDICT_TO_PROG(last);
1018 last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts);
1019 if (second && second != last)
1020 second->v.chain = EDICT_TO_PROG(last);
1022 RETURN_EDICT(first);
1024 #else
1026 int e;
1027 int f;
1028 char *s, *t;
1029 edict_t *ed;
1031 e = G_EDICTNUM(OFS_PARM0);
1032 f = G_INT(OFS_PARM1);
1033 s = G_STRING(OFS_PARM2);
1034 if (!s)
1035 PR_RunError ("PF_Find: bad search string");
1037 for (e++ ; e < sv.num_edicts ; e++)
1039 ed = EDICT_NUM(e);
1040 if (ed->free)
1041 continue;
1042 t = E_STRING(ed,f);
1043 if (!t)
1044 continue;
1045 if (!strcmp(t,s))
1047 RETURN_EDICT(ed);
1048 return;
1052 RETURN_EDICT(sv.edicts);
1054 #endif
1056 void PR_CheckEmptyString (char *s)
1058 if (s[0] <= ' ')
1059 PR_RunError ("Bad string");
1062 void PF_precache_file (void)
1063 { // precache_file is only used to copy files with qcc, it does nothing
1064 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1067 void PF_precache_sound (void)
1069 char *s;
1070 int i;
1072 if (sv.state != ss_loading)
1073 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1075 s = G_STRING(OFS_PARM0);
1076 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1077 PR_CheckEmptyString (s);
1079 for (i=0 ; i<MAX_SOUNDS ; i++)
1081 if (!sv.sound_precache[i])
1083 sv.sound_precache[i] = s;
1084 return;
1086 if (!strcmp(sv.sound_precache[i], s))
1087 return;
1089 PR_RunError ("PF_precache_sound: overflow");
1092 void PF_precache_model (void)
1094 char *s;
1095 int i;
1097 if (sv.state != ss_loading)
1098 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1100 s = G_STRING(OFS_PARM0);
1101 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1102 PR_CheckEmptyString (s);
1104 for (i=0 ; i<MAX_MODELS ; i++)
1106 if (!sv.model_precache[i])
1108 sv.model_precache[i] = s;
1109 sv.models[i] = Mod_ForName (s, true);
1110 return;
1112 if (!strcmp(sv.model_precache[i], s))
1113 return;
1115 PR_RunError ("PF_precache_model: overflow");
1119 void PF_coredump (void)
1121 ED_PrintEdicts ();
1124 void PF_traceon (void)
1126 pr_trace = true;
1129 void PF_traceoff (void)
1131 pr_trace = false;
1134 void PF_eprint (void)
1136 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1140 ===============
1141 PF_walkmove
1143 float(float yaw, float dist) walkmove
1144 ===============
1146 void PF_walkmove (void)
1148 edict_t *ent;
1149 float yaw, dist;
1150 vec3_t move;
1151 dfunction_t *oldf;
1152 int oldself;
1154 ent = PROG_TO_EDICT(pr_global_struct->self);
1155 yaw = G_FLOAT(OFS_PARM0);
1156 dist = G_FLOAT(OFS_PARM1);
1158 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1160 G_FLOAT(OFS_RETURN) = 0;
1161 return;
1164 yaw = yaw*M_PI*2 / 360;
1166 move[0] = cos(yaw)*dist;
1167 move[1] = sin(yaw)*dist;
1168 move[2] = 0;
1170 // save program state, because SV_movestep may call other progs
1171 oldf = pr_xfunction;
1172 oldself = pr_global_struct->self;
1174 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1177 // restore program state
1178 pr_xfunction = oldf;
1179 pr_global_struct->self = oldself;
1183 ===============
1184 PF_droptofloor
1186 void() droptofloor
1187 ===============
1189 void PF_droptofloor (void)
1191 edict_t *ent;
1192 vec3_t end;
1193 trace_t trace;
1195 ent = PROG_TO_EDICT(pr_global_struct->self);
1197 VectorCopy (ent->v.origin, end);
1198 end[2] -= 256;
1200 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1202 if (trace.fraction == 1 || trace.allsolid)
1203 G_FLOAT(OFS_RETURN) = 0;
1204 else
1206 VectorCopy (trace.endpos, ent->v.origin);
1207 SV_LinkEdict (ent, false);
1208 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1209 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1210 G_FLOAT(OFS_RETURN) = 1;
1215 ===============
1216 PF_lightstyle
1218 void(float style, string value) lightstyle
1219 ===============
1221 void PF_lightstyle (void)
1223 int style;
1224 char *val;
1225 client_t *client;
1226 int j;
1228 style = G_FLOAT(OFS_PARM0);
1229 val = G_STRING(OFS_PARM1);
1231 // change the string in sv
1232 sv.lightstyles[style] = val;
1234 // send message to all clients on this server
1235 if (sv.state != ss_active)
1236 return;
1238 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1239 if (client->active || client->spawned)
1241 MSG_WriteChar (&client->message, svc_lightstyle);
1242 MSG_WriteChar (&client->message,style);
1243 MSG_WriteString (&client->message, val);
1247 void PF_rint (void)
1249 float f;
1250 f = G_FLOAT(OFS_PARM0);
1251 if (f > 0)
1252 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1253 else
1254 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1256 void PF_floor (void)
1258 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1260 void PF_ceil (void)
1262 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1267 =============
1268 PF_checkbottom
1269 =============
1271 void PF_checkbottom (void)
1273 edict_t *ent;
1275 ent = G_EDICT(OFS_PARM0);
1277 G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
1281 =============
1282 PF_pointcontents
1283 =============
1285 void PF_pointcontents (void)
1287 float *v;
1289 v = G_VECTOR(OFS_PARM0);
1291 G_FLOAT(OFS_RETURN) = SV_PointContents (v);
1295 =============
1296 PF_nextent
1298 entity nextent(entity)
1299 =============
1301 void PF_nextent (void)
1303 int i;
1304 edict_t *ent;
1306 i = G_EDICTNUM(OFS_PARM0);
1307 while (1)
1309 i++;
1310 if (i == sv.num_edicts)
1312 RETURN_EDICT(sv.edicts);
1313 return;
1315 ent = EDICT_NUM(i);
1316 if (!ent->free)
1318 RETURN_EDICT(ent);
1319 return;
1325 =============
1326 PF_aim
1328 Pick a vector for the player to shoot along
1329 vector aim(entity, missilespeed)
1330 =============
1332 cvar_t sv_aim = {"sv_aim", "0.93"};
1333 void PF_aim (void)
1335 edict_t *ent, *check, *bestent;
1336 vec3_t start, dir, end, bestdir;
1337 int i, j;
1338 trace_t tr;
1339 float dist, bestdist;
1341 ent = G_EDICT(OFS_PARM0);
1343 VectorCopy (ent->v.origin, start);
1344 start[2] += 20;
1346 // try sending a trace straight
1347 VectorCopy (pr_global_struct->v_forward, dir);
1348 VectorMA (start, 2048, dir, end);
1349 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1350 if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1351 && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1353 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1354 return;
1358 // try all possible entities
1359 VectorCopy (dir, bestdir);
1360 bestdist = sv_aim.value;
1361 bestent = NULL;
1363 check = NEXT_EDICT(sv.edicts);
1364 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1366 if (check->v.takedamage != DAMAGE_AIM)
1367 continue;
1368 if (check == ent)
1369 continue;
1370 if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1371 continue; // don't aim at teammate
1372 for (j=0 ; j<3 ; j++)
1373 end[j] = check->v.origin[j]
1374 + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1375 VectorSubtract (end, start, dir);
1376 VectorNormalize (dir);
1377 dist = DotProduct (dir, pr_global_struct->v_forward);
1378 if (dist < bestdist)
1379 continue; // to far to turn
1380 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1381 if (tr.ent == check)
1382 { // can shoot at this one
1383 bestdist = dist;
1384 bestent = check;
1388 if (bestent)
1390 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1391 dist = DotProduct (dir, pr_global_struct->v_forward);
1392 VectorScale (pr_global_struct->v_forward, dist, end);
1393 end[2] = dir[2];
1394 VectorNormalize (end);
1395 VectorCopy (end, G_VECTOR(OFS_RETURN));
1397 else
1399 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1404 ==============
1405 PF_changeyaw
1407 This was a major timewaster in progs, so it was converted to C
1408 ==============
1410 void PF_changeyaw (void)
1412 edict_t *ent;
1413 float ideal, current, move, speed;
1415 ent = PROG_TO_EDICT(pr_global_struct->self);
1416 current = anglemod( ent->v.angles[1] );
1417 ideal = ent->v.ideal_yaw;
1418 speed = ent->v.yaw_speed;
1420 if (current == ideal)
1421 return;
1422 move = ideal - current;
1423 if (ideal > current)
1425 if (move >= 180)
1426 move = move - 360;
1428 else
1430 if (move <= -180)
1431 move = move + 360;
1433 if (move > 0)
1435 if (move > speed)
1436 move = speed;
1438 else
1440 if (move < -speed)
1441 move = -speed;
1444 ent->v.angles[1] = anglemod (current + move);
1447 #ifdef QUAKE2
1449 ==============
1450 PF_changepitch
1451 ==============
1453 void PF_changepitch (void)
1455 edict_t *ent;
1456 float ideal, current, move, speed;
1458 ent = G_EDICT(OFS_PARM0);
1459 current = anglemod( ent->v.angles[0] );
1460 ideal = ent->v.idealpitch;
1461 speed = ent->v.pitch_speed;
1463 if (current == ideal)
1464 return;
1465 move = ideal - current;
1466 if (ideal > current)
1468 if (move >= 180)
1469 move = move - 360;
1471 else
1473 if (move <= -180)
1474 move = move + 360;
1476 if (move > 0)
1478 if (move > speed)
1479 move = speed;
1481 else
1483 if (move < -speed)
1484 move = -speed;
1487 ent->v.angles[0] = anglemod (current + move);
1489 #endif
1492 ===============================================================================
1494 MESSAGE WRITING
1496 ===============================================================================
1499 #define MSG_BROADCAST 0 // unreliable to all
1500 #define MSG_ONE 1 // reliable to one (msg_entity)
1501 #define MSG_ALL 2 // reliable to all
1502 #define MSG_INIT 3 // write to the init string
1504 sizebuf_t *WriteDest (void)
1506 int entnum;
1507 int dest;
1508 edict_t *ent;
1510 dest = G_FLOAT(OFS_PARM0);
1511 switch (dest)
1513 case MSG_BROADCAST:
1514 return &sv.datagram;
1516 case MSG_ONE:
1517 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1518 entnum = NUM_FOR_EDICT(ent);
1519 if (entnum < 1 || entnum > svs.maxclients)
1520 PR_RunError ("WriteDest: not a client");
1521 return &svs.clients[entnum-1].message;
1523 case MSG_ALL:
1524 return &sv.reliable_datagram;
1526 case MSG_INIT:
1527 return &sv.signon;
1529 default:
1530 PR_RunError ("WriteDest: bad destination");
1531 break;
1534 return NULL;
1537 void PF_WriteByte (void)
1539 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1542 void PF_WriteChar (void)
1544 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1547 void PF_WriteShort (void)
1549 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1552 void PF_WriteLong (void)
1554 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1557 void PF_WriteAngle (void)
1559 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1562 void PF_WriteCoord (void)
1564 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1567 void PF_WriteString (void)
1569 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1573 void PF_WriteEntity (void)
1575 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1578 //=============================================================================
1580 int SV_ModelIndex (char *name);
1582 void PF_makestatic (void)
1584 edict_t *ent;
1585 int i;
1587 ent = G_EDICT(OFS_PARM0);
1589 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1591 MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
1593 MSG_WriteByte (&sv.signon, ent->v.frame);
1594 MSG_WriteByte (&sv.signon, ent->v.colormap);
1595 MSG_WriteByte (&sv.signon, ent->v.skin);
1596 for (i=0 ; i<3 ; i++)
1598 MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1599 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1602 // throw the entity away now
1603 ED_Free (ent);
1606 //=============================================================================
1609 ==============
1610 PF_setspawnparms
1611 ==============
1613 void PF_setspawnparms (void)
1615 edict_t *ent;
1616 int i;
1617 client_t *client;
1619 ent = G_EDICT(OFS_PARM0);
1620 i = NUM_FOR_EDICT(ent);
1621 if (i < 1 || i > svs.maxclients)
1622 PR_RunError ("Entity is not a client");
1624 // copy spawn parms out of the client_t
1625 client = svs.clients + (i-1);
1627 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1628 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1632 ==============
1633 PF_changelevel
1634 ==============
1636 void PF_changelevel (void)
1638 #ifdef QUAKE2
1639 char *s1, *s2;
1641 if (svs.changelevel_issued)
1642 return;
1643 svs.changelevel_issued = true;
1645 s1 = G_STRING(OFS_PARM0);
1646 s2 = G_STRING(OFS_PARM1);
1648 if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE))
1649 Cbuf_AddText (va("changelevel %s %s\n",s1, s2));
1650 else
1651 Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2));
1652 #else
1653 char *s;
1655 // make sure we don't issue two changelevels
1656 if (svs.changelevel_issued)
1657 return;
1658 svs.changelevel_issued = true;
1660 s = G_STRING(OFS_PARM0);
1661 Cbuf_AddText (va("changelevel %s\n",s));
1662 #endif
1666 #ifdef QUAKE2
1668 #define CONTENT_WATER -3
1669 #define CONTENT_SLIME -4
1670 #define CONTENT_LAVA -5
1672 #define FL_IMMUNE_WATER 131072
1673 #define FL_IMMUNE_SLIME 262144
1674 #define FL_IMMUNE_LAVA 524288
1676 #define CHAN_VOICE 2
1677 #define CHAN_BODY 4
1679 #define ATTN_NORM 1
1681 void PF_WaterMove (void)
1683 edict_t *self;
1684 int flags;
1685 int waterlevel;
1686 int watertype;
1687 float drownlevel;
1688 float damage = 0.0;
1690 self = PROG_TO_EDICT(pr_global_struct->self);
1692 if (self->v.movetype == MOVETYPE_NOCLIP)
1694 self->v.air_finished = sv.time + 12;
1695 G_FLOAT(OFS_RETURN) = damage;
1696 return;
1699 if (self->v.health < 0)
1701 G_FLOAT(OFS_RETURN) = damage;
1702 return;
1705 if (self->v.deadflag == DEAD_NO)
1706 drownlevel = 3;
1707 else
1708 drownlevel = 1;
1710 flags = (int)self->v.flags;
1711 waterlevel = (int)self->v.waterlevel;
1712 watertype = (int)self->v.watertype;
1714 if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
1715 if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
1717 if (self->v.air_finished < sv.time)
1718 if (self->v.pain_finished < sv.time)
1720 self->v.dmg = self->v.dmg + 2;
1721 if (self->v.dmg > 15)
1722 self->v.dmg = 10;
1723 // T_Damage (self, world, world, self.dmg, 0, FALSE);
1724 damage = self->v.dmg;
1725 self->v.pain_finished = sv.time + 1.0;
1728 else
1730 if (self->v.air_finished < sv.time)
1731 // sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
1732 SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM);
1733 else if (self->v.air_finished < sv.time + 9)
1734 // sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
1735 SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM);
1736 self->v.air_finished = sv.time + 12.0;
1737 self->v.dmg = 2;
1740 if (!waterlevel)
1742 if (flags & FL_INWATER)
1744 // play leave water sound
1745 // sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
1746 SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM);
1747 self->v.flags = (float)(flags &~FL_INWATER);
1749 self->v.air_finished = sv.time + 12.0;
1750 G_FLOAT(OFS_RETURN) = damage;
1751 return;
1754 if (watertype == CONTENT_LAVA)
1755 { // do damage
1756 if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE)))
1757 if (self->v.dmgtime < sv.time)
1759 if (self->v.radsuit_finished < sv.time)
1760 self->v.dmgtime = sv.time + 0.2;
1761 else
1762 self->v.dmgtime = sv.time + 1.0;
1763 // T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE);
1764 damage = (float)(10*waterlevel);
1767 else if (watertype == CONTENT_SLIME)
1768 { // do damage
1769 if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE)))
1770 if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
1772 self->v.dmgtime = sv.time + 1.0;
1773 // T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE);
1774 damage = (float)(4*waterlevel);
1778 if ( !(flags & FL_INWATER) )
1781 // player enter water sound
1782 if (watertype == CONTENT_LAVA)
1783 // sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
1784 SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM);
1785 if (watertype == CONTENT_WATER)
1786 // sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
1787 SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM);
1788 if (watertype == CONTENT_SLIME)
1789 // sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
1790 SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM);
1792 self->v.flags = (float)(flags | FL_INWATER);
1793 self->v.dmgtime = 0;
1796 if (! (flags & FL_WATERJUMP) )
1798 // self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
1799 VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
1802 G_FLOAT(OFS_RETURN) = damage;
1806 void PF_sin (void)
1808 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1811 void PF_cos (void)
1813 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1816 void PF_sqrt (void)
1818 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1820 #endif
1822 void PF_Fixme (void)
1824 PR_RunError ("unimplemented bulitin");
1829 builtin_t pr_builtin[] =
1831 PF_Fixme,
1832 PF_makevectors, // void(entity e) makevectors = #1;
1833 PF_setorigin, // void(entity e, vector o) setorigin = #2;
1834 PF_setmodel, // void(entity e, string m) setmodel = #3;
1835 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
1836 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
1837 PF_break, // void() break = #6;
1838 PF_random, // float() random = #7;
1839 PF_sound, // void(entity e, float chan, string samp) sound = #8;
1840 PF_normalize, // vector(vector v) normalize = #9;
1841 PF_error, // void(string e) error = #10;
1842 PF_objerror, // void(string e) objerror = #11;
1843 PF_vlen, // float(vector v) vlen = #12;
1844 PF_vectoyaw, // float(vector v) vectoyaw = #13;
1845 PF_Spawn, // entity() spawn = #14;
1846 PF_Remove, // void(entity e) remove = #15;
1847 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
1848 PF_checkclient, // entity() clientlist = #17;
1849 PF_Find, // entity(entity start, .string fld, string match) find = #18;
1850 PF_precache_sound, // void(string s) precache_sound = #19;
1851 PF_precache_model, // void(string s) precache_model = #20;
1852 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
1853 PF_findradius, // entity(vector org, float rad) findradius = #22;
1854 PF_bprint, // void(string s) bprint = #23;
1855 PF_sprint, // void(entity client, string s) sprint = #24;
1856 PF_dprint, // void(string s) dprint = #25;
1857 PF_ftos, // void(string s) ftos = #26;
1858 PF_vtos, // void(string s) vtos = #27;
1859 PF_coredump,
1860 PF_traceon,
1861 PF_traceoff,
1862 PF_eprint, // void(entity e) debug print an entire entity
1863 PF_walkmove, // float(float yaw, float dist) walkmove
1864 PF_Fixme, // float(float yaw, float dist) walkmove
1865 PF_droptofloor,
1866 PF_lightstyle,
1867 PF_rint,
1868 PF_floor,
1869 PF_ceil,
1870 PF_Fixme,
1871 PF_checkbottom,
1872 PF_pointcontents,
1873 PF_Fixme,
1874 PF_fabs,
1875 PF_aim,
1876 PF_cvar,
1877 PF_localcmd,
1878 PF_nextent,
1879 PF_particle,
1880 PF_changeyaw,
1881 PF_Fixme,
1882 PF_vectoangles,
1884 PF_WriteByte,
1885 PF_WriteChar,
1886 PF_WriteShort,
1887 PF_WriteLong,
1888 PF_WriteCoord,
1889 PF_WriteAngle,
1890 PF_WriteString,
1891 PF_WriteEntity,
1893 #ifdef QUAKE2
1894 PF_sin,
1895 PF_cos,
1896 PF_sqrt,
1897 PF_changepitch,
1898 PF_TraceToss,
1899 PF_etos,
1900 PF_WaterMove,
1901 #else
1902 PF_Fixme,
1903 PF_Fixme,
1904 PF_Fixme,
1905 PF_Fixme,
1906 PF_Fixme,
1907 PF_Fixme,
1908 PF_Fixme,
1909 #endif
1911 SV_MoveToGoal,
1912 PF_precache_file,
1913 PF_makestatic,
1915 PF_changelevel,
1916 PF_Fixme,
1918 PF_cvar_set,
1919 PF_centerprint,
1921 PF_ambientsound,
1923 PF_precache_model,
1924 PF_precache_sound, // precache_sound2 is different only for qcc
1925 PF_precache_file,
1927 PF_setspawnparms
1930 builtin_t *pr_builtins = pr_builtin;
1931 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);