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.
23 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
25 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
29 ===============================================================================
33 ===============================================================================
37 char *PF_VarString (int first)
43 for (i=first ; i<pr_argc ; i++)
45 strcat (out, G_STRING((OFS_PARM0+i*3)));
50 char *ENGINE_EXTENSIONS = "\
53 DP_ENT_DELTACOMPRESS \
65 DP_SV_DRAWONLYTOCLIENT \
66 DP_SV_NODRAWTOCLIENT \
67 DP_SV_EXTERIORMODELTOCLIENT \
82 DP_QC_FINDCHAINFLOAT \
93 qboolean checkextension(char *name)
98 for (e = ENGINE_EXTENSIONS;*e;e++)
105 while (*e && *e != ' ')
107 if (e - start == len)
108 if (!strncasecmp(start, name, len))
118 returns true if the extension is supported by the server
120 checkextension(extensionname)
123 void PF_checkextension (void)
125 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
132 This is a TERMINAL error, which will kill off the entire server.
144 Con_Printf ("======SERVER ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
145 ed = PROG_TO_EDICT(pr_global_struct->self);
148 Host_Error ("Program error");
155 Dumps out self, then an error message. The program is aborted and self is
156 removed, but the level can continue.
161 void PF_objerror (void)
167 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
168 ed = PROG_TO_EDICT(pr_global_struct->self);
172 // LordHavoc: bug fix - no longer kills server
173 // Host_Error ("Program error");
182 Writes new values for v_forward, v_up, and v_right based on angles
186 void PF_makevectors (void)
188 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
195 Writes new values for v_forward, v_up, and v_right based on the given forward vector
196 vectorvectors(vector, vector)
199 void PF_vectorvectors (void)
201 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
202 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
209 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
211 setorigin (entity, origin)
214 void PF_setorigin (void)
219 e = G_EDICT(OFS_PARM0);
220 org = G_VECTOR(OFS_PARM1);
221 VectorCopy (org, e->v.origin);
222 SV_LinkEdict (e, false);
226 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
232 float xvector[2], yvector[2];
234 vec3_t base, transformed;
239 for (i=0 ; i<3 ; i++)
241 PR_RunError ("backwards mins/maxs");
244 rotate = false; // FIXME: implement rotation properly again
248 VectorCopy (min, rmin);
249 VectorCopy (max, rmax);
253 // find min / max for rotations
254 angles = e->v.angles;
256 a = angles[1]/180 * M_PI;
260 yvector[0] = -sin(a);
263 VectorCopy (min, bounds[0]);
264 VectorCopy (max, bounds[1]);
266 rmin[0] = rmin[1] = rmin[2] = 9999;
267 rmax[0] = rmax[1] = rmax[2] = -9999;
269 for (i=0 ; i<= 1 ; i++)
271 base[0] = bounds[i][0];
272 for (j=0 ; j<= 1 ; j++)
274 base[1] = bounds[j][1];
275 for (k=0 ; k<= 1 ; k++)
277 base[2] = bounds[k][2];
279 // transform the point
280 transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
281 transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
282 transformed[2] = base[2];
284 for (l=0 ; l<3 ; l++)
286 if (transformed[l] < rmin[l])
287 rmin[l] = transformed[l];
288 if (transformed[l] > rmax[l])
289 rmax[l] = transformed[l];
296 // set derived values
297 VectorCopy (rmin, e->v.mins);
298 VectorCopy (rmax, e->v.maxs);
299 VectorSubtract (max, min, e->v.size);
302 // set derived values
303 VectorCopy (min, e->v.mins);
304 VectorCopy (max, e->v.maxs);
305 VectorSubtract (max, min, e->v.size);
307 SV_LinkEdict (e, false);
314 the size box is rotated by the current angle
315 LordHavoc: no it isn't...
317 setsize (entity, minvector, maxvector)
320 void PF_setsize (void)
325 e = G_EDICT(OFS_PARM0);
326 min = G_VECTOR(OFS_PARM1);
327 max = G_VECTOR(OFS_PARM2);
328 SetMinMaxSize (e, min, max, false);
336 setmodel(entity, model)
339 void PF_setmodel (void)
346 e = G_EDICT(OFS_PARM0);
347 m = G_STRING(OFS_PARM1);
349 // check to see if model was properly precached
350 for (i=0, check = sv.model_precache ; *check ; i++, check++)
351 if (!strcmp(*check, m))
355 PR_RunError ("no precache: %s\n", m);
358 e->v.model = m - pr_strings;
359 e->v.modelindex = i; //SV_ModelIndex (m);
361 mod = sv.models[ (int)e->v.modelindex]; // Mod_ForName (m, true);
365 { // LordHavoc: corrected model bounding box, but for compatibility that means I have to break it here
367 if (mod->type == ALIASTYPE_MDL)
369 min[0] = min[1] = min[2] = -16;
370 max[0] = max[1] = max[2] = 16;
371 SetMinMaxSize (e, min, max, true);
374 SetMinMaxSize (e, mod->mins, mod->maxs, true);
377 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
379 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
386 broadcast print to everyone on server
391 void PF_bprint (void)
396 SV_BroadcastPrintf ("%s", s);
403 single print to a specific client
405 sprint(clientent, value)
408 void PF_sprint (void)
414 entnum = G_EDICTNUM(OFS_PARM0);
417 if (entnum < 1 || entnum > svs.maxclients)
419 Con_Printf ("tried to sprint to a non-client\n");
423 client = &svs.clients[entnum-1];
425 MSG_WriteChar (&client->message,svc_print);
426 MSG_WriteString (&client->message, s );
434 single print to a specific client
436 centerprint(clientent, value)
439 void PF_centerprint (void)
445 entnum = G_EDICTNUM(OFS_PARM0);
448 if (entnum < 1 || entnum > svs.maxclients)
450 Con_Printf ("tried to sprint to a non-client\n");
454 client = &svs.clients[entnum-1];
456 MSG_WriteChar (&client->message,svc_centerprint);
457 MSG_WriteString (&client->message, s );
465 vector normalize(vector)
468 void PF_normalize (void)
474 value1 = G_VECTOR(OFS_PARM0);
476 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
480 newvalue[0] = newvalue[1] = newvalue[2] = 0;
484 newvalue[0] = value1[0] * new;
485 newvalue[1] = value1[1] * new;
486 newvalue[2] = value1[2] * new;
489 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
504 value1 = G_VECTOR(OFS_PARM0);
506 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
509 G_FLOAT(OFS_RETURN) = new;
516 float vectoyaw(vector)
519 void PF_vectoyaw (void)
524 value1 = G_VECTOR(OFS_PARM0);
526 if (value1[1] == 0 && value1[0] == 0)
530 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
535 G_FLOAT(OFS_RETURN) = yaw;
543 vector vectoangles(vector)
546 void PF_vectoangles (void)
552 value1 = G_VECTOR(OFS_PARM0);
554 if (value1[1] == 0 && value1[0] == 0)
564 // LordHavoc: optimized a bit
567 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
571 else if (value1[1] > 0)
576 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
577 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
582 G_FLOAT(OFS_RETURN+0) = pitch;
583 G_FLOAT(OFS_RETURN+1) = yaw;
584 G_FLOAT(OFS_RETURN+2) = 0;
591 Returns a number from 0<= num < 1
596 void PF_random (void)
600 num = (rand ()&0x7fff) / ((float)0x7fff);
602 G_FLOAT(OFS_RETURN) = num;
609 particle(origin, color, count)
612 void PF_particle (void)
618 org = G_VECTOR(OFS_PARM0);
619 dir = G_VECTOR(OFS_PARM1);
620 color = G_FLOAT(OFS_PARM2);
621 count = G_FLOAT(OFS_PARM3);
622 SV_StartParticle (org, dir, color, count);
632 void PF_ambientsound (void)
637 float vol, attenuation;
638 int i, soundnum, large;
640 pos = G_VECTOR (OFS_PARM0);
641 samp = G_STRING(OFS_PARM1);
642 vol = G_FLOAT(OFS_PARM2);
643 attenuation = G_FLOAT(OFS_PARM3);
645 // check to see if samp was properly precached
646 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
647 if (!strcmp(*check,samp))
652 Con_Printf ("no precache: %s\n", samp);
660 // add an svc_spawnambient command to the level signon packet
663 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
665 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
667 for (i=0 ; i<3 ; i++)
668 MSG_WriteDPCoord(&sv.signon, pos[i]);
671 MSG_WriteShort (&sv.signon, soundnum);
673 MSG_WriteByte (&sv.signon, soundnum);
675 MSG_WriteByte (&sv.signon, vol*255);
676 MSG_WriteByte (&sv.signon, attenuation*64);
684 Each entity can have eight independant sound sources, like voice,
687 Channel 0 is an auto-allocate channel, the others override anything
688 already running on that entity/channel pair.
690 An attenuation of 0 will play full volume everywhere in the level.
691 Larger attenuations will drop off.
703 entity = G_EDICT(OFS_PARM0);
704 channel = G_FLOAT(OFS_PARM1);
705 sample = G_STRING(OFS_PARM2);
706 volume = G_FLOAT(OFS_PARM3) * 255;
707 attenuation = G_FLOAT(OFS_PARM4);
709 if (volume < 0 || volume > 255)
710 Host_Error ("SV_StartSound: volume = %i", volume);
712 if (attenuation < 0 || attenuation > 4)
713 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
715 if (channel < 0 || channel > 7)
716 Host_Error ("SV_StartSound: channel = %i", channel);
718 SV_StartSound (entity, channel, sample, volume, attenuation);
730 // Con_Printf ("break statement\n");
731 // *(int *)-4 = 0; // dump to debugger
732 PR_RunError ("break statement");
739 Used for use tracing and shot targeting
740 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
741 if the tryents flag is set.
743 traceline (vector1, vector2, tryents)
746 void PF_traceline (void)
753 v1 = G_VECTOR(OFS_PARM0);
754 v2 = G_VECTOR(OFS_PARM1);
755 nomonsters = G_FLOAT(OFS_PARM2);
756 ent = G_EDICT(OFS_PARM3);
758 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
760 pr_global_struct->trace_allsolid = trace.allsolid;
761 pr_global_struct->trace_startsolid = trace.startsolid;
762 pr_global_struct->trace_fraction = trace.fraction;
763 pr_global_struct->trace_inwater = trace.inwater;
764 pr_global_struct->trace_inopen = trace.inopen;
765 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
766 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
767 pr_global_struct->trace_plane_dist = trace.plane.dist;
769 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
771 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
772 // FIXME: add trace_endcontents
780 Used for use tracing and shot targeting
781 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
782 if the tryents flag is set.
784 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
787 // LordHavoc: added this for my own use, VERY useful, similar to traceline
788 void PF_tracebox (void)
790 float *v1, *v2, *m1, *m2;
795 v1 = G_VECTOR(OFS_PARM0);
796 m1 = G_VECTOR(OFS_PARM1);
797 m2 = G_VECTOR(OFS_PARM2);
798 v2 = G_VECTOR(OFS_PARM3);
799 nomonsters = G_FLOAT(OFS_PARM4);
800 ent = G_EDICT(OFS_PARM5);
802 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
804 pr_global_struct->trace_allsolid = trace.allsolid;
805 pr_global_struct->trace_startsolid = trace.startsolid;
806 pr_global_struct->trace_fraction = trace.fraction;
807 pr_global_struct->trace_inwater = trace.inwater;
808 pr_global_struct->trace_inopen = trace.inopen;
809 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
810 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
811 pr_global_struct->trace_plane_dist = trace.plane.dist;
813 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
815 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
818 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
819 void PF_TraceToss (void)
825 ent = G_EDICT(OFS_PARM0);
826 ignore = G_EDICT(OFS_PARM1);
828 trace = SV_Trace_Toss (ent, ignore);
830 pr_global_struct->trace_allsolid = trace.allsolid;
831 pr_global_struct->trace_startsolid = trace.startsolid;
832 pr_global_struct->trace_fraction = trace.fraction;
833 pr_global_struct->trace_inwater = trace.inwater;
834 pr_global_struct->trace_inopen = trace.inopen;
835 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
836 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
837 pr_global_struct->trace_plane_dist = trace.plane.dist;
839 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
841 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
849 Returns true if the given entity can move to the given position from it's
850 current position by walking or rolling.
852 scalar checkpos (entity, vector)
855 void PF_checkpos (void)
859 //============================================================================
861 qbyte checkpvs[MAX_MAP_LEAFS/8];
863 int PF_newcheckclient (int check)
871 // cycle to the next one
875 if (check > svs.maxclients)
876 check = svs.maxclients;
878 if (check == svs.maxclients)
885 if (i == svs.maxclients+1)
891 break; // didn't find anything else
895 if (ent->v.health <= 0)
897 if ((int)ent->v.flags & FL_NOTARGET)
900 // anything that is a client, or has a client as an enemy
904 // get the PVS for the entity
905 VectorAdd (ent->v.origin, ent->v.view_ofs, org);
906 leaf = Mod_PointInLeaf (org, sv.worldmodel);
907 pvs = Mod_LeafPVS (leaf, sv.worldmodel);
908 memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
917 Returns a client (or object that has a client enemy) that would be a
920 If there is more than one valid option, they are cycled each frame
922 If (self.origin + self.viewofs) is not in the PVS of the current target,
923 it is not returned at all.
928 int c_invis, c_notvis;
929 void PF_checkclient (void)
936 // find a new check if on a new frame
937 if (sv.time - sv.lastchecktime >= 0.1)
939 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
940 sv.lastchecktime = sv.time;
943 // return check if it might be visible
944 ent = EDICT_NUM(sv.lastcheck);
945 if (ent->free || ent->v.health <= 0)
947 RETURN_EDICT(sv.edicts);
951 // if current entity can't possibly see the check entity, return 0
952 self = PROG_TO_EDICT(pr_global_struct->self);
953 VectorAdd (self->v.origin, self->v.view_ofs, view);
954 leaf = Mod_PointInLeaf (view, sv.worldmodel);
955 l = (leaf - sv.worldmodel->leafs) - 1;
956 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
959 RETURN_EDICT(sv.edicts);
963 // might be able to see it
968 //============================================================================
975 Sends text over to the client's execution buffer
977 stuffcmd (clientent, value)
980 void PF_stuffcmd (void)
986 entnum = G_EDICTNUM(OFS_PARM0);
987 if (entnum < 1 || entnum > svs.maxclients)
988 PR_RunError ("Parm 0 not a client");
989 str = G_STRING(OFS_PARM1);
992 host_client = &svs.clients[entnum-1];
993 Host_ClientCommands ("%s", str);
1001 Sends text over to the client's execution buffer
1006 void PF_localcmd (void)
1010 str = G_STRING(OFS_PARM0);
1025 str = G_STRING(OFS_PARM0);
1027 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
1037 void PF_cvar_set (void)
1041 var = G_STRING(OFS_PARM0);
1042 val = G_STRING(OFS_PARM1);
1044 Cvar_Set (var, val);
1051 Returns a chain of entities that have origins within a spherical area
1053 findradius (origin, radius)
1056 void PF_findradius (void)
1058 edict_t *ent, *chain;
1065 chain = (edict_t *)sv.edicts;
1067 org = G_VECTOR(OFS_PARM0);
1068 radius = G_FLOAT(OFS_PARM1);
1069 radius2 = radius * radius;
1071 ent = NEXT_EDICT(sv.edicts);
1072 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1076 if (ent->v.solid == SOLID_NOT)
1079 // LordHavoc: compare against bounding box rather than center,
1080 // and use DotProduct instead of Length, major speedup
1081 eorg[0] = (org[0] - ent->v.origin[0]) - bound(ent->v.mins[0], (org[0] - ent->v.origin[0]), ent->v.maxs[0]);
1082 eorg[1] = (org[1] - ent->v.origin[1]) - bound(ent->v.mins[1], (org[1] - ent->v.origin[1]), ent->v.maxs[1]);
1083 eorg[2] = (org[2] - ent->v.origin[2]) - bound(ent->v.mins[2], (org[2] - ent->v.origin[2]), ent->v.maxs[2]);
1084 if (DotProduct(eorg, eorg) > radius2)
1087 ent->v.chain = EDICT_TO_PROG(chain);
1091 RETURN_EDICT(chain);
1100 void PF_dprint (void)
1102 Con_DPrintf ("%s",PF_VarString(0));
1105 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
1106 #define STRINGTEMP_BUFFERS 16
1107 #define STRINGTEMP_LENGTH 128
1108 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
1109 static int pr_string_tempindex = 0;
1111 static char *PR_GetTempString(void)
1114 s = pr_string_temp[pr_string_tempindex];
1115 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
1123 v = G_FLOAT(OFS_PARM0);
1125 s = PR_GetTempString();
1128 sprintf (s, "%d",(int)v);
1130 sprintf (s, "%5.1f",v);
1132 // LordHavoc: ftos improvement
1133 sprintf (s, "%g", v);
1134 G_INT(OFS_RETURN) = s - pr_strings;
1140 v = G_FLOAT(OFS_PARM0);
1141 G_FLOAT(OFS_RETURN) = fabs(v);
1147 s = PR_GetTempString();
1148 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1149 G_INT(OFS_RETURN) = s - pr_strings;
1155 s = PR_GetTempString();
1156 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1157 G_INT(OFS_RETURN) = s - pr_strings;
1160 void PF_Spawn (void)
1167 void PF_Remove (void)
1171 ed = G_EDICT(OFS_PARM0);
1172 if (ed == sv.edicts)
1173 PR_RunError("remove: tried to remove world\n");
1174 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1175 PR_RunError("remove: tried to remove a client\n");
1180 // entity (entity start, .string field, string match) find = #5;
1188 e = G_EDICTNUM(OFS_PARM0);
1189 f = G_INT(OFS_PARM1);
1190 s = G_STRING(OFS_PARM2);
1193 RETURN_EDICT(sv.edicts);
1197 for (e++ ; e < sv.num_edicts ; e++)
1212 RETURN_EDICT(sv.edicts);
1215 // LordHavoc: added this for searching float, int, and entity reference fields
1216 void PF_FindFloat (void)
1223 e = G_EDICTNUM(OFS_PARM0);
1224 f = G_INT(OFS_PARM1);
1225 s = G_FLOAT(OFS_PARM2);
1227 for (e++ ; e < sv.num_edicts ; e++)
1232 if (E_FLOAT(ed,f) == s)
1239 RETURN_EDICT(sv.edicts);
1242 // chained search for strings in entity fields
1243 // entity(.string field, string match) findchain = #402;
1244 void PF_findchain (void)
1249 edict_t *ent, *chain;
1251 chain = (edict_t *)sv.edicts;
1253 f = G_INT(OFS_PARM0);
1254 s = G_STRING(OFS_PARM1);
1257 RETURN_EDICT(sv.edicts);
1261 ent = NEXT_EDICT(sv.edicts);
1262 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1266 t = E_STRING(ent,f);
1272 ent->v.chain = EDICT_TO_PROG(chain);
1276 RETURN_EDICT(chain);
1279 // LordHavoc: chained search for float, int, and entity reference fields
1280 // entity(.string field, float match) findchainfloat = #403;
1281 void PF_findchainfloat (void)
1286 edict_t *ent, *chain;
1288 chain = (edict_t *)sv.edicts;
1290 f = G_INT(OFS_PARM0);
1291 s = G_FLOAT(OFS_PARM1);
1293 ent = NEXT_EDICT(sv.edicts);
1294 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1298 if (E_FLOAT(ent,f) != s)
1301 ent->v.chain = EDICT_TO_PROG(chain);
1305 RETURN_EDICT(chain);
1308 void PR_CheckEmptyString (char *s)
1311 PR_RunError ("Bad string");
1314 void PF_precache_file (void)
1315 { // precache_file is only used to copy files with qcc, it does nothing
1316 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1319 void PF_precache_sound (void)
1324 if (sv.state != ss_loading)
1325 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1327 s = G_STRING(OFS_PARM0);
1328 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1329 PR_CheckEmptyString (s);
1331 for (i=0 ; i<MAX_SOUNDS ; i++)
1333 if (!sv.sound_precache[i])
1335 sv.sound_precache[i] = s;
1338 if (!strcmp(sv.sound_precache[i], s))
1341 PR_RunError ("PF_precache_sound: overflow");
1344 void PF_precache_model (void)
1349 if (sv.state != ss_loading)
1350 PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
1352 s = G_STRING(OFS_PARM0);
1353 if (sv.worldmodel->ishlbsp && ((!s) || (!s[0])))
1355 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1356 PR_CheckEmptyString (s);
1358 for (i=0 ; i<MAX_MODELS ; i++)
1360 if (!sv.model_precache[i])
1362 sv.model_precache[i] = s;
1363 sv.models[i] = Mod_ForName (s, true, false, false);
1366 if (!strcmp(sv.model_precache[i], s))
1369 PR_RunError ("PF_precache_model: overflow");
1373 void PF_coredump (void)
1378 void PF_traceon (void)
1383 void PF_traceoff (void)
1388 void PF_eprint (void)
1390 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1397 float(float yaw, float dist) walkmove
1400 void PF_walkmove (void)
1408 ent = PROG_TO_EDICT(pr_global_struct->self);
1409 yaw = G_FLOAT(OFS_PARM0);
1410 dist = G_FLOAT(OFS_PARM1);
1412 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1414 G_FLOAT(OFS_RETURN) = 0;
1418 yaw = yaw*M_PI*2 / 360;
1420 move[0] = cos(yaw)*dist;
1421 move[1] = sin(yaw)*dist;
1424 // save program state, because SV_movestep may call other progs
1425 oldf = pr_xfunction;
1426 oldself = pr_global_struct->self;
1428 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1431 // restore program state
1432 pr_xfunction = oldf;
1433 pr_global_struct->self = oldself;
1443 void PF_droptofloor (void)
1449 ent = PROG_TO_EDICT(pr_global_struct->self);
1451 VectorCopy (ent->v.origin, end);
1454 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
1456 if (trace.fraction == 1 || trace.allsolid)
1457 G_FLOAT(OFS_RETURN) = 0;
1460 VectorCopy (trace.endpos, ent->v.origin);
1461 SV_LinkEdict (ent, false);
1462 ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
1463 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
1464 G_FLOAT(OFS_RETURN) = 1;
1465 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1466 ent->suspendedinairflag = true;
1474 void(float style, string value) lightstyle
1477 void PF_lightstyle (void)
1484 style = G_FLOAT(OFS_PARM0);
1485 val = G_STRING(OFS_PARM1);
1487 // change the string in sv
1488 sv.lightstyles[style] = val;
1490 // send message to all clients on this server
1491 if (sv.state != ss_active)
1494 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1495 if (client->active || client->spawned)
1497 MSG_WriteChar (&client->message, svc_lightstyle);
1498 MSG_WriteChar (&client->message,style);
1499 MSG_WriteString (&client->message, val);
1506 f = G_FLOAT(OFS_PARM0);
1508 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1510 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1512 void PF_floor (void)
1514 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1518 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1527 void PF_checkbottom (void)
1529 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1537 void PF_pointcontents (void)
1539 G_FLOAT(OFS_RETURN) = SV_PointContents (G_VECTOR(OFS_PARM0));
1546 entity nextent(entity)
1549 void PF_nextent (void)
1554 i = G_EDICTNUM(OFS_PARM0);
1558 if (i == sv.num_edicts)
1560 RETURN_EDICT(sv.edicts);
1576 Pick a vector for the player to shoot along
1577 vector aim(entity, missilespeed)
1582 edict_t *ent, *check, *bestent;
1583 vec3_t start, dir, end, bestdir;
1586 float dist, bestdist;
1589 ent = G_EDICT(OFS_PARM0);
1590 speed = G_FLOAT(OFS_PARM1);
1592 VectorCopy (ent->v.origin, start);
1595 // try sending a trace straight
1596 VectorCopy (pr_global_struct->v_forward, dir);
1597 VectorMA (start, 2048, dir, end);
1598 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1599 if (tr.ent && ((edict_t *)tr.ent)->v.takedamage == DAMAGE_AIM
1600 && (!teamplay.integer || ent->v.team <=0 || ent->v.team != ((edict_t *)tr.ent)->v.team) )
1602 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1607 // try all possible entities
1608 VectorCopy (dir, bestdir);
1609 bestdist = sv_aim.value;
1612 check = NEXT_EDICT(sv.edicts);
1613 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1615 if (check->v.takedamage != DAMAGE_AIM)
1619 if (teamplay.integer && ent->v.team > 0 && ent->v.team == check->v.team)
1620 continue; // don't aim at teammate
1621 for (j=0 ; j<3 ; j++)
1622 end[j] = check->v.origin[j]
1623 + 0.5*(check->v.mins[j] + check->v.maxs[j]);
1624 VectorSubtract (end, start, dir);
1625 VectorNormalize (dir);
1626 dist = DotProduct (dir, pr_global_struct->v_forward);
1627 if (dist < bestdist)
1628 continue; // to far to turn
1629 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1630 if (tr.ent == check)
1631 { // can shoot at this one
1639 VectorSubtract (bestent->v.origin, ent->v.origin, dir);
1640 dist = DotProduct (dir, pr_global_struct->v_forward);
1641 VectorScale (pr_global_struct->v_forward, dist, end);
1643 VectorNormalize (end);
1644 VectorCopy (end, G_VECTOR(OFS_RETURN));
1648 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1656 This was a major timewaster in progs, so it was converted to C
1659 void PF_changeyaw (void)
1662 float ideal, current, move, speed;
1664 ent = PROG_TO_EDICT(pr_global_struct->self);
1665 current = ANGLEMOD(ent->v.angles[1]);
1666 ideal = ent->v.ideal_yaw;
1667 speed = ent->v.yaw_speed;
1669 if (current == ideal)
1671 move = ideal - current;
1672 if (ideal > current)
1693 ent->v.angles[1] = ANGLEMOD (current + move);
1701 void PF_changepitch (void)
1704 float ideal, current, move, speed;
1707 ent = G_EDICT(OFS_PARM0);
1708 current = ANGLEMOD( ent->v.angles[0] );
1709 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1710 ideal = val->_float;
1713 PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1716 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1717 speed = val->_float;
1720 PR_RunError ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1724 if (current == ideal)
1726 move = ideal - current;
1727 if (ideal > current)
1748 ent->v.angles[0] = ANGLEMOD (current + move);
1752 ===============================================================================
1756 ===============================================================================
1759 #define MSG_BROADCAST 0 // unreliable to all
1760 #define MSG_ONE 1 // reliable to one (msg_entity)
1761 #define MSG_ALL 2 // reliable to all
1762 #define MSG_INIT 3 // write to the init string
1764 sizebuf_t *WriteDest (void)
1770 dest = G_FLOAT(OFS_PARM0);
1774 return &sv.datagram;
1777 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1778 entnum = NUM_FOR_EDICT(ent);
1779 if (entnum < 1 || entnum > svs.maxclients)
1780 PR_RunError ("WriteDest: not a client");
1781 return &svs.clients[entnum-1].message;
1784 return &sv.reliable_datagram;
1790 PR_RunError ("WriteDest: bad destination");
1797 void PF_WriteByte (void)
1799 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1802 void PF_WriteChar (void)
1804 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1807 void PF_WriteShort (void)
1809 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1812 void PF_WriteLong (void)
1814 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1817 void PF_WriteAngle (void)
1819 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1822 void PF_WriteCoord (void)
1824 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1827 void PF_WriteString (void)
1829 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1833 void PF_WriteEntity (void)
1835 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1838 //=============================================================================
1840 int SV_ModelIndex (char *name);
1842 void PF_makestatic (void)
1847 ent = G_EDICT(OFS_PARM0);
1850 if (ent->v.modelindex >= 256 || ent->v.frame >= 256)
1855 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1856 MSG_WriteShort (&sv.signon, ent->v.modelindex);
1857 MSG_WriteShort (&sv.signon, ent->v.frame);
1861 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1862 MSG_WriteByte (&sv.signon, ent->v.modelindex);
1863 MSG_WriteByte (&sv.signon, ent->v.frame);
1866 MSG_WriteByte (&sv.signon, ent->v.colormap);
1867 MSG_WriteByte (&sv.signon, ent->v.skin);
1868 for (i=0 ; i<3 ; i++)
1870 MSG_WriteDPCoord(&sv.signon, ent->v.origin[i]);
1871 MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
1874 // throw the entity away now
1878 //=============================================================================
1885 void PF_setspawnparms (void)
1891 ent = G_EDICT(OFS_PARM0);
1892 i = NUM_FOR_EDICT(ent);
1893 if (i < 1 || i > svs.maxclients)
1894 PR_RunError ("Entity is not a client");
1896 // copy spawn parms out of the client_t
1897 client = svs.clients + (i-1);
1899 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1900 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1908 void PF_changelevel (void)
1912 // make sure we don't issue two changelevels
1913 if (svs.changelevel_issued)
1915 svs.changelevel_issued = true;
1917 s = G_STRING(OFS_PARM0);
1918 Cbuf_AddText (va("changelevel %s\n",s));
1923 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1928 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1933 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1940 Returns a vector of length < 1
1945 void PF_randomvec (void)
1950 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1951 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1952 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1954 while (DotProduct(temp, temp) >= 1);
1955 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1958 void SV_LightPoint (vec3_t color, vec3_t p);
1963 Returns a color vector indicating the lighting at the requested point.
1965 (Internal Operation note: actually measures the light beneath the point, just like
1966 the model lighting on the client)
1971 void PF_GetLight (void)
1975 p = G_VECTOR(OFS_PARM0);
1976 SV_LightPoint (color, p);
1977 VectorCopy (color, G_VECTOR(OFS_RETURN));
1980 #define MAX_QC_CVARS 128
1981 cvar_t qc_cvar[MAX_QC_CVARS];
1984 void PF_registercvar (void)
1988 name = G_STRING(OFS_PARM0);
1989 value = G_STRING(OFS_PARM1);
1990 G_FLOAT(OFS_RETURN) = 0;
1991 // first check to see if it has already been defined
1992 if (Cvar_FindVar (name))
1995 // check for overlap with a command
1996 if (Cmd_Exists (name))
1998 Con_Printf ("PF_registercvar: %s is a command\n", name);
2002 if (currentqc_cvar >= MAX_QC_CVARS)
2003 PR_RunError ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
2005 // copy the name and value
2006 variable = &qc_cvar[currentqc_cvar++];
2007 variable->name = Z_Malloc (strlen(name)+1);
2008 strcpy (variable->name, name);
2009 variable->string = Z_Malloc (strlen(value)+1);
2010 strcpy (variable->string, value);
2011 variable->value = atof (value);
2013 // link the variable in
2014 variable->next = cvar_vars;
2015 cvar_vars = variable;
2016 G_FLOAT(OFS_RETURN) = 1; // success
2023 returns the minimum of two supplied floats
2030 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2032 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2033 else if (pr_argc >= 3)
2036 float f = G_FLOAT(OFS_PARM0);
2037 for (i = 1;i < pr_argc;i++)
2038 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2039 f = G_FLOAT((OFS_PARM0+i*3));
2040 G_FLOAT(OFS_RETURN) = f;
2043 PR_RunError("min: must supply at least 2 floats\n");
2050 returns the maximum of two supplied floats
2057 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2059 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2060 else if (pr_argc >= 3)
2063 float f = G_FLOAT(OFS_PARM0);
2064 for (i = 1;i < pr_argc;i++)
2065 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2066 f = G_FLOAT((OFS_PARM0+i*3));
2067 G_FLOAT(OFS_RETURN) = f;
2070 PR_RunError("max: must supply at least 2 floats\n");
2077 returns number bounded by supplied range
2079 min(min, value, max)
2082 void PF_bound (void)
2084 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2091 returns a raised to power b
2098 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2105 copies data from one entity to another
2107 copyentity(src, dst)
2110 void PF_copyentity (void)
2113 in = G_EDICT(OFS_PARM0);
2114 out = G_EDICT(OFS_PARM1);
2115 memcpy(out, in, pr_edict_size);
2122 sets the color of a client and broadcasts the update to all connected clients
2124 setcolor(clientent, value)
2127 void PF_setcolor (void)
2132 entnum = G_EDICTNUM(OFS_PARM0);
2133 i = G_FLOAT(OFS_PARM1);
2135 if (entnum < 1 || entnum > svs.maxclients)
2137 Con_Printf ("tried to setcolor a non-client\n");
2141 client = &svs.clients[entnum-1];
2143 client->edict->v.team = (i & 15) + 1;
2145 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2146 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2147 MSG_WriteByte (&sv.reliable_datagram, i);
2154 effect(origin, modelname, startframe, framecount, framerate)
2157 void PF_effect (void)
2160 s = G_STRING(OFS_PARM1);
2162 PR_RunError("effect: no model specified\n");
2164 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2167 void PF_te_blood (void)
2169 if (G_FLOAT(OFS_PARM2) < 1)
2171 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2172 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2174 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2175 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2176 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2178 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2179 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2180 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2182 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2185 void PF_te_bloodshower (void)
2187 if (G_FLOAT(OFS_PARM3) < 1)
2189 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2190 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2192 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2193 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2194 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2196 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2197 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2200 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2202 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2205 void PF_te_explosionrgb (void)
2207 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2208 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2210 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2211 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2212 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2214 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2215 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2216 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2219 void PF_te_particlecube (void)
2221 if (G_FLOAT(OFS_PARM3) < 1)
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2226 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2227 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2228 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2230 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2231 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2232 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2234 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2235 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2236 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2238 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2240 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2241 // gravity true/false
2242 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2244 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2247 void PF_te_particlerain (void)
2249 if (G_FLOAT(OFS_PARM3) < 1)
2251 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2252 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2255 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2256 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2260 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2262 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2263 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2264 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2266 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2268 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2271 void PF_te_particlesnow (void)
2273 if (G_FLOAT(OFS_PARM3) < 1)
2275 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2276 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2286 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2287 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2288 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2290 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2292 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2295 void PF_te_spark (void)
2297 if (G_FLOAT(OFS_PARM2) < 1)
2299 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2300 MSG_WriteByte(&sv.datagram, TE_SPARK);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2304 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2306 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2307 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2308 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2310 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2313 void PF_te_gunshotquad (void)
2315 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2316 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2318 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2319 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2320 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2323 void PF_te_spikequad (void)
2325 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2326 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2328 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2329 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2330 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2333 void PF_te_superspikequad (void)
2335 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2336 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2338 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2339 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2340 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2343 void PF_te_explosionquad (void)
2345 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2346 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2348 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2349 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2350 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2353 void PF_te_smallflash (void)
2355 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2356 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2358 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2359 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2360 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2363 void PF_te_customflash (void)
2365 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2367 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2368 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2370 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2371 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2372 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2374 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2376 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2378 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2379 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2380 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2383 void PF_te_gunshot (void)
2385 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2386 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2388 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2389 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2390 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2393 void PF_te_spike (void)
2395 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2396 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2398 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2399 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2400 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2403 void PF_te_superspike (void)
2405 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2406 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2408 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2409 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2410 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2413 void PF_te_explosion (void)
2415 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2416 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2418 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2419 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2420 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2423 void PF_te_tarexplosion (void)
2425 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2426 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2428 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2429 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2430 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2433 void PF_te_wizspike (void)
2435 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2436 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2438 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2439 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2440 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2443 void PF_te_knightspike (void)
2445 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2446 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2448 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2449 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2450 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2453 void PF_te_lavasplash (void)
2455 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2456 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2458 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2459 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2460 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2463 void PF_te_teleport (void)
2465 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2466 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2468 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2469 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2470 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2473 void PF_te_explosion2 (void)
2475 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2476 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2478 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2479 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2480 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2482 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2485 void PF_te_lightning1 (void)
2487 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2488 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2490 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2494 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2496 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2497 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2498 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2501 void PF_te_lightning2 (void)
2503 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2504 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2506 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2508 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2509 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2510 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2517 void PF_te_lightning3 (void)
2519 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2520 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2522 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2524 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2525 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2526 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2528 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2529 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2533 void PF_te_beam (void)
2535 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2536 MSG_WriteByte(&sv.datagram, TE_BEAM);
2538 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2540 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2541 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2542 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2544 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2545 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2549 void PF_te_plasmaburn (void)
2551 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2552 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2553 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2554 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2555 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2558 void PF_Fixme (void)
2560 PR_RunError ("unimplemented builtin"); // LordHavoc: was misspelled (bulitin)
2565 builtin_t pr_builtin[] =
2568 PF_makevectors, // void(entity e) makevectors = #1;
2569 PF_setorigin, // void(entity e, vector o) setorigin = #2;
2570 PF_setmodel, // void(entity e, string m) setmodel = #3;
2571 PF_setsize, // void(entity e, vector min, vector max) setsize = #4;
2572 PF_Fixme, // void(entity e, vector min, vector max) setabssize = #5;
2573 PF_break, // void() break = #6;
2574 PF_random, // float() random = #7;
2575 PF_sound, // void(entity e, float chan, string samp) sound = #8;
2576 PF_normalize, // vector(vector v) normalize = #9;
2577 PF_error, // void(string e) error = #10;
2578 PF_objerror, // void(string e) objerror = #11;
2579 PF_vlen, // float(vector v) vlen = #12;
2580 PF_vectoyaw, // float(vector v) vectoyaw = #13;
2581 PF_Spawn, // entity() spawn = #14;
2582 PF_Remove, // void(entity e) remove = #15;
2583 PF_traceline, // float(vector v1, vector v2, float tryents) traceline = #16;
2584 PF_checkclient, // entity() clientlist = #17;
2585 PF_Find, // entity(entity start, .string fld, string match) find = #18;
2586 PF_precache_sound, // void(string s) precache_sound = #19;
2587 PF_precache_model, // void(string s) precache_model = #20;
2588 PF_stuffcmd, // void(entity client, string s)stuffcmd = #21;
2589 PF_findradius, // entity(vector org, float rad) findradius = #22;
2590 PF_bprint, // void(string s) bprint = #23;
2591 PF_sprint, // void(entity client, string s) sprint = #24;
2592 PF_dprint, // void(string s) dprint = #25;
2593 PF_ftos, // void(string s) ftos = #26;
2594 PF_vtos, // void(string s) vtos = #27;
2598 PF_eprint, // void(entity e) debug print an entire entity
2599 PF_walkmove, // float(float yaw, float dist) walkmove
2600 PF_Fixme, // float(float yaw, float dist) walkmove
2650 PF_precache_sound, // precache_sound2 is different only for qcc
2655 PF_Fixme, // #79 LordHavoc: dunno who owns 79-89, so these are just padding
2667 PF_tracebox, // #90 LordHavoc builtin range (9x)
2668 PF_randomvec, // #91
2670 PF_registercvar, // #93
2675 PF_FindFloat, // #98
2676 PF_checkextension, // #99
2677 #define a PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme, PF_Fixme,
2678 #define aa a a a a a a a a a a
2682 PF_copyentity, // #400 LordHavoc: builtin range (4xx)
2683 PF_setcolor, // #401
2684 PF_findchain, // #402
2685 PF_findchainfloat, // #403
2687 PF_te_blood, // #405
2688 PF_te_bloodshower, // #406
2689 PF_te_explosionrgb, // #407
2690 PF_te_particlecube, // #408
2691 PF_te_particlerain, // #409
2692 PF_te_particlesnow, // #410
2693 PF_te_spark, // #411
2694 PF_te_gunshotquad, // #412
2695 PF_te_spikequad, // #413
2696 PF_te_superspikequad, // #414
2697 PF_te_explosionquad, // #415
2698 PF_te_smallflash, // #416
2699 PF_te_customflash, // #417
2700 PF_te_gunshot, // #418
2701 PF_te_spike, // #419
2702 PF_te_superspike, // #420
2703 PF_te_explosion, // #421
2704 PF_te_tarexplosion, // #422
2705 PF_te_wizspike, // #423
2706 PF_te_knightspike, // #424
2707 PF_te_lavasplash, // #425
2708 PF_te_teleport, // #426
2709 PF_te_explosion2, // #427
2710 PF_te_lightning1, // #428
2711 PF_te_lightning2, // #429
2712 PF_te_lightning3, // #430
2714 PF_vectorvectors, // #432
2715 PF_te_plasmaburn, // #433
2718 builtin_t *pr_builtins = pr_builtin;
2719 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);