git-svn-id: http://bladebattles.com/kurok/SVN@11 20cd92bb-ff49-0410-b73e-96a06e42c3b9
[kurok.git] / pr_cmds.c
blob58c6f8111bae76973ca9a443d40e3a18053878cf
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] = cosf(a);
161 xvector[1] = sinf(a);
162 yvector[0] = -sinf(a);
163 yvector[1] = cosf(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 = sqrtf(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 = sqrtf(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) (atan2f(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) (atan2f(value1[1], value1[0]) * 180 / M_PI);
447 if (yaw < 0)
448 yaw += 360;
450 forward = sqrtf (value1[0]*value1[0] + value1[1]*value1[1]);
451 pitch = (int) (atan2f(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 sprintf (pr_string_temp, "%1f",v);
935 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
938 void PF_fabs (void)
940 float v;
941 v = G_FLOAT(OFS_PARM0);
942 G_FLOAT(OFS_RETURN) = fabsf(v);
945 void PF_vtos (void)
947 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]);
948 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
951 #ifdef QUAKE2
952 void PF_etos (void)
954 sprintf (pr_string_temp, "entity %i", G_EDICTNUM(OFS_PARM0));
955 G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
957 #endif
959 void PF_Spawn (void)
961 edict_t *ed;
962 ed = ED_Alloc();
963 RETURN_EDICT(ed);
966 void PF_Remove (void)
968 edict_t *ed;
970 ed = G_EDICT(OFS_PARM0);
971 ED_Free (ed);
975 // entity (entity start, .string field, string match) find = #5;
976 void PF_Find (void)
977 #ifdef QUAKE2
979 int e;
980 int f;
981 char *s, *t;
982 edict_t *ed;
983 edict_t *first;
984 edict_t *second;
985 edict_t *last;
987 first = second = last = (edict_t *)sv.edicts;
988 e = G_EDICTNUM(OFS_PARM0);
989 f = G_INT(OFS_PARM1);
990 s = G_STRING(OFS_PARM2);
991 if (!s)
992 PR_RunError ("PF_Find: bad search string");
994 for (e++ ; e < sv.num_edicts ; e++)
996 ed = EDICT_NUM(e);
997 if (ed->free)
998 continue;
999 t = E_STRING(ed,f);
1000 if (!t)
1001 continue;
1002 if (!strcmp(t,s))
1004 if (first == (edict_t *)sv.edicts)
1005 first = ed;
1006 else if (second == (edict_t *)sv.edicts)
1007 second = ed;
1008 ed->v.chain = EDICT_TO_PROG(last);
1009 last = ed;
1013 if (first != last)
1015 if (last != second)
1016 first->v.chain = last->v.chain;
1017 else
1018 first->v.chain = EDICT_TO_PROG(last);
1019 last->v.chain = EDICT_TO_PROG((edict_t *)sv.edicts);
1020 if (second && second != last)
1021 second->v.chain = EDICT_TO_PROG(last);
1023 RETURN_EDICT(first);
1025 #else
1027 int e;
1028 int f;
1029 char *s, *t;
1030 edict_t *ed;
1032 e = G_EDICTNUM(OFS_PARM0);
1033 f = G_INT(OFS_PARM1);
1034 s = G_STRING(OFS_PARM2);
1035 if (!s)
1036 PR_RunError ("PF_Find: bad search string");
1038 for (e++ ; e < sv.num_edicts ; e++)
1040 ed = EDICT_NUM(e);
1041 if (ed->free)
1042 continue;
1043 t = E_STRING(ed,f);
1044 if (!t)
1045 continue;
1046 if (!strcmp(t,s))
1048 RETURN_EDICT(ed);
1049 return;
1053 RETURN_EDICT(sv.edicts);
1055 #endif
1057 void PR_CheckEmptyString (char *s)
1059 if (s[0] <= ' ')
1060 PR_RunError ("Bad string");
1063 void PF_precache_file (void)
1064 { // precache_file is only used to copy files with qcc, it does nothing
1065 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1068 void PF_precache_sound (void)
1070 char *s;
1071 int i;
1073 if (sv.state != ss_loading)
1074 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1076 s = G_STRING(OFS_PARM0);
1077 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1078 PR_CheckEmptyString (s);
1080 for (i=0 ; i<MAX_SOUNDS ; i++)
1082 if (!sv.sound_precache[i])
1084 sv.sound_precache[i] = s;
1085 return;
1087 if (!strcmp(sv.sound_precache[i], s))
1088 return;
1090 PR_RunError ("PF_precache_sound: overflow");
1093 void PF_precache_model (void)
1095 char *s;
1096 int i;
1098 if (sv.state != ss_loading)
1099 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1101 s = G_STRING(OFS_PARM0);
1102 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1103 PR_CheckEmptyString (s);
1105 for (i=0 ; i<MAX_MODELS ; i++)
1107 if (!sv.model_precache[i])
1109 sv.model_precache[i] = s;
1110 sv.models[i] = Mod_ForName (s, true);
1111 return;
1113 if (!strcmp(sv.model_precache[i], s))
1114 return;
1116 PR_RunError ("PF_precache_model: overflow");
1120 void PF_coredump (void)
1122 ED_PrintEdicts ();
1125 void PF_traceon (void)
1127 pr_trace = true;
1130 void PF_traceoff (void)
1132 pr_trace = false;
1135 void PF_eprint (void)
1137 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1141 ===============
1142 PF_walkmove
1144 float(float yaw, float dist) walkmove
1145 ===============
1147 void PF_walkmove (void)
1149 edict_t *ent;
1150 float yaw, dist;
1151 vec3_t move;
1152 dfunction_t *oldf;
1153 int oldself;
1155 ent = PROG_TO_EDICT(pr_global_struct->self);
1156 yaw = G_FLOAT(OFS_PARM0);
1157 dist = G_FLOAT(OFS_PARM1);
1159 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1161 G_FLOAT(OFS_RETURN) = 0;
1162 return;
1165 yaw = yaw*M_PI*2 / 360;
1167 move[0] = cosf(yaw)*dist;
1168 move[1] = sinf(yaw)*dist;
1169 move[2] = 0;
1171 // save program state, because SV_movestep may call other progs
1172 oldf = pr_xfunction;
1173 oldself = pr_global_struct->self;
1175 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1178 // restore program state
1179 pr_xfunction = oldf;
1180 pr_global_struct->self = oldself;
1184 ===============
1185 PF_droptofloor
1187 void() droptofloor
1188 ===============
1190 void PF_droptofloor (void)
1192 edict_t *ent;
1193 vec3_t end;
1194 trace_t trace;
1196 ent = PROG_TO_EDICT(pr_global_struct->self);
1198 VectorCopy (ent->v.origin, end);
1199 end[2] -= 256;
1201 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
1203 if (trace.fraction == 1 || trace.allsolid)
1204 G_FLOAT(OFS_RETURN) = 0;
1205 else
1207 VectorCopy (trace.endpos, ent->v.origin);
1208 SV_LinkEdict (ent, false);
1209 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1210 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1211 G_FLOAT(OFS_RETURN) = 1;
1216 ===============
1217 PF_lightstyle
1219 void(float style, string value) lightstyle
1220 ===============
1222 void PF_lightstyle (void)
1224 int style;
1225 char *val;
1226 client_t *client;
1227 int j;
1229 style = G_FLOAT(OFS_PARM0);
1230 val = G_STRING(OFS_PARM1);
1232 // change the string in sv
1233 sv.lightstyles[style] = val;
1235 // send message to all clients on this server
1236 if (sv.state != ss_active)
1237 return;
1239 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1240 if (client->active || client->spawned)
1242 MSG_WriteChar (&client->message, svc_lightstyle);
1243 MSG_WriteChar (&client->message,style);
1244 MSG_WriteString (&client->message, val);
1248 void PF_rint (void)
1250 float f;
1251 f = G_FLOAT(OFS_PARM0);
1252 if (f > 0)
1253 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1254 else
1255 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1257 void PF_floor (void)
1259 G_FLOAT(OFS_RETURN) = floorf(G_FLOAT(OFS_PARM0));
1261 void PF_ceil (void)
1263 G_FLOAT(OFS_RETURN) = ceilf(G_FLOAT(OFS_PARM0));
1268 =============
1269 PF_checkbottom
1270 =============
1272 void PF_checkbottom (void)
1274 edict_t *ent;
1276 ent = G_EDICT(OFS_PARM0);
1278 G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
1282 =============
1283 PF_pointcontents
1284 =============
1286 void PF_pointcontents (void)
1288 float *v;
1290 v = G_VECTOR(OFS_PARM0);
1292 G_FLOAT(OFS_RETURN) = SV_PointContents (v);
1296 =============
1297 PF_nextent
1299 entity nextent(entity)
1300 =============
1302 void PF_nextent (void)
1304 int i;
1305 edict_t *ent;
1307 i = G_EDICTNUM(OFS_PARM0);
1308 while (1)
1310 i++;
1311 if (i == sv.num_edicts)
1313 RETURN_EDICT(sv.edicts);
1314 return;
1316 ent = EDICT_NUM(i);
1317 if (!ent->free)
1319 RETURN_EDICT(ent);
1320 return;
1326 =============
1327 PF_aim
1329 Pick a vector for the player to shoot along
1330 vector aim(entity, missilespeed)
1331 =============
1333 cvar_t sv_aim = {"sv_aim", "0.99"};
1334 void PF_aim (void)
1336 edict_t *ent, *check, *bestent;
1337 vec3_t start, dir, end, bestdir;
1338 int i, j;
1339 trace_t tr;
1340 float dist, bestdist;
1341 float speed;
1343 ent = G_EDICT(OFS_PARM0);
1344 speed = G_FLOAT(OFS_PARM1);
1346 VectorCopy (ent->v.origin, start);
1347 start[2] += 20;
1349 // try sending a trace straight
1350 VectorCopy (pr_global_struct->v_forward, dir);
1351 VectorMA (start, 2048, dir, end);
1352 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1353 if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
1354 && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
1356 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1357 return;
1361 // try all possible entities
1362 VectorCopy (dir, bestdir);
1363 if (cl_autoaim.value)
1364 bestdist = sv_aim.value;
1365 else
1366 bestdist = 1;
1367 bestent = NULL;
1369 check = NEXT_EDICT(sv.edicts);
1370 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1372 if (check->v.takedamage != DAMAGE_AIM)
1373 continue;
1374 if (check == ent)
1375 continue;
1376 if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
1377 continue; // don't aim at teammate
1378 for (j=0 ; j<3 ; j++)
1379 end[j] = check->v.origin[j]
1380 + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1381 VectorSubtract (end, start, dir);
1382 VectorNormalize (dir);
1383 dist = DotProduct (dir, pr_global_struct->v_forward);
1384 if (dist < bestdist)
1385 continue; // to far to turn
1386 tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
1387 if (tr.ent == check)
1388 { // can shoot at this one
1389 bestdist = dist;
1390 bestent = check;
1394 if (bestent)
1396 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1397 // dist = DotProduct (dir, pr_global_struct->v_forward);
1398 // VectorScale (pr_global_struct->v_forward, dist, end);
1399 end[0] = dir[0];
1400 end[1] = dir[1];
1401 end[2] = dir[2];
1402 VectorNormalize (end);
1403 VectorCopy (end, G_VECTOR(OFS_RETURN));
1405 else
1407 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1412 ==============
1413 PF_changeyaw
1415 This was a major timewaster in progs, so it was converted to C
1416 ==============
1418 void PF_changeyaw (void)
1420 edict_t *ent;
1421 float ideal, current, move, speed;
1423 ent = PROG_TO_EDICT(pr_global_struct->self);
1424 current = anglemod( ent->v.angles[1] );
1425 ideal = ent->v.ideal_yaw;
1426 speed = ent->v.yaw_speed;
1428 if (current == ideal)
1429 return;
1430 move = ideal - current;
1431 if (ideal > current)
1433 if (move >= 180)
1434 move = move - 360;
1436 else
1438 if (move <= -180)
1439 move = move + 360;
1441 if (move > 0)
1443 if (move > speed)
1444 move = speed;
1446 else
1448 if (move < -speed)
1449 move = -speed;
1452 ent->v.angles[1] = anglemod (current + move);
1455 #ifdef QUAKE2
1457 ==============
1458 PF_changepitch
1459 ==============
1461 void PF_changepitch (void)
1463 edict_t *ent;
1464 float ideal, current, move, speed;
1466 ent = G_EDICT(OFS_PARM0);
1467 current = anglemod( ent->v.angles[0] );
1468 ideal = ent->v.idealpitch;
1469 speed = ent->v.pitch_speed;
1471 if (current == ideal)
1472 return;
1473 move = ideal - current;
1474 if (ideal > current)
1476 if (move >= 180)
1477 move = move - 360;
1479 else
1481 if (move <= -180)
1482 move = move + 360;
1484 if (move > 0)
1486 if (move > speed)
1487 move = speed;
1489 else
1491 if (move < -speed)
1492 move = -speed;
1495 ent->v.angles[0] = anglemod (current + move);
1497 #endif
1500 ===============================================================================
1502 MESSAGE WRITING
1504 ===============================================================================
1507 #define MSG_BROADCAST 0 // unreliable to all
1508 #define MSG_ONE 1 // reliable to one (msg_entity)
1509 #define MSG_ALL 2 // reliable to all
1510 #define MSG_INIT 3 // write to the init string
1512 sizebuf_t *WriteDest (void)
1514 int entnum;
1515 int dest;
1516 edict_t *ent;
1518 dest = G_FLOAT(OFS_PARM0);
1519 switch (dest)
1521 case MSG_BROADCAST:
1522 return &sv.datagram;
1524 case MSG_ONE:
1525 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1526 entnum = NUM_FOR_EDICT(ent);
1527 if (entnum < 1 || entnum > svs.maxclients)
1528 PR_RunError ("WriteDest: not a client");
1529 return &svs.clients[entnum-1].message;
1531 case MSG_ALL:
1532 return &sv.reliable_datagram;
1534 case MSG_INIT:
1535 return &sv.signon;
1537 default:
1538 PR_RunError ("WriteDest: bad destination");
1539 break;
1542 return NULL;
1545 void PF_WriteByte (void)
1547 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1550 void PF_WriteChar (void)
1552 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1555 void PF_WriteShort (void)
1557 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1560 void PF_WriteLong (void)
1562 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1565 void PF_WriteAngle (void)
1567 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1570 void PF_WriteCoord (void)
1572 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1575 void PF_WriteString (void)
1577 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1581 void PF_WriteEntity (void)
1583 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1586 //=============================================================================
1588 int SV_ModelIndex (char *name);
1590 void PF_makestatic (void)
1592 edict_t *ent;
1593 int i;
1595 ent = G_EDICT(OFS_PARM0);
1597 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1599 MSG_WriteByte (&sv.signon, SV_ModelIndex(pr_strings + ent->v.model));
1601 MSG_WriteByte (&sv.signon, ent->v.frame);
1602 MSG_WriteByte (&sv.signon, ent->v.colormap);
1603 MSG_WriteByte (&sv.signon, ent->v.skin);
1604 for (i=0 ; i<3 ; i++)
1606 MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
1607 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1610 // throw the entity away now
1611 ED_Free (ent);
1614 //=============================================================================
1617 ==============
1618 PF_setspawnparms
1619 ==============
1621 void PF_setspawnparms (void)
1623 edict_t *ent;
1624 int i;
1625 client_t *client;
1627 ent = G_EDICT(OFS_PARM0);
1628 i = NUM_FOR_EDICT(ent);
1629 if (i < 1 || i > svs.maxclients)
1630 PR_RunError ("Entity is not a client");
1632 // copy spawn parms out of the client_t
1633 client = svs.clients + (i-1);
1635 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1636 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1640 ==============
1641 PF_changelevel
1642 ==============
1644 void PF_changelevel (void)
1646 #ifdef QUAKE2
1647 char *s1, *s2;
1649 if (svs.changelevel_issued)
1650 return;
1651 svs.changelevel_issued = true;
1653 s1 = G_STRING(OFS_PARM0);
1654 s2 = G_STRING(OFS_PARM1);
1656 if ((int)pr_global_struct->serverflags & (SFL_NEW_UNIT | SFL_NEW_EPISODE))
1657 Cbuf_AddText (va("changelevel %s %s\n",s1, s2));
1658 else
1659 Cbuf_AddText (va("changelevel2 %s %s\n",s1, s2));
1660 #else
1661 char *s;
1663 // make sure we don't issue two changelevels
1664 if (svs.changelevel_issued)
1665 return;
1666 svs.changelevel_issued = true;
1668 s = G_STRING(OFS_PARM0);
1669 Cbuf_AddText (va("changelevel %s\n",s));
1670 #endif
1674 #ifdef QUAKE2
1676 #define CONTENT_WATER -3
1677 #define CONTENT_SLIME -4
1678 #define CONTENT_LAVA -5
1680 #define FL_IMMUNE_WATER 131072
1681 #define FL_IMMUNE_SLIME 262144
1682 #define FL_IMMUNE_LAVA 524288
1684 #define CHAN_VOICE 2
1685 #define CHAN_BODY 4
1687 #define ATTN_NORM 1
1689 void PF_WaterMove (void)
1691 edict_t *self;
1692 int flags;
1693 int waterlevel;
1694 int watertype;
1695 float drownlevel;
1696 float damage = 0.0;
1698 self = PROG_TO_EDICT(pr_global_struct->self);
1700 if (self->v.movetype == MOVETYPE_NOCLIP)
1702 self->v.air_finished = sv.time + 12;
1703 G_FLOAT(OFS_RETURN) = damage;
1704 return;
1707 if (self->v.health < 0)
1709 G_FLOAT(OFS_RETURN) = damage;
1710 return;
1713 if (self->v.deadflag == DEAD_NO)
1714 drownlevel = 3;
1715 else
1716 drownlevel = 1;
1718 flags = (int)self->v.flags;
1719 waterlevel = (int)self->v.waterlevel;
1720 watertype = (int)self->v.watertype;
1722 if (!(flags & (FL_IMMUNE_WATER + FL_GODMODE)))
1723 if (((flags & FL_SWIM) && (waterlevel < drownlevel)) || (waterlevel >= drownlevel))
1725 if (self->v.air_finished < sv.time)
1726 if (self->v.pain_finished < sv.time)
1728 self->v.dmg = self->v.dmg + 2;
1729 if (self->v.dmg > 15)
1730 self->v.dmg = 10;
1731 // T_Damage (self, world, world, self.dmg, 0, FALSE);
1732 damage = self->v.dmg;
1733 self->v.pain_finished = sv.time + 1.0;
1736 else
1738 if (self->v.air_finished < sv.time)
1739 // sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
1740 SV_StartSound (self, CHAN_VOICE, "player/gasp2.wav", 255, ATTN_NORM);
1741 else if (self->v.air_finished < sv.time + 9)
1742 // sound (self, CHAN_VOICE, "player/gasp1.wav", 1, ATTN_NORM);
1743 SV_StartSound (self, CHAN_VOICE, "player/gasp1.wav", 255, ATTN_NORM);
1744 self->v.air_finished = sv.time + 12.0;
1745 self->v.dmg = 2;
1748 if (!waterlevel)
1750 if (flags & FL_INWATER)
1752 // play leave water sound
1753 // sound (self, CHAN_BODY, "misc/outwater.wav", 1, ATTN_NORM);
1754 SV_StartSound (self, CHAN_BODY, "misc/outwater.wav", 255, ATTN_NORM);
1755 self->v.flags = (float)(flags &~FL_INWATER);
1757 self->v.air_finished = sv.time + 12.0;
1758 G_FLOAT(OFS_RETURN) = damage;
1759 return;
1762 if (watertype == CONTENT_LAVA)
1763 { // do damage
1764 if (!(flags & (FL_IMMUNE_LAVA + FL_GODMODE)))
1765 if (self->v.dmgtime < sv.time)
1767 if (self->v.radsuit_finished < sv.time)
1768 self->v.dmgtime = sv.time + 0.2;
1769 else
1770 self->v.dmgtime = sv.time + 1.0;
1771 // T_Damage (self, world, world, 10*self.waterlevel, 0, TRUE);
1772 damage = (float)(10*waterlevel);
1775 else if (watertype == CONTENT_SLIME)
1776 { // do damage
1777 if (!(flags & (FL_IMMUNE_SLIME + FL_GODMODE)))
1778 if (self->v.dmgtime < sv.time && self->v.radsuit_finished < sv.time)
1780 self->v.dmgtime = sv.time + 1.0;
1781 // T_Damage (self, world, world, 4*self.waterlevel, 0, TRUE);
1782 damage = (float)(4*waterlevel);
1786 if ( !(flags & FL_INWATER) )
1789 // player enter water sound
1790 if (watertype == CONTENT_LAVA)
1791 // sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
1792 SV_StartSound (self, CHAN_BODY, "player/inlava.wav", 255, ATTN_NORM);
1793 if (watertype == CONTENT_WATER)
1794 // sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
1795 SV_StartSound (self, CHAN_BODY, "player/inh2o.wav", 255, ATTN_NORM);
1796 if (watertype == CONTENT_SLIME)
1797 // sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
1798 SV_StartSound (self, CHAN_BODY, "player/slimbrn2.wav", 255, ATTN_NORM);
1800 self->v.flags = (float)(flags | FL_INWATER);
1801 self->v.dmgtime = 0;
1804 if (! (flags & FL_WATERJUMP) )
1806 // self.velocity = self.velocity - 0.8*self.waterlevel*frametime*self.velocity;
1807 VectorMA (self->v.velocity, -0.8 * self->v.waterlevel * host_frametime, self->v.velocity, self->v.velocity);
1810 G_FLOAT(OFS_RETURN) = damage;
1814 void PF_sin (void)
1816 G_FLOAT(OFS_RETURN) = sinf(G_FLOAT(OFS_PARM0));
1819 void PF_cos (void)
1821 G_FLOAT(OFS_RETURN) = cosf(G_FLOAT(OFS_PARM0));
1824 void PF_sqrt (void)
1826 G_FLOAT(OFS_RETURN) = sqrtf(G_FLOAT(OFS_PARM0));
1828 #endif
1830 void PF_Fixme (void)
1832 PR_RunError ("unimplemented bulitin");
1837 builtin_t pr_builtin[] =
1839 PF_Fixme,
1840 PF_makevectors, // void(entity e) makevectors = #1;
1841 PF_setorigin, // void(entity e, vector o) setorigin = #2;
1842 PF_setmodel, // void(entity e, string m) setmodel = #3;
1843 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
1844 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
1845 PF_break, // void() break = #6;
1846 PF_random, // float() random = #7;
1847 PF_sound, // void(entity e, float chan, string samp) sound = #8;
1848 PF_normalize, // vector(vector v) normalize = #9;
1849 PF_error, // void(string e) error = #10;
1850 PF_objerror, // void(string e) objerror = #11;
1851 PF_vlen, // float(vector v) vlen = #12;
1852 PF_vectoyaw, // float(vector v) vectoyaw = #13;
1853 PF_Spawn, // entity() spawn = #14;
1854 PF_Remove, // void(entity e) remove = #15;
1855 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
1856 PF_checkclient, // entity() clientlist = #17;
1857 PF_Find, // entity(entity start, .string fld, string match) find = #18;
1858 PF_precache_sound, // void(string s) precache_sound = #19;
1859 PF_precache_model, // void(string s) precache_model = #20;
1860 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
1861 PF_findradius, // entity(vector org, float rad) findradius = #22;
1862 PF_bprint, // void(string s) bprint = #23;
1863 PF_sprint, // void(entity client, string s) sprint = #24;
1864 PF_dprint, // void(string s) dprint = #25;
1865 PF_ftos, // void(string s) ftos = #26;
1866 PF_vtos, // void(string s) vtos = #27;
1867 PF_coredump,
1868 PF_traceon,
1869 PF_traceoff,
1870 PF_eprint, // void(entity e) debug print an entire entity
1871 PF_walkmove, // float(float yaw, float dist) walkmove
1872 PF_Fixme, // float(float yaw, float dist) walkmove
1873 PF_droptofloor,
1874 PF_lightstyle,
1875 PF_rint,
1876 PF_floor,
1877 PF_ceil,
1878 PF_Fixme,
1879 PF_checkbottom,
1880 PF_pointcontents,
1881 PF_Fixme,
1882 PF_fabs,
1883 PF_aim,
1884 PF_cvar,
1885 PF_localcmd,
1886 PF_nextent,
1887 PF_particle,
1888 PF_changeyaw,
1889 PF_Fixme,
1890 PF_vectoangles,
1892 PF_WriteByte,
1893 PF_WriteChar,
1894 PF_WriteShort,
1895 PF_WriteLong,
1896 PF_WriteCoord,
1897 PF_WriteAngle,
1898 PF_WriteString,
1899 PF_WriteEntity,
1901 #ifdef QUAKE2
1902 PF_sin,
1903 PF_cos,
1904 PF_sqrt,
1905 PF_changepitch,
1906 PF_TraceToss,
1907 PF_etos,
1908 PF_WaterMove,
1909 #else
1910 PF_Fixme,
1911 PF_Fixme,
1912 PF_Fixme,
1913 PF_Fixme,
1914 PF_Fixme,
1915 PF_Fixme,
1916 PF_Fixme,
1917 #endif
1919 SV_MoveToGoal,
1920 PF_precache_file,
1921 PF_makestatic,
1923 PF_changelevel,
1924 PF_Fixme,
1926 PF_cvar_set,
1927 PF_centerprint,
1929 PF_ambientsound,
1931 PF_precache_model,
1932 PF_precache_sound, // precache_sound2 is different only for qcc
1933 PF_precache_file,
1935 PF_setspawnparms
1938 builtin_t *pr_builtins = pr_builtin;
1939 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);