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
24 cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
26 mempool_t *pr_strings_mempool;
28 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
29 #define STRINGTEMP_BUFFERS 16
30 #define STRINGTEMP_LENGTH 4096
31 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
32 static int pr_string_tempindex = 0;
34 static char *PR_GetTempString(void)
37 s = pr_string_temp[pr_string_tempindex];
38 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
42 #define RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
43 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
44 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
48 ===============================================================================
52 ===============================================================================
56 void PF_VarString(int first, char *out, int outlength)
62 outend = out + outlength - 1;
63 for (i = first;i < pr_argc && out < outend;i++)
65 s = G_STRING((OFS_PARM0+i*3));
66 while (out < outend && *s)
72 char *ENGINE_EXTENSIONS =
83 "DP_ENT_CUSTOMCOLORMAP "
84 "DP_ENT_EXTERIORMODELTOCLIENT "
86 "DP_ENT_LOWPRECISION "
89 "DP_GFX_EXTERNALTEXTURES "
91 "DP_GFX_QUAKE3MODELTAGS "
95 "DP_HALFLIFE_MAP_CVAR "
99 "DP_MOVETYPEBOUNCEMISSILE "
106 "DP_QC_FINDCHAINFLAGS "
107 "DP_QC_FINDCHAINFLOAT "
110 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
114 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_SINCOSSQRTPOW "
119 "DP_QC_TRACE_MOVETYPE_HITMODEL "
120 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
121 "DP_QC_VECTORVECTORS "
125 "DP_SND_DIRECTIONLESSATTNNONE "
130 "DP_SV_DRAWONLYTOCLIENT "
132 "DP_SV_EXTERIORMODELTOCLIENT "
133 "DP_SV_NODRAWTOCLIENT "
134 "DP_SV_PLAYERPHYSICS "
135 "DP_SV_ROTATINGBMODEL "
141 "DP_TE_EXPLOSIONRGB "
143 "DP_TE_PARTICLECUBE "
144 "DP_TE_PARTICLERAIN "
145 "DP_TE_PARTICLESNOW "
147 "DP_TE_QUADEFFECTS1 "
150 "DP_TE_STANDARDEFFECTBUILTINS "
153 "KRIMZON_SV_PARSECLIENTCOMMAND "
157 "TENEBRAE_GFX_DLIGHTS "
161 qboolean checkextension(char *name)
166 for (e = ENGINE_EXTENSIONS;*e;e++)
173 while (*e && *e != ' ')
175 if (e - start == len)
176 if (!strncasecmp(start, name, len))
186 returns true if the extension is supported by the server
188 checkextension(extensionname)
191 void PF_checkextension (void)
193 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
200 This is a TERMINAL error, which will kill off the entire server.
209 char string[STRINGTEMP_LENGTH];
211 PF_VarString(0, string, sizeof(string));
212 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
213 ed = PROG_TO_EDICT(pr_global_struct->self);
216 PF_ERROR("Program error");
223 Dumps out self, then an error message. The program is aborted and self is
224 removed, but the level can continue.
229 void PF_objerror (void)
232 char string[STRINGTEMP_LENGTH];
234 PF_VarString(0, string, sizeof(string));
235 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
236 ed = PROG_TO_EDICT(pr_global_struct->self);
246 Writes new values for v_forward, v_up, and v_right based on angles
250 void PF_makevectors (void)
252 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
259 Writes new values for v_forward, v_up, and v_right based on the given forward vector
260 vectorvectors(vector, vector)
263 void PF_vectorvectors (void)
265 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
266 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
273 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.
275 setorigin (entity, origin)
278 void PF_setorigin (void)
283 e = G_EDICT(OFS_PARM0);
285 PF_WARNING("setorigin: can not modify world entity\n");
287 PF_WARNING("setorigin: can not modify free entity\n");
288 org = G_VECTOR(OFS_PARM1);
289 VectorCopy (org, e->v->origin);
290 SV_LinkEdict (e, false);
294 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
298 for (i=0 ; i<3 ; i++)
300 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
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);
327 PF_WARNING("setsize: can not modify world entity\n");
329 PF_WARNING("setsize: can not modify free entity\n");
330 min = G_VECTOR(OFS_PARM1);
331 max = G_VECTOR(OFS_PARM2);
332 SetMinMaxSize (e, min, max, false);
340 setmodel(entity, model)
343 void PF_setmodel (void)
350 e = G_EDICT(OFS_PARM0);
352 PF_WARNING("setmodel: can not modify world entity\n");
354 PF_WARNING("setmodel: can not modify free entity\n");
355 m = G_STRING(OFS_PARM1);
357 // check to see if model was properly precached
358 for (i=0, check = sv.model_precache ; *check ; i++, check++)
359 if (!strcmp(*check, m))
363 PF_WARNING("setmodel: no precache\n");
366 e->v->model = PR_SetString(*check);
367 e->v->modelindex = i;
369 mod = sv.models[ (int)e->v->modelindex];
372 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
374 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
381 broadcast print to everyone on server
386 void PF_bprint (void)
388 char string[STRINGTEMP_LENGTH];
389 PF_VarString(0, string, sizeof(string));
390 SV_BroadcastPrint(string);
397 single print to a specific client
399 sprint(clientent, value)
402 void PF_sprint (void)
406 char string[STRINGTEMP_LENGTH];
408 entnum = G_EDICTNUM(OFS_PARM0);
410 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
412 Con_Print("tried to sprint to a non-client\n");
416 client = svs.clients + entnum-1;
417 if (!client->netconnection)
419 PF_VarString(1, string, sizeof(string));
420 MSG_WriteChar(&client->message,svc_print);
421 MSG_WriteString(&client->message, string);
429 single print to a specific client
431 centerprint(clientent, value)
434 void PF_centerprint (void)
438 char string[STRINGTEMP_LENGTH];
440 entnum = G_EDICTNUM(OFS_PARM0);
442 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
444 Con_Print("tried to sprint to a non-client\n");
448 client = svs.clients + entnum-1;
449 if (!client->netconnection)
451 PF_VarString(1, string, sizeof(string));
452 MSG_WriteChar(&client->message,svc_centerprint);
453 MSG_WriteString(&client->message, string);
461 vector normalize(vector)
464 void PF_normalize (void)
470 value1 = G_VECTOR(OFS_PARM0);
472 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
476 newvalue[0] = newvalue[1] = newvalue[2] = 0;
480 newvalue[0] = value1[0] * new;
481 newvalue[1] = value1[1] * new;
482 newvalue[2] = value1[2] * new;
485 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
500 value1 = G_VECTOR(OFS_PARM0);
502 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
505 G_FLOAT(OFS_RETURN) = new;
512 float vectoyaw(vector)
515 void PF_vectoyaw (void)
520 value1 = G_VECTOR(OFS_PARM0);
522 if (value1[1] == 0 && value1[0] == 0)
526 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
531 G_FLOAT(OFS_RETURN) = yaw;
539 vector vectoangles(vector)
542 void PF_vectoangles (void)
544 double value1[3], forward, yaw, pitch;
546 VectorCopy(G_VECTOR(OFS_PARM0), value1);
548 if (value1[1] == 0 && value1[0] == 0)
558 // LordHavoc: optimized a bit
561 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
565 else if (value1[1] > 0)
570 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
571 pitch = (atan2(value1[2], forward) * 180 / M_PI);
576 VectorSet(G_VECTOR(OFS_RETURN), pitch, yaw, 0);
583 Returns a number from 0<= num < 1
588 void PF_random (void)
592 num = (rand ()&0x7fff) / ((float)0x7fff);
594 G_FLOAT(OFS_RETURN) = num;
601 particle(origin, color, count)
604 void PF_particle (void)
610 org = G_VECTOR(OFS_PARM0);
611 dir = G_VECTOR(OFS_PARM1);
612 color = G_FLOAT(OFS_PARM2);
613 count = G_FLOAT(OFS_PARM3);
614 SV_StartParticle (org, dir, color, count);
624 void PF_ambientsound (void)
629 float vol, attenuation;
632 pos = G_VECTOR (OFS_PARM0);
633 samp = G_STRING(OFS_PARM1);
634 vol = G_FLOAT(OFS_PARM2);
635 attenuation = G_FLOAT(OFS_PARM3);
637 // check to see if samp was properly precached
638 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
639 if (!strcmp(*check,samp))
644 Con_Printf("no precache: %s\n", samp);
652 // add an svc_spawnambient command to the level signon packet
655 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
657 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
659 MSG_WriteVector(&sv.signon, pos, sv.protocol);
662 MSG_WriteShort (&sv.signon, soundnum);
664 MSG_WriteByte (&sv.signon, soundnum);
666 MSG_WriteByte (&sv.signon, vol*255);
667 MSG_WriteByte (&sv.signon, attenuation*64);
675 Each entity can have eight independant sound sources, like voice,
678 Channel 0 is an auto-allocate channel, the others override anything
679 already running on that entity/channel pair.
681 An attenuation of 0 will play full volume everywhere in the level.
682 Larger attenuations will drop off.
694 entity = G_EDICT(OFS_PARM0);
695 channel = G_FLOAT(OFS_PARM1);
696 sample = G_STRING(OFS_PARM2);
697 volume = G_FLOAT(OFS_PARM3) * 255;
698 attenuation = G_FLOAT(OFS_PARM4);
700 if (volume < 0 || volume > 255)
701 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
703 if (attenuation < 0 || attenuation > 4)
704 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
706 if (channel < 0 || channel > 7)
707 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
709 SV_StartSound (entity, channel, sample, volume, attenuation);
721 PF_ERROR("break: break statement\n");
728 Used for use tracing and shot targeting
729 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
730 if the tryents flag is set.
732 traceline (vector1, vector2, tryents)
735 void PF_traceline (void)
742 pr_xfunction->builtinsprofile += 30;
744 v1 = G_VECTOR(OFS_PARM0);
745 v2 = G_VECTOR(OFS_PARM1);
746 move = G_FLOAT(OFS_PARM2);
747 ent = G_EDICT(OFS_PARM3);
749 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
751 pr_global_struct->trace_allsolid = trace.allsolid;
752 pr_global_struct->trace_startsolid = trace.startsolid;
753 pr_global_struct->trace_fraction = trace.fraction;
754 pr_global_struct->trace_inwater = trace.inwater;
755 pr_global_struct->trace_inopen = trace.inopen;
756 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
757 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
758 pr_global_struct->trace_plane_dist = trace.plane.dist;
760 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
762 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
763 // FIXME: add trace_endcontents
771 Used for use tracing and shot targeting
772 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
773 if the tryents flag is set.
775 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
778 // LordHavoc: added this for my own use, VERY useful, similar to traceline
779 void PF_tracebox (void)
781 float *v1, *v2, *m1, *m2;
786 pr_xfunction->builtinsprofile += 30;
788 v1 = G_VECTOR(OFS_PARM0);
789 m1 = G_VECTOR(OFS_PARM1);
790 m2 = G_VECTOR(OFS_PARM2);
791 v2 = G_VECTOR(OFS_PARM3);
792 move = G_FLOAT(OFS_PARM4);
793 ent = G_EDICT(OFS_PARM5);
795 trace = SV_Move (v1, m1, m2, v2, move, ent);
797 pr_global_struct->trace_allsolid = trace.allsolid;
798 pr_global_struct->trace_startsolid = trace.startsolid;
799 pr_global_struct->trace_fraction = trace.fraction;
800 pr_global_struct->trace_inwater = trace.inwater;
801 pr_global_struct->trace_inopen = trace.inopen;
802 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
803 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
804 pr_global_struct->trace_plane_dist = trace.plane.dist;
806 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
808 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
811 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
812 void PF_TraceToss (void)
818 pr_xfunction->builtinsprofile += 600;
820 ent = G_EDICT(OFS_PARM0);
821 if (ent == sv.edicts)
822 PF_WARNING("tracetoss: can not use world entity\n");
823 ignore = G_EDICT(OFS_PARM1);
825 trace = SV_Trace_Toss (ent, ignore);
827 pr_global_struct->trace_allsolid = trace.allsolid;
828 pr_global_struct->trace_startsolid = trace.startsolid;
829 pr_global_struct->trace_fraction = trace.fraction;
830 pr_global_struct->trace_inwater = trace.inwater;
831 pr_global_struct->trace_inopen = trace.inopen;
832 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
833 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
834 pr_global_struct->trace_plane_dist = trace.plane.dist;
836 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
838 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
846 Returns true if the given entity can move to the given position from it's
847 current position by walking or rolling.
849 scalar checkpos (entity, vector)
852 void PF_checkpos (void)
856 //============================================================================
859 qbyte checkpvs[MAX_MAP_LEAFS/8];
861 int PF_newcheckclient (int check)
867 // cycle to the next one
869 check = bound(1, check, svs.maxclients);
870 if (check == svs.maxclients)
878 pr_xfunction->builtinsprofile++;
880 if (i == svs.maxclients+1)
882 // look up the client's edict
884 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
885 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
887 // found a valid client (possibly the same one again)
891 // get the PVS for the entity
892 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
894 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
895 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
904 Returns a client (or object that has a client enemy) that would be a
907 If there is more than one valid option, they are cycled each frame
909 If (self.origin + self.viewofs) is not in the PVS of the current target,
910 it is not returned at all.
915 int c_invis, c_notvis;
916 void PF_checkclient (void)
921 // find a new check if on a new frame
922 if (sv.time - sv.lastchecktime >= 0.1)
924 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
925 sv.lastchecktime = sv.time;
928 // return check if it might be visible
929 ent = EDICT_NUM(sv.lastcheck);
930 if (ent->e->free || ent->v->health <= 0)
932 RETURN_EDICT(sv.edicts);
936 // if current entity can't possibly see the check entity, return 0
937 self = PROG_TO_EDICT(pr_global_struct->self);
938 VectorAdd(self->v->origin, self->v->view_ofs, view);
939 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
942 RETURN_EDICT(sv.edicts);
946 // might be able to see it
951 //============================================================================
958 Sends text over to the client's execution buffer
960 stuffcmd (clientent, value)
963 void PF_stuffcmd (void)
969 entnum = G_EDICTNUM(OFS_PARM0);
970 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
972 Con_Print("Can't stuffcmd to a non-client\n");
975 str = G_STRING(OFS_PARM1);
978 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
979 Host_ClientCommands ("%s", str);
987 Sends text to server console
992 void PF_localcmd (void)
994 Cbuf_AddText(G_STRING(OFS_PARM0));
1006 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1016 void PF_cvar_set (void)
1018 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1025 Returns a chain of entities that have origins within a spherical area
1027 findradius (origin, radius)
1030 void PF_findradius (void)
1032 edict_t *ent, *chain;
1039 chain = (edict_t *)sv.edicts;
1041 org = G_VECTOR(OFS_PARM0);
1042 radius = G_FLOAT(OFS_PARM1);
1043 radius2 = radius * radius;
1045 ent = NEXT_EDICT(sv.edicts);
1046 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1048 pr_xfunction->builtinsprofile++;
1051 if (ent->v->solid == SOLID_NOT)
1054 // LordHavoc: compare against bounding box rather than center,
1055 // and use DotProduct instead of Length, major speedup
1056 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1057 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1058 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1059 if (DotProduct(eorg, eorg) > radius2)
1062 ent->v->chain = EDICT_TO_PROG(chain);
1066 RETURN_EDICT(chain);
1075 void PF_dprint (void)
1077 char string[STRINGTEMP_LENGTH];
1078 if (developer.integer)
1080 PF_VarString(0, string, sizeof(string));
1089 v = G_FLOAT(OFS_PARM0);
1091 s = PR_GetTempString();
1092 if ((float)((int)v) == v)
1093 sprintf(s, "%i", (int)v);
1095 sprintf(s, "%f", v);
1096 G_INT(OFS_RETURN) = PR_SetString(s);
1102 v = G_FLOAT(OFS_PARM0);
1103 G_FLOAT(OFS_RETURN) = fabs(v);
1109 s = PR_GetTempString();
1110 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1111 G_INT(OFS_RETURN) = PR_SetString(s);
1117 s = PR_GetTempString();
1118 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1119 G_INT(OFS_RETURN) = PR_SetString(s);
1122 void PF_Spawn (void)
1125 pr_xfunction->builtinsprofile += 20;
1130 void PF_Remove (void)
1133 pr_xfunction->builtinsprofile += 20;
1135 ed = G_EDICT(OFS_PARM0);
1136 if (ed == sv.edicts)
1137 PF_WARNING("remove: tried to remove world\n");
1138 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1139 PF_WARNING("remove: tried to remove a client\n");
1140 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1141 if (ed->e->free && developer.integer)
1142 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1147 // entity (entity start, .string field, string match) find = #5;
1155 e = G_EDICTNUM(OFS_PARM0);
1156 f = G_INT(OFS_PARM1);
1157 s = G_STRING(OFS_PARM2);
1160 RETURN_EDICT(sv.edicts);
1164 for (e++ ; e < sv.num_edicts ; e++)
1166 pr_xfunction->builtinsprofile++;
1180 RETURN_EDICT(sv.edicts);
1183 // LordHavoc: added this for searching float, int, and entity reference fields
1184 void PF_FindFloat (void)
1191 e = G_EDICTNUM(OFS_PARM0);
1192 f = G_INT(OFS_PARM1);
1193 s = G_FLOAT(OFS_PARM2);
1195 for (e++ ; e < sv.num_edicts ; e++)
1197 pr_xfunction->builtinsprofile++;
1201 if (E_FLOAT(ed,f) == s)
1208 RETURN_EDICT(sv.edicts);
1211 // chained search for strings in entity fields
1212 // entity(.string field, string match) findchain = #402;
1213 void PF_findchain (void)
1218 edict_t *ent, *chain;
1220 chain = (edict_t *)sv.edicts;
1222 f = G_INT(OFS_PARM0);
1223 s = G_STRING(OFS_PARM1);
1226 RETURN_EDICT(sv.edicts);
1230 ent = NEXT_EDICT(sv.edicts);
1231 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1233 pr_xfunction->builtinsprofile++;
1236 t = E_STRING(ent,f);
1242 ent->v->chain = EDICT_TO_PROG(chain);
1246 RETURN_EDICT(chain);
1249 // LordHavoc: chained search for float, int, and entity reference fields
1250 // entity(.string field, float match) findchainfloat = #403;
1251 void PF_findchainfloat (void)
1256 edict_t *ent, *chain;
1258 chain = (edict_t *)sv.edicts;
1260 f = G_INT(OFS_PARM0);
1261 s = G_FLOAT(OFS_PARM1);
1263 ent = NEXT_EDICT(sv.edicts);
1264 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1266 pr_xfunction->builtinsprofile++;
1269 if (E_FLOAT(ent,f) != s)
1272 ent->v->chain = EDICT_TO_PROG(chain);
1276 RETURN_EDICT(chain);
1279 // LordHavoc: search for flags in float fields
1280 void PF_findflags (void)
1287 e = G_EDICTNUM(OFS_PARM0);
1288 f = G_INT(OFS_PARM1);
1289 s = (int)G_FLOAT(OFS_PARM2);
1291 for (e++ ; e < sv.num_edicts ; e++)
1293 pr_xfunction->builtinsprofile++;
1297 if ((int)E_FLOAT(ed,f) & s)
1304 RETURN_EDICT(sv.edicts);
1307 // LordHavoc: chained search for flags in float fields
1308 void PF_findchainflags (void)
1313 edict_t *ent, *chain;
1315 chain = (edict_t *)sv.edicts;
1317 f = G_INT(OFS_PARM0);
1318 s = (int)G_FLOAT(OFS_PARM1);
1320 ent = NEXT_EDICT(sv.edicts);
1321 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1323 pr_xfunction->builtinsprofile++;
1326 if (!((int)E_FLOAT(ent,f) & s))
1329 ent->v->chain = EDICT_TO_PROG(chain);
1333 RETURN_EDICT(chain);
1336 void PR_CheckEmptyString (char *s)
1339 PF_ERROR("Bad string");
1342 void PF_precache_file (void)
1343 { // precache_file is only used to copy files with qcc, it does nothing
1344 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1347 void PF_precache_sound (void)
1351 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1353 if (sv.state != ss_loading)
1354 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1356 s = G_STRING(OFS_PARM0);
1357 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1358 PR_CheckEmptyString (s);
1360 for (i=0 ; i<limit ; i++)
1362 if (!sv.sound_precache[i])
1364 sv.sound_precache[i] = s;
1367 if (!strcmp(sv.sound_precache[i], s))
1370 PF_ERROR("PF_precache_sound: overflow");
1373 void PF_precache_model (void)
1377 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1379 if (sv.state != ss_loading)
1380 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1382 s = G_STRING(OFS_PARM0);
1383 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1385 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1386 PR_CheckEmptyString (s);
1388 for (i = 0;i < limit;i++)
1390 if (!sv.model_precache[i])
1392 sv.model_precache[i] = s;
1393 sv.models[i] = Mod_ForName (s, true, false, false);
1396 if (!strcmp(sv.model_precache[i], s))
1399 PF_ERROR("PF_precache_model: overflow");
1403 void PF_coredump (void)
1408 void PF_traceon (void)
1413 void PF_traceoff (void)
1418 void PF_eprint (void)
1420 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1427 float(float yaw, float dist) walkmove
1430 void PF_walkmove (void)
1438 // assume failure if it returns early
1439 G_FLOAT(OFS_RETURN) = 0;
1441 ent = PROG_TO_EDICT(pr_global_struct->self);
1442 if (ent == sv.edicts)
1443 PF_WARNING("walkmove: can not modify world entity\n");
1445 PF_WARNING("walkmove: can not modify free entity\n");
1446 yaw = G_FLOAT(OFS_PARM0);
1447 dist = G_FLOAT(OFS_PARM1);
1449 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1452 yaw = yaw*M_PI*2 / 360;
1454 move[0] = cos(yaw)*dist;
1455 move[1] = sin(yaw)*dist;
1458 // save program state, because SV_movestep may call other progs
1459 oldf = pr_xfunction;
1460 oldself = pr_global_struct->self;
1462 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1465 // restore program state
1466 pr_xfunction = oldf;
1467 pr_global_struct->self = oldself;
1477 void PF_droptofloor (void)
1483 // assume failure if it returns early
1484 G_FLOAT(OFS_RETURN) = 0;
1486 ent = PROG_TO_EDICT(pr_global_struct->self);
1487 if (ent == sv.edicts)
1488 PF_WARNING("droptofloor: can not modify world entity\n");
1490 PF_WARNING("droptofloor: can not modify free entity\n");
1492 VectorCopy (ent->v->origin, end);
1495 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1497 if (trace.fraction != 1)
1499 VectorCopy (trace.endpos, ent->v->origin);
1500 SV_LinkEdict (ent, false);
1501 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1502 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1503 G_FLOAT(OFS_RETURN) = 1;
1504 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1505 ent->e->suspendedinairflag = true;
1513 void(float style, string value) lightstyle
1516 void PF_lightstyle (void)
1523 style = G_FLOAT(OFS_PARM0);
1524 val = G_STRING(OFS_PARM1);
1526 // change the string in sv
1527 sv.lightstyles[style] = val;
1529 // send message to all clients on this server
1530 if (sv.state != ss_active)
1533 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1535 if (client->netconnection)
1537 MSG_WriteChar (&client->message, svc_lightstyle);
1538 MSG_WriteChar (&client->message,style);
1539 MSG_WriteString (&client->message, val);
1547 f = G_FLOAT(OFS_PARM0);
1549 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1551 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1553 void PF_floor (void)
1555 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1559 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1568 void PF_checkbottom (void)
1570 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1578 void PF_pointcontents (void)
1580 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1587 entity nextent(entity)
1590 void PF_nextent (void)
1595 i = G_EDICTNUM(OFS_PARM0);
1598 pr_xfunction->builtinsprofile++;
1600 if (i == sv.num_edicts)
1602 RETURN_EDICT(sv.edicts);
1618 Pick a vector for the player to shoot along
1619 vector aim(entity, missilespeed)
1624 edict_t *ent, *check, *bestent;
1625 vec3_t start, dir, end, bestdir;
1628 float dist, bestdist;
1631 // assume failure if it returns early
1632 VectorClear(G_VECTOR(OFS_RETURN));
1634 ent = G_EDICT(OFS_PARM0);
1635 if (ent == sv.edicts)
1636 PF_WARNING("aim: can not use world entity\n");
1638 PF_WARNING("aim: can not use free entity\n");
1639 speed = G_FLOAT(OFS_PARM1);
1641 VectorCopy (ent->v->origin, start);
1644 // try sending a trace straight
1645 VectorCopy (pr_global_struct->v_forward, dir);
1646 VectorMA (start, 2048, dir, end);
1647 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1648 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1649 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1651 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1656 // try all possible entities
1657 VectorCopy (dir, bestdir);
1658 bestdist = sv_aim.value;
1661 check = NEXT_EDICT(sv.edicts);
1662 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1664 pr_xfunction->builtinsprofile++;
1665 if (check->v->takedamage != DAMAGE_AIM)
1669 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1670 continue; // don't aim at teammate
1671 for (j=0 ; j<3 ; j++)
1672 end[j] = check->v->origin[j]
1673 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1674 VectorSubtract (end, start, dir);
1675 VectorNormalize (dir);
1676 dist = DotProduct (dir, pr_global_struct->v_forward);
1677 if (dist < bestdist)
1678 continue; // to far to turn
1679 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1680 if (tr.ent == check)
1681 { // can shoot at this one
1689 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1690 dist = DotProduct (dir, pr_global_struct->v_forward);
1691 VectorScale (pr_global_struct->v_forward, dist, end);
1693 VectorNormalize (end);
1694 VectorCopy (end, G_VECTOR(OFS_RETURN));
1698 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1706 This was a major timewaster in progs, so it was converted to C
1709 void PF_changeyaw (void)
1712 float ideal, current, move, speed;
1714 ent = PROG_TO_EDICT(pr_global_struct->self);
1715 if (ent == sv.edicts)
1716 PF_WARNING("changeyaw: can not modify world entity\n");
1718 PF_WARNING("changeyaw: can not modify free entity\n");
1719 current = ANGLEMOD(ent->v->angles[1]);
1720 ideal = ent->v->ideal_yaw;
1721 speed = ent->v->yaw_speed;
1723 if (current == ideal)
1725 move = ideal - current;
1726 if (ideal > current)
1747 ent->v->angles[1] = ANGLEMOD (current + move);
1755 void PF_changepitch (void)
1758 float ideal, current, move, speed;
1761 ent = G_EDICT(OFS_PARM0);
1762 if (ent == sv.edicts)
1763 PF_WARNING("changepitch: can not modify world entity\n");
1765 PF_WARNING("changepitch: can not modify free entity\n");
1766 current = ANGLEMOD( ent->v->angles[0] );
1767 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1768 ideal = val->_float;
1771 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1774 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1775 speed = val->_float;
1778 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1782 if (current == ideal)
1784 move = ideal - current;
1785 if (ideal > current)
1806 ent->v->angles[0] = ANGLEMOD (current + move);
1810 ===============================================================================
1814 ===============================================================================
1817 #define MSG_BROADCAST 0 // unreliable to all
1818 #define MSG_ONE 1 // reliable to one (msg_entity)
1819 #define MSG_ALL 2 // reliable to all
1820 #define MSG_INIT 3 // write to the init string
1822 sizebuf_t *WriteDest (void)
1828 dest = G_FLOAT(OFS_PARM0);
1832 return &sv.datagram;
1835 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1836 entnum = NUM_FOR_EDICT(ent);
1837 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1838 Host_Error("WriteDest: tried to write to non-client\n");
1839 return &svs.clients[entnum-1].message;
1842 return &sv.reliable_datagram;
1848 Host_Error("WriteDest: bad destination");
1855 void PF_WriteByte (void)
1857 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1860 void PF_WriteChar (void)
1862 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1865 void PF_WriteShort (void)
1867 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1870 void PF_WriteLong (void)
1872 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1875 void PF_WriteAngle (void)
1877 if (sv.protocol == PROTOCOL_DARKPLACES5)
1878 MSG_WriteAngle16i (WriteDest(), G_FLOAT(OFS_PARM1));
1880 MSG_WriteAngle8i (WriteDest(), G_FLOAT(OFS_PARM1));
1883 void PF_WriteCoord (void)
1885 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1888 void PF_WriteString (void)
1890 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1894 void PF_WriteEntity (void)
1896 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1899 //=============================================================================
1901 void PF_makestatic (void)
1906 ent = G_EDICT(OFS_PARM0);
1907 if (ent == sv.edicts)
1908 PF_WARNING("makestatic: can not modify world entity\n");
1910 PF_WARNING("makestatic: can not modify free entity\n");
1913 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1918 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1919 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1920 MSG_WriteShort (&sv.signon, ent->v->frame);
1924 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1925 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1926 MSG_WriteByte (&sv.signon, ent->v->frame);
1929 MSG_WriteByte (&sv.signon, ent->v->colormap);
1930 MSG_WriteByte (&sv.signon, ent->v->skin);
1931 for (i=0 ; i<3 ; i++)
1933 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1934 MSG_WriteAngle8i(&sv.signon, ent->v->angles[i]);
1937 // throw the entity away now
1941 //=============================================================================
1948 void PF_setspawnparms (void)
1954 ent = G_EDICT(OFS_PARM0);
1955 i = NUM_FOR_EDICT(ent);
1956 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1958 Con_Print("tried to setspawnparms on a non-client\n");
1962 // copy spawn parms out of the client_t
1963 client = svs.clients + i-1;
1964 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1965 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1973 void PF_changelevel (void)
1977 // make sure we don't issue two changelevels
1978 if (svs.changelevel_issued)
1980 svs.changelevel_issued = true;
1982 s = G_STRING(OFS_PARM0);
1983 Cbuf_AddText (va("changelevel %s\n",s));
1988 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1993 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1998 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2005 Returns a vector of length < 1
2010 void PF_randomvec (void)
2015 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2016 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2017 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2019 while (DotProduct(temp, temp) >= 1);
2020 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2027 Returns a color vector indicating the lighting at the requested point.
2029 (Internal Operation note: actually measures the light beneath the point, just like
2030 the model lighting on the client)
2035 void PF_GetLight (void)
2037 vec3_t ambientcolor, diffusecolor, diffusenormal;
2039 p = G_VECTOR(OFS_PARM0);
2040 VectorClear(ambientcolor);
2041 VectorClear(diffusecolor);
2042 VectorClear(diffusenormal);
2043 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2044 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2045 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2048 void PF_registercvar (void)
2051 name = G_STRING(OFS_PARM0);
2052 value = G_STRING(OFS_PARM1);
2053 G_FLOAT(OFS_RETURN) = 0;
2055 // first check to see if it has already been defined
2056 if (Cvar_FindVar (name))
2059 // check for overlap with a command
2060 if (Cmd_Exists (name))
2062 Con_Printf("PF_registercvar: %s is a command\n", name);
2066 Cvar_Get(name, value, 0);
2068 G_FLOAT(OFS_RETURN) = 1; // success
2075 returns the minimum of two supplied floats
2082 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2084 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2085 else if (pr_argc >= 3)
2088 float f = G_FLOAT(OFS_PARM0);
2089 for (i = 1;i < pr_argc;i++)
2090 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2091 f = G_FLOAT((OFS_PARM0+i*3));
2092 G_FLOAT(OFS_RETURN) = f;
2096 G_FLOAT(OFS_RETURN) = 0;
2097 PF_WARNING("min: must supply at least 2 floats\n");
2105 returns the maximum of two supplied floats
2112 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2114 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2115 else if (pr_argc >= 3)
2118 float f = G_FLOAT(OFS_PARM0);
2119 for (i = 1;i < pr_argc;i++)
2120 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2121 f = G_FLOAT((OFS_PARM0+i*3));
2122 G_FLOAT(OFS_RETURN) = f;
2126 G_FLOAT(OFS_RETURN) = 0;
2127 PF_WARNING("max: must supply at least 2 floats\n");
2135 returns number bounded by supplied range
2137 min(min, value, max)
2140 void PF_bound (void)
2142 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2149 returns a raised to power b
2156 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2163 copies data from one entity to another
2165 copyentity(src, dst)
2168 void PF_copyentity (void)
2171 in = G_EDICT(OFS_PARM0);
2172 if (in == sv.edicts)
2173 PF_WARNING("copyentity: can not read world entity\n");
2175 PF_WARNING("copyentity: can not read free entity\n");
2176 out = G_EDICT(OFS_PARM1);
2177 if (out == sv.edicts)
2178 PF_WARNING("copyentity: can not modify world entity\n");
2180 PF_WARNING("copyentity: can not modify free entity\n");
2181 memcpy(out->v, in->v, progs->entityfields * 4);
2188 sets the color of a client and broadcasts the update to all connected clients
2190 setcolor(clientent, value)
2193 void PF_setcolor (void)
2199 entnum = G_EDICTNUM(OFS_PARM0);
2200 i = G_FLOAT(OFS_PARM1);
2202 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2204 Con_Print("tried to setcolor a non-client\n");
2208 client = svs.clients + entnum-1;
2209 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2212 client->old_colors = i;
2213 client->edict->v->team = (i & 15) + 1;
2215 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2216 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2217 MSG_WriteByte (&sv.reliable_datagram, i);
2224 effect(origin, modelname, startframe, framecount, framerate)
2227 void PF_effect (void)
2231 s = G_STRING(OFS_PARM1);
2233 PF_WARNING("effect: no model specified\n");
2235 i = SV_ModelIndex(s);
2237 PF_WARNING("effect: model not precached\n");
2238 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2241 void PF_te_blood (void)
2243 if (G_FLOAT(OFS_PARM2) < 1)
2245 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2246 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2248 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2252 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2253 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2254 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2256 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2259 void PF_te_bloodshower (void)
2261 if (G_FLOAT(OFS_PARM3) < 1)
2263 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2264 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2266 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2274 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2276 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2279 void PF_te_explosionrgb (void)
2281 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2282 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2284 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2288 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2289 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2290 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2293 void PF_te_particlecube (void)
2295 if (G_FLOAT(OFS_PARM3) < 1)
2297 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2298 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2300 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2312 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2314 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2315 // gravity true/false
2316 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2318 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2321 void PF_te_particlerain (void)
2323 if (G_FLOAT(OFS_PARM3) < 1)
2325 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2326 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2328 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2333 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2334 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2337 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2340 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2342 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2345 void PF_te_particlesnow (void)
2347 if (G_FLOAT(OFS_PARM3) < 1)
2349 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2350 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2352 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2354 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2357 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2358 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2360 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2361 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2362 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2364 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2366 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2369 void PF_te_spark (void)
2371 if (G_FLOAT(OFS_PARM2) < 1)
2373 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2374 MSG_WriteByte(&sv.datagram, TE_SPARK);
2376 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2377 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2378 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2380 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2381 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2382 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2384 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2387 void PF_te_gunshotquad (void)
2389 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2390 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2392 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2393 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2394 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2397 void PF_te_spikequad (void)
2399 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2400 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2402 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2403 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2404 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2407 void PF_te_superspikequad (void)
2409 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2410 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2412 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2413 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2414 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2417 void PF_te_explosionquad (void)
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2422 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2423 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2424 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2427 void PF_te_smallflash (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2432 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2433 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2434 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2437 void PF_te_customflash (void)
2439 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2441 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2442 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2444 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2445 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2446 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2448 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2450 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2452 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2453 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2454 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2457 void PF_te_gunshot (void)
2459 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2460 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2462 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2463 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2464 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2467 void PF_te_spike (void)
2469 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2470 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2472 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2473 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2474 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2477 void PF_te_superspike (void)
2479 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2480 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2482 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2483 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2484 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2487 void PF_te_explosion (void)
2489 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2490 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2492 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2493 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2494 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2497 void PF_te_tarexplosion (void)
2499 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2500 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2502 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2503 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2504 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2507 void PF_te_wizspike (void)
2509 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2510 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2512 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2513 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2514 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2517 void PF_te_knightspike (void)
2519 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2520 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2522 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2523 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2524 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2527 void PF_te_lavasplash (void)
2529 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2530 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2532 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2533 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2534 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2537 void PF_te_teleport (void)
2539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2540 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2542 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2543 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2544 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2547 void PF_te_explosion2 (void)
2549 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2550 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2552 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2553 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2554 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2556 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2557 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2560 void PF_te_lightning1 (void)
2562 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2563 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2565 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2567 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2568 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2569 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2571 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2572 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2573 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2576 void PF_te_lightning2 (void)
2578 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2579 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2581 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2583 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2584 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2585 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2587 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2588 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2589 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2592 void PF_te_lightning3 (void)
2594 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2595 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2597 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2599 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2600 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2601 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2603 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2604 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2605 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2608 void PF_te_beam (void)
2610 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2611 MSG_WriteByte(&sv.datagram, TE_BEAM);
2613 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2615 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2616 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2617 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2619 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2620 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2621 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2624 void PF_te_plasmaburn (void)
2626 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2627 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2628 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2629 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2630 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2633 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2636 vec3_t v1, clipplanenormal, normal;
2637 vec_t clipplanedist, clipdist;
2639 if (surf->flags & SURF_PLANEBACK)
2640 VectorNegate(surf->plane->normal, normal);
2642 VectorCopy(surf->plane->normal, normal);
2643 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2645 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2646 VectorNormalizeFast(v1);
2647 CrossProduct(v1, normal, clipplanenormal);
2648 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2649 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2652 clipdist = -clipdist;
2653 VectorMA(out, clipdist, clipplanenormal, out);
2658 static msurface_t *getsurface(edict_t *ed, int surfnum)
2662 if (!ed || ed->e->free)
2664 modelindex = ed->v->modelindex;
2665 if (modelindex < 1 || modelindex >= MAX_MODELS)
2667 model = sv.models[modelindex];
2668 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2670 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2674 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2675 void PF_getsurfacenumpoints(void)
2678 // return 0 if no such surface
2679 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2681 G_FLOAT(OFS_RETURN) = 0;
2685 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2687 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2688 void PF_getsurfacepoint(void)
2693 VectorClear(G_VECTOR(OFS_RETURN));
2694 ed = G_EDICT(OFS_PARM0);
2695 if (!ed || ed->e->free)
2697 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2699 pointnum = G_FLOAT(OFS_PARM2);
2700 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2702 // FIXME: implement rotation/scaling
2703 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2705 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2706 void PF_getsurfacenormal(void)
2709 VectorClear(G_VECTOR(OFS_RETURN));
2710 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2712 // FIXME: implement rotation/scaling
2713 if (surf->flags & SURF_PLANEBACK)
2714 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2716 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2718 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2719 void PF_getsurfacetexture(void)
2722 G_INT(OFS_RETURN) = 0;
2723 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2725 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2727 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2728 void PF_getsurfacenearpoint(void)
2730 int surfnum, best, modelindex;
2732 vec_t dist, bestdist;
2737 G_FLOAT(OFS_RETURN) = -1;
2738 ed = G_EDICT(OFS_PARM0);
2739 point = G_VECTOR(OFS_PARM1);
2741 if (!ed || ed->e->free)
2743 modelindex = ed->v->modelindex;
2744 if (modelindex < 1 || modelindex >= MAX_MODELS)
2746 model = sv.models[modelindex];
2747 if (!model->brushq1.numsurfaces)
2750 // FIXME: implement rotation/scaling
2751 VectorSubtract(point, ed->v->origin, p);
2753 bestdist = 1000000000;
2754 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2756 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2757 dist = PlaneDiff(p, surf->plane);
2759 if (dist < bestdist)
2761 clippointtosurface(surf, p, clipped);
2762 VectorSubtract(clipped, p, clipped);
2763 dist += DotProduct(clipped, clipped);
2764 if (dist < bestdist)
2771 G_FLOAT(OFS_RETURN) = best;
2773 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2774 void PF_getsurfaceclippedpoint(void)
2779 VectorClear(G_VECTOR(OFS_RETURN));
2780 ed = G_EDICT(OFS_PARM0);
2781 if (!ed || ed->e->free)
2783 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2785 // FIXME: implement rotation/scaling
2786 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2787 clippointtosurface(surf, p, out);
2788 // FIXME: implement rotation/scaling
2789 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2792 #define MAX_PRFILES 256
2794 qfile_t *pr_files[MAX_PRFILES];
2796 void PR_Files_Init(void)
2798 memset(pr_files, 0, sizeof(pr_files));
2801 void PR_Files_CloseAll(void)
2804 for (i = 0;i < MAX_PRFILES;i++)
2807 FS_Close(pr_files[i]);
2812 //float(string s) stof = #81; // get numerical value from a string
2815 char string[STRINGTEMP_LENGTH];
2816 PF_VarString(0, string, sizeof(string));
2817 G_FLOAT(OFS_RETURN) = atof(string);
2820 //float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
2823 int filenum, mode, i;
2824 char *modestring, *filename;
2825 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2826 if (pr_files[filenum] == NULL)
2828 if (filenum >= MAX_PRFILES)
2830 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2831 G_FLOAT(OFS_RETURN) = -2;
2834 mode = G_FLOAT(OFS_PARM1);
2837 case 0: // FILE_READ
2840 case 1: // FILE_APPEND
2843 case 2: // FILE_WRITE
2847 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2848 G_FLOAT(OFS_RETURN) = -3;
2851 filename = G_STRING(OFS_PARM0);
2852 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2853 // ../ is parent directory on many platforms
2854 // // is parent directory on Amiga
2855 // / at the beginning of a path is root on unix, and parent directory on Amiga
2856 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2857 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2858 for (i = 0;filename[i];i++)
2860 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2862 Con_Printf("PF_fopen: dangerous/confusing/annoying/non-portable filename \"%s\" not allowed. (contains control characters or // or .. or : or \\ or begins with /)\n", filename);
2863 G_FLOAT(OFS_RETURN) = -4;
2867 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2869 if (pr_files[filenum] == NULL && modestring == "rb")
2870 pr_files[filenum] = FS_Open(filename, modestring, false);
2872 if (pr_files[filenum] == NULL)
2873 G_FLOAT(OFS_RETURN) = -1;
2875 G_FLOAT(OFS_RETURN) = filenum;
2878 //void(float fhandle) fclose = #111; // closes a file
2879 void PF_fclose(void)
2881 int filenum = G_FLOAT(OFS_PARM0);
2882 if (filenum < 0 || filenum >= MAX_PRFILES)
2884 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2887 if (pr_files[filenum] == NULL)
2889 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2892 FS_Close(pr_files[filenum]);
2893 pr_files[filenum] = NULL;
2896 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2900 static char string[STRINGTEMP_LENGTH];
2901 int filenum = G_FLOAT(OFS_PARM0);
2902 if (filenum < 0 || filenum >= MAX_PRFILES)
2904 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2907 if (pr_files[filenum] == NULL)
2909 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2915 c = FS_Getc(pr_files[filenum]);
2916 if (c == '\r' || c == '\n' || c < 0)
2918 if (end < STRINGTEMP_LENGTH - 1)
2922 // remove \n following \r
2924 c = FS_Getc(pr_files[filenum]);
2925 if (developer.integer)
2926 Con_Printf("fgets: %s\n", string);
2928 G_INT(OFS_RETURN) = PR_SetString(string);
2930 G_INT(OFS_RETURN) = 0;
2933 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2937 char string[STRINGTEMP_LENGTH];
2938 int filenum = G_FLOAT(OFS_PARM0);
2939 if (filenum < 0 || filenum >= MAX_PRFILES)
2941 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2944 if (pr_files[filenum] == NULL)
2946 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2949 PF_VarString(1, string, sizeof(string));
2950 if ((stringlength = strlen(string)))
2951 FS_Write(pr_files[filenum], string, stringlength);
2952 if (developer.integer)
2953 Con_Printf("fputs: %s\n", string);
2956 //float(string s) strlen = #114; // returns how many characters are in a string
2957 void PF_strlen(void)
2960 s = G_STRING(OFS_PARM0);
2962 G_FLOAT(OFS_RETURN) = strlen(s);
2964 G_FLOAT(OFS_RETURN) = 0;
2967 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2968 void PF_strcat(void)
2970 char *s = PR_GetTempString();
2971 PF_VarString(0, s, STRINGTEMP_LENGTH);
2972 G_INT(OFS_RETURN) = PR_SetString(s);
2975 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2976 void PF_substring(void)
2978 int i, start, length;
2979 char *s, *string = PR_GetTempString();
2980 s = G_STRING(OFS_PARM0);
2981 start = G_FLOAT(OFS_PARM1);
2982 length = G_FLOAT(OFS_PARM2);
2985 for (i = 0;i < start && *s;i++, s++);
2986 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2989 G_INT(OFS_RETURN) = PR_SetString(string);
2992 //vector(string s) stov = #117; // returns vector value from a string
2995 char string[STRINGTEMP_LENGTH];
2996 PF_VarString(0, string, sizeof(string));
2997 Math_atov(string, G_VECTOR(OFS_RETURN));
3000 //string(string s) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
3001 void PF_strzone(void)
3004 in = G_STRING(OFS_PARM0);
3005 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3007 G_INT(OFS_RETURN) = PR_SetString(out);
3010 //void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
3011 void PF_strunzone(void)
3013 Mem_Free(G_STRING(OFS_PARM0));
3016 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3017 //this function originally written by KrimZon, made shorter by LordHavoc
3018 void PF_clientcommand (void)
3020 client_t *temp_client;
3023 //find client for this entity
3024 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3025 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3027 Con_Print("PF_clientcommand: entity is not a client\n");
3031 temp_client = host_client;
3032 host_client = svs.clients + i;
3033 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3034 host_client = temp_client;
3037 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3038 //this function originally written by KrimZon, made shorter by LordHavoc
3039 //20040203: rewritten by LordHavoc (no longer uses allocations)
3041 char *tokens[256], tokenbuf[4096];
3042 void PF_tokenize (void)
3046 p = G_STRING(OFS_PARM0);
3050 while(COM_ParseToken(&p, false))
3052 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3054 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3056 tokens[num_tokens++] = tokenbuf + pos;
3057 strcpy(tokenbuf + pos, com_token);
3058 pos += strlen(com_token) + 1;
3061 G_FLOAT(OFS_RETURN) = num_tokens;
3064 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3065 //this function originally written by KrimZon, made shorter by LordHavoc
3068 int token_num = G_FLOAT(OFS_PARM0);
3069 if (token_num >= 0 && token_num < num_tokens)
3070 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3072 G_INT(OFS_RETURN) = PR_SetString("");
3075 //void(entity e, entity tagentity, string tagname) setattachment = #443; // attachs e to a tag on tagentity (note: use "" to attach to entity origin/angles instead of a tag)
3076 void PF_setattachment (void)
3078 edict_t *e = G_EDICT(OFS_PARM0);
3079 edict_t *tagentity = G_EDICT(OFS_PARM1);
3080 char *tagname = G_STRING(OFS_PARM2);
3086 PF_WARNING("setattachment: can not modify world entity\n");
3088 PF_WARNING("setattachment: can not modify free entity\n");
3090 if (tagentity == NULL)
3091 tagentity = sv.edicts;
3093 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3095 v->edict = EDICT_TO_PROG(tagentity);
3097 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3100 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3102 modelindex = (int)tagentity->v->modelindex;
3103 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3105 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3106 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3107 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3109 // FIXME: use a model function to get tag info (need to handle skeletal)
3110 if (v->_float == 0 && model->alias.aliasnum_tags)
3111 for (i = 0;i < model->alias.aliasnum_tags;i++)
3112 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3115 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name);
3118 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity));
3123 /////////////////////////////////////////
3124 // DP_QC_FS_SEARCH extension
3126 // qc fs search handling
3127 #define MAX_SEARCHES 128
3129 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3131 void PR_Search_Init(void)
3133 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3136 void PR_Search_Reset(void)
3139 // reset the fssearch list
3140 for(i = 0; i < MAX_SEARCHES; i++)
3141 if(pr_fssearchlist[i])
3142 FS_FreeSearch(pr_fssearchlist[i]);
3143 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3150 float search_begin(string pattern, float caseinsensitive, float quiet)
3153 void PF_search_begin(void)
3157 int caseinsens, quiet;
3159 pattern = G_STRING(OFS_PARM0);
3161 PR_CheckEmptyString(pattern);
3163 caseinsens = G_FLOAT(OFS_PARM1);
3164 quiet = G_FLOAT(OFS_PARM2);
3166 for(handle = 0; handle < MAX_SEARCHES; handle++)
3167 if(!pr_fssearchlist[handle])
3170 if(handle >= MAX_SEARCHES)
3172 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3173 G_FLOAT(OFS_RETURN) = -2;
3177 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3178 G_FLOAT(OFS_RETURN) = -1;
3180 G_FLOAT(OFS_RETURN) = handle;
3187 void search_end(float handle)
3190 void PF_search_end(void)
3194 handle = G_FLOAT(OFS_PARM0);
3196 if(handle < 0 || handle >= MAX_SEARCHES)
3198 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3201 if(pr_fssearchlist[handle] == NULL)
3203 Con_Printf("PF_search_end: no such handle %i\n", handle);
3207 FS_FreeSearch(pr_fssearchlist[handle]);
3208 pr_fssearchlist[handle] = NULL;
3215 float search_getsize(float handle)
3218 void PF_search_getsize(void)
3222 handle = G_FLOAT(OFS_PARM0);
3224 if(handle < 0 || handle >= MAX_SEARCHES)
3226 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3229 if(pr_fssearchlist[handle] == NULL)
3231 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3235 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3240 VM_search_getfilename
3242 string search_getfilename(float handle, float num)
3245 void PF_search_getfilename(void)
3247 int handle, filenum;
3250 handle = G_FLOAT(OFS_PARM0);
3251 filenum = G_FLOAT(OFS_PARM1);
3253 if(handle < 0 || handle >= MAX_SEARCHES)
3255 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3258 if(pr_fssearchlist[handle] == NULL)
3260 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3263 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3265 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3269 tmp = PR_GetTempString();
3270 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3272 G_INT(OFS_RETURN) = PR_SetString(tmp);
3275 void PF_cvar_string (void)
3281 str = G_STRING(OFS_PARM0);
3282 var = Cvar_FindVar (str);
3284 tmp = PR_GetTempString();
3285 strcpy(tmp, var->string);
3287 G_INT(OFS_RETURN) = PR_SetString(tmp);
3292 builtin_t pr_builtin[] =
3295 PF_makevectors, // #1 void(entity e) makevectors
3296 PF_setorigin, // #2 void(entity e, vector o) setorigin
3297 PF_setmodel, // #3 void(entity e, string m) setmodel
3298 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3299 NULL, // #5 void(entity e, vector min, vector max) setabssize
3300 PF_break, // #6 void() break
3301 PF_random, // #7 float() random
3302 PF_sound, // #8 void(entity e, float chan, string samp) sound
3303 PF_normalize, // #9 vector(vector v) normalize
3304 PF_error, // #10 void(string e) error
3305 PF_objerror, // #11 void(string e) objerror
3306 PF_vlen, // #12 float(vector v) vlen
3307 PF_vectoyaw, // #13 float(vector v) vectoyaw
3308 PF_Spawn, // #14 entity() spawn
3309 PF_Remove, // #15 void(entity e) remove
3310 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3311 PF_checkclient, // #17 entity() clientlist
3312 PF_Find, // #18 entity(entity start, .string fld, string match) find
3313 PF_precache_sound, // #19 void(string s) precache_sound
3314 PF_precache_model, // #20 void(string s) precache_model
3315 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3316 PF_findradius, // #22 entity(vector org, float rad) findradius
3317 PF_bprint, // #23 void(string s) bprint
3318 PF_sprint, // #24 void(entity client, string s) sprint
3319 PF_dprint, // #25 void(string s) dprint
3320 PF_ftos, // #26 void(string s) ftos
3321 PF_vtos, // #27 void(string s) vtos
3322 PF_coredump, // #28 void() coredump
3323 PF_traceon, // #29 void() traceon
3324 PF_traceoff, // #30 void() traceoff
3325 PF_eprint, // #31 void(entity e) eprint
3326 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3328 PF_droptofloor, // #34 float() droptofloor
3329 PF_lightstyle, // #35 void(float style, string value) lightstyle
3330 PF_rint, // #36 float(float v) rint
3331 PF_floor, // #37 float(float v) floor
3332 PF_ceil, // #38 float(float v) ceil
3334 PF_checkbottom, // #40 float(entity e) checkbottom
3335 PF_pointcontents , // #41 float(vector v) pointcontents
3337 PF_fabs, // #43 float(float f) fabs
3338 PF_aim, // #44 vector(entity e, float speed) aim
3339 PF_cvar, // #45 float(string s) cvar
3340 PF_localcmd, // #46 void(string s) localcmd
3341 PF_nextent, // #47 entity(entity e) nextent
3342 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3343 PF_changeyaw, // #49 void() ChangeYaw
3345 PF_vectoangles, // #51 vector(vector v) vectoangles
3346 PF_WriteByte, // #52 void(float to, float f) WriteByte
3347 PF_WriteChar, // #53 void(float to, float f) WriteChar
3348 PF_WriteShort, // #54 void(float to, float f) WriteShort
3349 PF_WriteLong, // #55 void(float to, float f) WriteLong
3350 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3351 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3352 PF_WriteString, // #58 void(float to, string s) WriteString
3353 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3354 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3355 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3356 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3357 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3358 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3359 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3361 SV_MoveToGoal, // #67 void(float step) movetogoal
3362 PF_precache_file, // #68 string(string s) precache_file
3363 PF_makestatic, // #69 void(entity e) makestatic
3364 PF_changelevel, // #70 void(string s) changelevel
3366 PF_cvar_set, // #72 void(string var, string val) cvar_set
3367 PF_centerprint, // #73 void(entity client, strings) centerprint
3368 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3369 PF_precache_model, // #75 string(string s) precache_model2
3370 PF_precache_sound, // #76 string(string s) precache_sound2
3371 PF_precache_file, // #77 string(string s) precache_file2
3372 PF_setspawnparms, // #78 void(entity e) setspawnparms
3375 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3384 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3385 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3386 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3387 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3388 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3389 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3390 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3391 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3392 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3393 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3404 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3405 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3406 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3407 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3408 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3409 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3410 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3411 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3412 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3413 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3414 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3415 a a a a a a a a // #120-199
3416 a a a a a a a a a a // #200-299
3417 a a a a a a a a a a // #300-399
3418 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3419 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3420 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3421 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3422 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3423 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3424 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3425 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3426 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3427 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3428 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3429 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3430 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3431 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3432 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3433 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3434 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3435 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3436 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3437 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3438 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3439 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3440 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3441 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3442 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3443 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3444 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3445 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3446 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3448 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3449 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3450 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3451 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3452 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3453 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3454 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3455 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3456 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3457 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3458 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3459 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3460 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3461 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3462 PF_search_begin, // #444
3463 PF_search_end, // #445
3464 PF_search_getsize, // #446
3465 PF_search_getfilename, // #447
3466 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3467 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3468 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3478 a a a a // #460-499 (LordHavoc)
3481 builtin_t *pr_builtins = pr_builtin;
3482 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3484 void PR_Cmd_Init(void)
3486 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3491 void PR_Cmd_Reset(void)
3493 Mem_EmptyPool(pr_strings_mempool);
3495 PR_Files_CloseAll();