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 "
156 "TENEBRAE_GFX_DLIGHTS "
160 qboolean checkextension(char *name)
165 for (e = ENGINE_EXTENSIONS;*e;e++)
172 while (*e && *e != ' ')
174 if (e - start == len)
175 if (!strncasecmp(start, name, len))
185 returns true if the extension is supported by the server
187 checkextension(extensionname)
190 void PF_checkextension (void)
192 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
199 This is a TERMINAL error, which will kill off the entire server.
208 char string[STRINGTEMP_LENGTH];
210 PF_VarString(0, string, sizeof(string));
211 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
212 ed = PROG_TO_EDICT(pr_global_struct->self);
215 PF_ERROR("Program error");
222 Dumps out self, then an error message. The program is aborted and self is
223 removed, but the level can continue.
228 void PF_objerror (void)
231 char string[STRINGTEMP_LENGTH];
233 PF_VarString(0, string, sizeof(string));
234 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
235 ed = PROG_TO_EDICT(pr_global_struct->self);
245 Writes new values for v_forward, v_up, and v_right based on angles
249 void PF_makevectors (void)
251 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
258 Writes new values for v_forward, v_up, and v_right based on the given forward vector
259 vectorvectors(vector, vector)
262 void PF_vectorvectors (void)
264 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
265 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
272 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.
274 setorigin (entity, origin)
277 void PF_setorigin (void)
282 e = G_EDICT(OFS_PARM0);
284 PF_WARNING("setorigin: can not modify world entity\n");
286 PF_WARNING("setorigin: can not modify free entity\n");
287 org = G_VECTOR(OFS_PARM1);
288 VectorCopy (org, e->v->origin);
289 SV_LinkEdict (e, false);
293 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
297 for (i=0 ; i<3 ; i++)
299 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
301 // set derived values
302 VectorCopy (min, e->v->mins);
303 VectorCopy (max, e->v->maxs);
304 VectorSubtract (max, min, e->v->size);
306 SV_LinkEdict (e, false);
313 the size box is rotated by the current angle
314 LordHavoc: no it isn't...
316 setsize (entity, minvector, maxvector)
319 void PF_setsize (void)
324 e = G_EDICT(OFS_PARM0);
326 PF_WARNING("setsize: can not modify world entity\n");
328 PF_WARNING("setsize: can not modify free entity\n");
329 min = G_VECTOR(OFS_PARM1);
330 max = G_VECTOR(OFS_PARM2);
331 SetMinMaxSize (e, min, max, false);
339 setmodel(entity, model)
342 void PF_setmodel (void)
349 e = G_EDICT(OFS_PARM0);
351 PF_WARNING("setmodel: can not modify world entity\n");
353 PF_WARNING("setmodel: can not modify free entity\n");
354 m = G_STRING(OFS_PARM1);
356 // check to see if model was properly precached
357 for (i=0, check = sv.model_precache ; *check ; i++, check++)
358 if (!strcmp(*check, m))
362 PF_WARNING("setmodel: no precache\n");
365 e->v->model = PR_SetString(*check);
366 e->v->modelindex = i;
368 mod = sv.models[ (int)e->v->modelindex];
371 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
373 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
380 broadcast print to everyone on server
385 void PF_bprint (void)
387 char string[STRINGTEMP_LENGTH];
388 PF_VarString(0, string, sizeof(string));
389 SV_BroadcastPrint(string);
396 single print to a specific client
398 sprint(clientent, value)
401 void PF_sprint (void)
405 char string[STRINGTEMP_LENGTH];
407 entnum = G_EDICTNUM(OFS_PARM0);
409 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
411 Con_Print("tried to sprint to a non-client\n");
415 client = svs.clients + entnum-1;
416 if (!client->netconnection)
418 PF_VarString(1, string, sizeof(string));
419 MSG_WriteChar(&client->message,svc_print);
420 MSG_WriteString(&client->message, string);
428 single print to a specific client
430 centerprint(clientent, value)
433 void PF_centerprint (void)
437 char string[STRINGTEMP_LENGTH];
439 entnum = G_EDICTNUM(OFS_PARM0);
441 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
443 Con_Print("tried to sprint to a non-client\n");
447 client = svs.clients + entnum-1;
448 if (!client->netconnection)
450 PF_VarString(1, string, sizeof(string));
451 MSG_WriteChar(&client->message,svc_centerprint);
452 MSG_WriteString(&client->message, string);
460 vector normalize(vector)
463 void PF_normalize (void)
469 value1 = G_VECTOR(OFS_PARM0);
471 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
475 newvalue[0] = newvalue[1] = newvalue[2] = 0;
479 newvalue[0] = value1[0] * new;
480 newvalue[1] = value1[1] * new;
481 newvalue[2] = value1[2] * new;
484 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
499 value1 = G_VECTOR(OFS_PARM0);
501 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
504 G_FLOAT(OFS_RETURN) = new;
511 float vectoyaw(vector)
514 void PF_vectoyaw (void)
519 value1 = G_VECTOR(OFS_PARM0);
521 if (value1[1] == 0 && value1[0] == 0)
525 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
530 G_FLOAT(OFS_RETURN) = yaw;
538 vector vectoangles(vector)
541 void PF_vectoangles (void)
543 double value1[3], forward, yaw, pitch;
545 VectorCopy(G_VECTOR(OFS_PARM0), value1);
547 if (value1[1] == 0 && value1[0] == 0)
557 // LordHavoc: optimized a bit
560 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
564 else if (value1[1] > 0)
569 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
570 pitch = (atan2(value1[2], forward) * 180 / M_PI);
575 VectorSet(G_VECTOR(OFS_RETURN), pitch, yaw, 0);
582 Returns a number from 0<= num < 1
587 void PF_random (void)
591 num = (rand ()&0x7fff) / ((float)0x7fff);
593 G_FLOAT(OFS_RETURN) = num;
600 particle(origin, color, count)
603 void PF_particle (void)
609 org = G_VECTOR(OFS_PARM0);
610 dir = G_VECTOR(OFS_PARM1);
611 color = G_FLOAT(OFS_PARM2);
612 count = G_FLOAT(OFS_PARM3);
613 SV_StartParticle (org, dir, color, count);
623 void PF_ambientsound (void)
628 float vol, attenuation;
631 pos = G_VECTOR (OFS_PARM0);
632 samp = G_STRING(OFS_PARM1);
633 vol = G_FLOAT(OFS_PARM2);
634 attenuation = G_FLOAT(OFS_PARM3);
636 // check to see if samp was properly precached
637 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
638 if (!strcmp(*check,samp))
643 Con_Printf("no precache: %s\n", samp);
651 // add an svc_spawnambient command to the level signon packet
654 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
656 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
658 MSG_WriteVector(&sv.signon, pos, sv.protocol);
661 MSG_WriteShort (&sv.signon, soundnum);
663 MSG_WriteByte (&sv.signon, soundnum);
665 MSG_WriteByte (&sv.signon, vol*255);
666 MSG_WriteByte (&sv.signon, attenuation*64);
674 Each entity can have eight independant sound sources, like voice,
677 Channel 0 is an auto-allocate channel, the others override anything
678 already running on that entity/channel pair.
680 An attenuation of 0 will play full volume everywhere in the level.
681 Larger attenuations will drop off.
693 entity = G_EDICT(OFS_PARM0);
694 channel = G_FLOAT(OFS_PARM1);
695 sample = G_STRING(OFS_PARM2);
696 volume = G_FLOAT(OFS_PARM3) * 255;
697 attenuation = G_FLOAT(OFS_PARM4);
699 if (volume < 0 || volume > 255)
700 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
702 if (attenuation < 0 || attenuation > 4)
703 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
705 if (channel < 0 || channel > 7)
706 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
708 SV_StartSound (entity, channel, sample, volume, attenuation);
720 PF_ERROR("break: break statement\n");
727 Used for use tracing and shot targeting
728 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
729 if the tryents flag is set.
731 traceline (vector1, vector2, tryents)
734 void PF_traceline (void)
741 pr_xfunction->builtinsprofile += 30;
743 v1 = G_VECTOR(OFS_PARM0);
744 v2 = G_VECTOR(OFS_PARM1);
745 move = G_FLOAT(OFS_PARM2);
746 ent = G_EDICT(OFS_PARM3);
748 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
750 pr_global_struct->trace_allsolid = trace.allsolid;
751 pr_global_struct->trace_startsolid = trace.startsolid;
752 pr_global_struct->trace_fraction = trace.fraction;
753 pr_global_struct->trace_inwater = trace.inwater;
754 pr_global_struct->trace_inopen = trace.inopen;
755 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
756 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
757 pr_global_struct->trace_plane_dist = trace.plane.dist;
759 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
761 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
762 // FIXME: add trace_endcontents
770 Used for use tracing and shot targeting
771 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
772 if the tryents flag is set.
774 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
777 // LordHavoc: added this for my own use, VERY useful, similar to traceline
778 void PF_tracebox (void)
780 float *v1, *v2, *m1, *m2;
785 pr_xfunction->builtinsprofile += 30;
787 v1 = G_VECTOR(OFS_PARM0);
788 m1 = G_VECTOR(OFS_PARM1);
789 m2 = G_VECTOR(OFS_PARM2);
790 v2 = G_VECTOR(OFS_PARM3);
791 move = G_FLOAT(OFS_PARM4);
792 ent = G_EDICT(OFS_PARM5);
794 trace = SV_Move (v1, m1, m2, v2, move, ent);
796 pr_global_struct->trace_allsolid = trace.allsolid;
797 pr_global_struct->trace_startsolid = trace.startsolid;
798 pr_global_struct->trace_fraction = trace.fraction;
799 pr_global_struct->trace_inwater = trace.inwater;
800 pr_global_struct->trace_inopen = trace.inopen;
801 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
802 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
803 pr_global_struct->trace_plane_dist = trace.plane.dist;
805 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
807 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
810 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
811 void PF_TraceToss (void)
817 pr_xfunction->builtinsprofile += 600;
819 ent = G_EDICT(OFS_PARM0);
820 if (ent == sv.edicts)
821 PF_WARNING("tracetoss: can not use world entity\n");
822 ignore = G_EDICT(OFS_PARM1);
824 trace = SV_Trace_Toss (ent, ignore);
826 pr_global_struct->trace_allsolid = trace.allsolid;
827 pr_global_struct->trace_startsolid = trace.startsolid;
828 pr_global_struct->trace_fraction = trace.fraction;
829 pr_global_struct->trace_inwater = trace.inwater;
830 pr_global_struct->trace_inopen = trace.inopen;
831 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
832 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
833 pr_global_struct->trace_plane_dist = trace.plane.dist;
835 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
837 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
845 Returns true if the given entity can move to the given position from it's
846 current position by walking or rolling.
848 scalar checkpos (entity, vector)
851 void PF_checkpos (void)
855 //============================================================================
858 qbyte checkpvs[MAX_MAP_LEAFS/8];
860 int PF_newcheckclient (int check)
866 // cycle to the next one
868 check = bound(1, check, svs.maxclients);
869 if (check == svs.maxclients)
877 pr_xfunction->builtinsprofile++;
879 if (i == svs.maxclients+1)
881 // look up the client's edict
883 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
884 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
886 // found a valid client (possibly the same one again)
890 // get the PVS for the entity
891 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
893 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
894 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
903 Returns a client (or object that has a client enemy) that would be a
906 If there is more than one valid option, they are cycled each frame
908 If (self.origin + self.viewofs) is not in the PVS of the current target,
909 it is not returned at all.
914 int c_invis, c_notvis;
915 void PF_checkclient (void)
920 // find a new check if on a new frame
921 if (sv.time - sv.lastchecktime >= 0.1)
923 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
924 sv.lastchecktime = sv.time;
927 // return check if it might be visible
928 ent = EDICT_NUM(sv.lastcheck);
929 if (ent->e->free || ent->v->health <= 0)
931 RETURN_EDICT(sv.edicts);
935 // if current entity can't possibly see the check entity, return 0
936 self = PROG_TO_EDICT(pr_global_struct->self);
937 VectorAdd(self->v->origin, self->v->view_ofs, view);
938 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
941 RETURN_EDICT(sv.edicts);
945 // might be able to see it
950 //============================================================================
957 Sends text over to the client's execution buffer
959 stuffcmd (clientent, value)
962 void PF_stuffcmd (void)
968 entnum = G_EDICTNUM(OFS_PARM0);
969 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
971 Con_Print("Can't stuffcmd to a non-client\n");
974 str = G_STRING(OFS_PARM1);
977 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
978 Host_ClientCommands ("%s", str);
986 Sends text to server console
991 void PF_localcmd (void)
993 Cbuf_AddText(G_STRING(OFS_PARM0));
1005 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1015 void PF_cvar_set (void)
1017 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1024 Returns a chain of entities that have origins within a spherical area
1026 findradius (origin, radius)
1029 void PF_findradius (void)
1031 edict_t *ent, *chain;
1038 chain = (edict_t *)sv.edicts;
1040 org = G_VECTOR(OFS_PARM0);
1041 radius = G_FLOAT(OFS_PARM1);
1042 radius2 = radius * radius;
1044 ent = NEXT_EDICT(sv.edicts);
1045 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1047 pr_xfunction->builtinsprofile++;
1050 if (ent->v->solid == SOLID_NOT)
1053 // LordHavoc: compare against bounding box rather than center,
1054 // and use DotProduct instead of Length, major speedup
1055 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1056 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1057 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1058 if (DotProduct(eorg, eorg) > radius2)
1061 ent->v->chain = EDICT_TO_PROG(chain);
1065 RETURN_EDICT(chain);
1074 void PF_dprint (void)
1076 char string[STRINGTEMP_LENGTH];
1077 if (developer.integer)
1079 PF_VarString(0, string, sizeof(string));
1088 v = G_FLOAT(OFS_PARM0);
1090 s = PR_GetTempString();
1091 if ((float)((int)v) == v)
1092 sprintf(s, "%i", (int)v);
1094 sprintf(s, "%f", v);
1095 G_INT(OFS_RETURN) = PR_SetString(s);
1101 v = G_FLOAT(OFS_PARM0);
1102 G_FLOAT(OFS_RETURN) = fabs(v);
1108 s = PR_GetTempString();
1109 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1110 G_INT(OFS_RETURN) = PR_SetString(s);
1116 s = PR_GetTempString();
1117 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1118 G_INT(OFS_RETURN) = PR_SetString(s);
1121 void PF_Spawn (void)
1124 pr_xfunction->builtinsprofile += 20;
1129 void PF_Remove (void)
1132 pr_xfunction->builtinsprofile += 20;
1134 ed = G_EDICT(OFS_PARM0);
1135 if (ed == sv.edicts)
1136 PF_WARNING("remove: tried to remove world\n");
1137 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1138 PF_WARNING("remove: tried to remove a client\n");
1139 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1140 if (ed->e->free && developer.integer)
1141 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1146 // entity (entity start, .string field, string match) find = #5;
1154 e = G_EDICTNUM(OFS_PARM0);
1155 f = G_INT(OFS_PARM1);
1156 s = G_STRING(OFS_PARM2);
1159 RETURN_EDICT(sv.edicts);
1163 for (e++ ; e < sv.num_edicts ; e++)
1165 pr_xfunction->builtinsprofile++;
1179 RETURN_EDICT(sv.edicts);
1182 // LordHavoc: added this for searching float, int, and entity reference fields
1183 void PF_FindFloat (void)
1190 e = G_EDICTNUM(OFS_PARM0);
1191 f = G_INT(OFS_PARM1);
1192 s = G_FLOAT(OFS_PARM2);
1194 for (e++ ; e < sv.num_edicts ; e++)
1196 pr_xfunction->builtinsprofile++;
1200 if (E_FLOAT(ed,f) == s)
1207 RETURN_EDICT(sv.edicts);
1210 // chained search for strings in entity fields
1211 // entity(.string field, string match) findchain = #402;
1212 void PF_findchain (void)
1217 edict_t *ent, *chain;
1219 chain = (edict_t *)sv.edicts;
1221 f = G_INT(OFS_PARM0);
1222 s = G_STRING(OFS_PARM1);
1225 RETURN_EDICT(sv.edicts);
1229 ent = NEXT_EDICT(sv.edicts);
1230 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1232 pr_xfunction->builtinsprofile++;
1235 t = E_STRING(ent,f);
1241 ent->v->chain = EDICT_TO_PROG(chain);
1245 RETURN_EDICT(chain);
1248 // LordHavoc: chained search for float, int, and entity reference fields
1249 // entity(.string field, float match) findchainfloat = #403;
1250 void PF_findchainfloat (void)
1255 edict_t *ent, *chain;
1257 chain = (edict_t *)sv.edicts;
1259 f = G_INT(OFS_PARM0);
1260 s = G_FLOAT(OFS_PARM1);
1262 ent = NEXT_EDICT(sv.edicts);
1263 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1265 pr_xfunction->builtinsprofile++;
1268 if (E_FLOAT(ent,f) != s)
1271 ent->v->chain = EDICT_TO_PROG(chain);
1275 RETURN_EDICT(chain);
1278 // LordHavoc: search for flags in float fields
1279 void PF_findflags (void)
1286 e = G_EDICTNUM(OFS_PARM0);
1287 f = G_INT(OFS_PARM1);
1288 s = (int)G_FLOAT(OFS_PARM2);
1290 for (e++ ; e < sv.num_edicts ; e++)
1292 pr_xfunction->builtinsprofile++;
1296 if ((int)E_FLOAT(ed,f) & s)
1303 RETURN_EDICT(sv.edicts);
1306 // LordHavoc: chained search for flags in float fields
1307 void PF_findchainflags (void)
1312 edict_t *ent, *chain;
1314 chain = (edict_t *)sv.edicts;
1316 f = G_INT(OFS_PARM0);
1317 s = (int)G_FLOAT(OFS_PARM1);
1319 ent = NEXT_EDICT(sv.edicts);
1320 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1322 pr_xfunction->builtinsprofile++;
1325 if (!((int)E_FLOAT(ent,f) & s))
1328 ent->v->chain = EDICT_TO_PROG(chain);
1332 RETURN_EDICT(chain);
1335 void PR_CheckEmptyString (char *s)
1338 PF_ERROR("Bad string");
1341 void PF_precache_file (void)
1342 { // precache_file is only used to copy files with qcc, it does nothing
1343 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1346 void PF_precache_sound (void)
1350 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1352 if (sv.state != ss_loading)
1353 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1355 s = G_STRING(OFS_PARM0);
1356 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1357 PR_CheckEmptyString (s);
1359 for (i=0 ; i<limit ; i++)
1361 if (!sv.sound_precache[i])
1363 sv.sound_precache[i] = s;
1366 if (!strcmp(sv.sound_precache[i], s))
1369 PF_ERROR("PF_precache_sound: overflow");
1372 void PF_precache_model (void)
1376 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1378 if (sv.state != ss_loading)
1379 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1381 s = G_STRING(OFS_PARM0);
1382 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1384 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1385 PR_CheckEmptyString (s);
1387 for (i = 0;i < limit;i++)
1389 if (!sv.model_precache[i])
1391 sv.model_precache[i] = s;
1392 sv.models[i] = Mod_ForName (s, true, false, false);
1395 if (!strcmp(sv.model_precache[i], s))
1398 PF_ERROR("PF_precache_model: overflow");
1402 void PF_coredump (void)
1407 void PF_traceon (void)
1412 void PF_traceoff (void)
1417 void PF_eprint (void)
1419 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1426 float(float yaw, float dist) walkmove
1429 void PF_walkmove (void)
1437 // assume failure if it returns early
1438 G_FLOAT(OFS_RETURN) = 0;
1440 ent = PROG_TO_EDICT(pr_global_struct->self);
1441 if (ent == sv.edicts)
1442 PF_WARNING("walkmove: can not modify world entity\n");
1444 PF_WARNING("walkmove: can not modify free entity\n");
1445 yaw = G_FLOAT(OFS_PARM0);
1446 dist = G_FLOAT(OFS_PARM1);
1448 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1451 yaw = yaw*M_PI*2 / 360;
1453 move[0] = cos(yaw)*dist;
1454 move[1] = sin(yaw)*dist;
1457 // save program state, because SV_movestep may call other progs
1458 oldf = pr_xfunction;
1459 oldself = pr_global_struct->self;
1461 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1464 // restore program state
1465 pr_xfunction = oldf;
1466 pr_global_struct->self = oldself;
1476 void PF_droptofloor (void)
1482 // assume failure if it returns early
1483 G_FLOAT(OFS_RETURN) = 0;
1485 ent = PROG_TO_EDICT(pr_global_struct->self);
1486 if (ent == sv.edicts)
1487 PF_WARNING("droptofloor: can not modify world entity\n");
1489 PF_WARNING("droptofloor: can not modify free entity\n");
1491 VectorCopy (ent->v->origin, end);
1494 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1496 if (trace.fraction != 1)
1498 VectorCopy (trace.endpos, ent->v->origin);
1499 SV_LinkEdict (ent, false);
1500 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1501 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1502 G_FLOAT(OFS_RETURN) = 1;
1503 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1504 ent->e->suspendedinairflag = true;
1512 void(float style, string value) lightstyle
1515 void PF_lightstyle (void)
1522 style = G_FLOAT(OFS_PARM0);
1523 val = G_STRING(OFS_PARM1);
1525 // change the string in sv
1526 sv.lightstyles[style] = val;
1528 // send message to all clients on this server
1529 if (sv.state != ss_active)
1532 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1534 if (client->netconnection)
1536 MSG_WriteChar (&client->message, svc_lightstyle);
1537 MSG_WriteChar (&client->message,style);
1538 MSG_WriteString (&client->message, val);
1546 f = G_FLOAT(OFS_PARM0);
1548 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1550 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1552 void PF_floor (void)
1554 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1558 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1567 void PF_checkbottom (void)
1569 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1577 void PF_pointcontents (void)
1579 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1586 entity nextent(entity)
1589 void PF_nextent (void)
1594 i = G_EDICTNUM(OFS_PARM0);
1597 pr_xfunction->builtinsprofile++;
1599 if (i == sv.num_edicts)
1601 RETURN_EDICT(sv.edicts);
1617 Pick a vector for the player to shoot along
1618 vector aim(entity, missilespeed)
1623 edict_t *ent, *check, *bestent;
1624 vec3_t start, dir, end, bestdir;
1627 float dist, bestdist;
1630 // assume failure if it returns early
1631 VectorClear(G_VECTOR(OFS_RETURN));
1633 ent = G_EDICT(OFS_PARM0);
1634 if (ent == sv.edicts)
1635 PF_WARNING("aim: can not use world entity\n");
1637 PF_WARNING("aim: can not use free entity\n");
1638 speed = G_FLOAT(OFS_PARM1);
1640 VectorCopy (ent->v->origin, start);
1643 // try sending a trace straight
1644 VectorCopy (pr_global_struct->v_forward, dir);
1645 VectorMA (start, 2048, dir, end);
1646 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1647 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1648 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1650 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1655 // try all possible entities
1656 VectorCopy (dir, bestdir);
1657 bestdist = sv_aim.value;
1660 check = NEXT_EDICT(sv.edicts);
1661 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1663 pr_xfunction->builtinsprofile++;
1664 if (check->v->takedamage != DAMAGE_AIM)
1668 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1669 continue; // don't aim at teammate
1670 for (j=0 ; j<3 ; j++)
1671 end[j] = check->v->origin[j]
1672 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1673 VectorSubtract (end, start, dir);
1674 VectorNormalize (dir);
1675 dist = DotProduct (dir, pr_global_struct->v_forward);
1676 if (dist < bestdist)
1677 continue; // to far to turn
1678 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1679 if (tr.ent == check)
1680 { // can shoot at this one
1688 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1689 dist = DotProduct (dir, pr_global_struct->v_forward);
1690 VectorScale (pr_global_struct->v_forward, dist, end);
1692 VectorNormalize (end);
1693 VectorCopy (end, G_VECTOR(OFS_RETURN));
1697 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1705 This was a major timewaster in progs, so it was converted to C
1708 void PF_changeyaw (void)
1711 float ideal, current, move, speed;
1713 ent = PROG_TO_EDICT(pr_global_struct->self);
1714 if (ent == sv.edicts)
1715 PF_WARNING("changeyaw: can not modify world entity\n");
1717 PF_WARNING("changeyaw: can not modify free entity\n");
1718 current = ANGLEMOD(ent->v->angles[1]);
1719 ideal = ent->v->ideal_yaw;
1720 speed = ent->v->yaw_speed;
1722 if (current == ideal)
1724 move = ideal - current;
1725 if (ideal > current)
1746 ent->v->angles[1] = ANGLEMOD (current + move);
1754 void PF_changepitch (void)
1757 float ideal, current, move, speed;
1760 ent = G_EDICT(OFS_PARM0);
1761 if (ent == sv.edicts)
1762 PF_WARNING("changepitch: can not modify world entity\n");
1764 PF_WARNING("changepitch: can not modify free entity\n");
1765 current = ANGLEMOD( ent->v->angles[0] );
1766 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1767 ideal = val->_float;
1770 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1773 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1774 speed = val->_float;
1777 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1781 if (current == ideal)
1783 move = ideal - current;
1784 if (ideal > current)
1805 ent->v->angles[0] = ANGLEMOD (current + move);
1809 ===============================================================================
1813 ===============================================================================
1816 #define MSG_BROADCAST 0 // unreliable to all
1817 #define MSG_ONE 1 // reliable to one (msg_entity)
1818 #define MSG_ALL 2 // reliable to all
1819 #define MSG_INIT 3 // write to the init string
1821 sizebuf_t *WriteDest (void)
1827 dest = G_FLOAT(OFS_PARM0);
1831 return &sv.datagram;
1834 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1835 entnum = NUM_FOR_EDICT(ent);
1836 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1837 Host_Error("WriteDest: tried to write to non-client\n");
1838 return &svs.clients[entnum-1].message;
1841 return &sv.reliable_datagram;
1847 Host_Error("WriteDest: bad destination");
1854 void PF_WriteByte (void)
1856 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1859 void PF_WriteChar (void)
1861 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1864 void PF_WriteShort (void)
1866 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1869 void PF_WriteLong (void)
1871 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1874 void PF_WriteAngle (void)
1876 if (sv.protocol == PROTOCOL_DARKPLACES5)
1877 MSG_WriteAngle16i (WriteDest(), G_FLOAT(OFS_PARM1));
1879 MSG_WriteAngle8i (WriteDest(), G_FLOAT(OFS_PARM1));
1882 void PF_WriteCoord (void)
1884 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1887 void PF_WriteString (void)
1889 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1893 void PF_WriteEntity (void)
1895 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1898 //=============================================================================
1900 void PF_makestatic (void)
1905 ent = G_EDICT(OFS_PARM0);
1906 if (ent == sv.edicts)
1907 PF_WARNING("makestatic: can not modify world entity\n");
1909 PF_WARNING("makestatic: can not modify free entity\n");
1912 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1917 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1918 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1919 MSG_WriteShort (&sv.signon, ent->v->frame);
1923 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1924 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1925 MSG_WriteByte (&sv.signon, ent->v->frame);
1928 MSG_WriteByte (&sv.signon, ent->v->colormap);
1929 MSG_WriteByte (&sv.signon, ent->v->skin);
1930 for (i=0 ; i<3 ; i++)
1932 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1933 MSG_WriteAngle8i(&sv.signon, ent->v->angles[i]);
1936 // throw the entity away now
1940 //=============================================================================
1947 void PF_setspawnparms (void)
1953 ent = G_EDICT(OFS_PARM0);
1954 i = NUM_FOR_EDICT(ent);
1955 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1957 Con_Print("tried to setspawnparms on a non-client\n");
1961 // copy spawn parms out of the client_t
1962 client = svs.clients + i-1;
1963 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1964 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1972 void PF_changelevel (void)
1976 // make sure we don't issue two changelevels
1977 if (svs.changelevel_issued)
1979 svs.changelevel_issued = true;
1981 s = G_STRING(OFS_PARM0);
1982 Cbuf_AddText (va("changelevel %s\n",s));
1987 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1992 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1997 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2004 Returns a vector of length < 1
2009 void PF_randomvec (void)
2014 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2015 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2016 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2018 while (DotProduct(temp, temp) >= 1);
2019 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2026 Returns a color vector indicating the lighting at the requested point.
2028 (Internal Operation note: actually measures the light beneath the point, just like
2029 the model lighting on the client)
2034 void PF_GetLight (void)
2036 vec3_t ambientcolor, diffusecolor, diffusenormal;
2038 p = G_VECTOR(OFS_PARM0);
2039 VectorClear(ambientcolor);
2040 VectorClear(diffusecolor);
2041 VectorClear(diffusenormal);
2042 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2043 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2044 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2047 void PF_registercvar (void)
2050 name = G_STRING(OFS_PARM0);
2051 value = G_STRING(OFS_PARM1);
2052 G_FLOAT(OFS_RETURN) = 0;
2054 // first check to see if it has already been defined
2055 if (Cvar_FindVar (name))
2058 // check for overlap with a command
2059 if (Cmd_Exists (name))
2061 Con_Printf("PF_registercvar: %s is a command\n", name);
2065 Cvar_Get(name, value, 0);
2067 G_FLOAT(OFS_RETURN) = 1; // success
2074 returns the minimum of two supplied floats
2081 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2083 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2084 else if (pr_argc >= 3)
2087 float f = G_FLOAT(OFS_PARM0);
2088 for (i = 1;i < pr_argc;i++)
2089 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2090 f = G_FLOAT((OFS_PARM0+i*3));
2091 G_FLOAT(OFS_RETURN) = f;
2095 G_FLOAT(OFS_RETURN) = 0;
2096 PF_WARNING("min: must supply at least 2 floats\n");
2104 returns the maximum of two supplied floats
2111 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2113 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2114 else if (pr_argc >= 3)
2117 float f = G_FLOAT(OFS_PARM0);
2118 for (i = 1;i < pr_argc;i++)
2119 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2120 f = G_FLOAT((OFS_PARM0+i*3));
2121 G_FLOAT(OFS_RETURN) = f;
2125 G_FLOAT(OFS_RETURN) = 0;
2126 PF_WARNING("max: must supply at least 2 floats\n");
2134 returns number bounded by supplied range
2136 min(min, value, max)
2139 void PF_bound (void)
2141 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2148 returns a raised to power b
2155 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2162 copies data from one entity to another
2164 copyentity(src, dst)
2167 void PF_copyentity (void)
2170 in = G_EDICT(OFS_PARM0);
2171 if (in == sv.edicts)
2172 PF_WARNING("copyentity: can not read world entity\n");
2174 PF_WARNING("copyentity: can not read free entity\n");
2175 out = G_EDICT(OFS_PARM1);
2176 if (out == sv.edicts)
2177 PF_WARNING("copyentity: can not modify world entity\n");
2179 PF_WARNING("copyentity: can not modify free entity\n");
2180 memcpy(out->v, in->v, progs->entityfields * 4);
2187 sets the color of a client and broadcasts the update to all connected clients
2189 setcolor(clientent, value)
2192 void PF_setcolor (void)
2198 entnum = G_EDICTNUM(OFS_PARM0);
2199 i = G_FLOAT(OFS_PARM1);
2201 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2203 Con_Print("tried to setcolor a non-client\n");
2207 client = svs.clients + entnum-1;
2208 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2211 client->old_colors = i;
2212 client->edict->v->team = (i & 15) + 1;
2214 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2215 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2216 MSG_WriteByte (&sv.reliable_datagram, i);
2223 effect(origin, modelname, startframe, framecount, framerate)
2226 void PF_effect (void)
2230 s = G_STRING(OFS_PARM1);
2232 PF_WARNING("effect: no model specified\n");
2234 i = SV_ModelIndex(s);
2236 PF_WARNING("effect: model not precached\n");
2237 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2240 void PF_te_blood (void)
2242 if (G_FLOAT(OFS_PARM2) < 1)
2244 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2245 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2247 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2251 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2252 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2253 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2255 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2258 void PF_te_bloodshower (void)
2260 if (G_FLOAT(OFS_PARM3) < 1)
2262 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2265 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2273 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2275 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2278 void PF_te_explosionrgb (void)
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2283 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2287 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2288 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2289 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2292 void PF_te_particlecube (void)
2294 if (G_FLOAT(OFS_PARM3) < 1)
2296 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2297 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2299 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2311 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2313 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2314 // gravity true/false
2315 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2317 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2320 void PF_te_particlerain (void)
2322 if (G_FLOAT(OFS_PARM3) < 1)
2324 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2325 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2327 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2328 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2333 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2337 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2339 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2341 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2344 void PF_te_particlesnow (void)
2346 if (G_FLOAT(OFS_PARM3) < 1)
2348 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2349 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2351 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2352 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2357 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2359 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2360 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2361 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2363 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2365 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2368 void PF_te_spark (void)
2370 if (G_FLOAT(OFS_PARM2) < 1)
2372 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2373 MSG_WriteByte(&sv.datagram, TE_SPARK);
2375 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2376 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2377 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2379 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2380 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2381 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2383 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2386 void PF_te_gunshotquad (void)
2388 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2389 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2391 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2392 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2393 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2396 void PF_te_spikequad (void)
2398 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2399 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2401 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2402 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2403 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2406 void PF_te_superspikequad (void)
2408 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2409 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2411 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2412 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2413 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2416 void PF_te_explosionquad (void)
2418 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2419 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2421 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2422 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2423 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2426 void PF_te_smallflash (void)
2428 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2429 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2431 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2432 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2433 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2436 void PF_te_customflash (void)
2438 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2440 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2441 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2443 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2444 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2445 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2447 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2449 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2451 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2452 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2453 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2456 void PF_te_gunshot (void)
2458 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2459 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2461 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2462 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2463 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2466 void PF_te_spike (void)
2468 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2469 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2471 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2472 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2473 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2476 void PF_te_superspike (void)
2478 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2479 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2481 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2482 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2483 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2486 void PF_te_explosion (void)
2488 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2489 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2491 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2492 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2493 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2496 void PF_te_tarexplosion (void)
2498 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2499 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2501 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2502 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2503 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2506 void PF_te_wizspike (void)
2508 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2509 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2511 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2512 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2513 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2516 void PF_te_knightspike (void)
2518 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2519 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2521 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2522 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2523 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2526 void PF_te_lavasplash (void)
2528 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2529 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2531 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2532 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2533 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2536 void PF_te_teleport (void)
2538 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2539 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2541 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2542 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2543 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2546 void PF_te_explosion2 (void)
2548 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2549 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2551 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2552 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2553 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2555 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2556 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2559 void PF_te_lightning1 (void)
2561 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2562 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2564 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2566 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2567 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2568 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2570 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2571 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2572 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2575 void PF_te_lightning2 (void)
2577 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2578 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2580 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2582 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2583 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2584 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2586 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2587 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2588 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2591 void PF_te_lightning3 (void)
2593 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2594 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2596 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2598 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2599 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2600 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2602 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2603 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2604 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2607 void PF_te_beam (void)
2609 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2610 MSG_WriteByte(&sv.datagram, TE_BEAM);
2612 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2614 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2615 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2616 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2618 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2619 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2620 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2623 void PF_te_plasmaburn (void)
2625 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2626 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2627 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2628 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2629 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2632 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2635 vec3_t v1, clipplanenormal, normal;
2636 vec_t clipplanedist, clipdist;
2638 if (surf->flags & SURF_PLANEBACK)
2639 VectorNegate(surf->plane->normal, normal);
2641 VectorCopy(surf->plane->normal, normal);
2642 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2644 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2645 VectorNormalizeFast(v1);
2646 CrossProduct(v1, normal, clipplanenormal);
2647 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2648 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2651 clipdist = -clipdist;
2652 VectorMA(out, clipdist, clipplanenormal, out);
2657 static msurface_t *getsurface(edict_t *ed, int surfnum)
2661 if (!ed || ed->e->free)
2663 modelindex = ed->v->modelindex;
2664 if (modelindex < 1 || modelindex >= MAX_MODELS)
2666 model = sv.models[modelindex];
2667 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2669 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2673 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2674 void PF_getsurfacenumpoints(void)
2677 // return 0 if no such surface
2678 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2680 G_FLOAT(OFS_RETURN) = 0;
2684 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2686 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2687 void PF_getsurfacepoint(void)
2692 VectorClear(G_VECTOR(OFS_RETURN));
2693 ed = G_EDICT(OFS_PARM0);
2694 if (!ed || ed->e->free)
2696 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2698 pointnum = G_FLOAT(OFS_PARM2);
2699 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2701 // FIXME: implement rotation/scaling
2702 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2704 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2705 void PF_getsurfacenormal(void)
2708 VectorClear(G_VECTOR(OFS_RETURN));
2709 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2711 // FIXME: implement rotation/scaling
2712 if (surf->flags & SURF_PLANEBACK)
2713 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2715 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2717 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2718 void PF_getsurfacetexture(void)
2721 G_INT(OFS_RETURN) = 0;
2722 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2724 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2726 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2727 void PF_getsurfacenearpoint(void)
2729 int surfnum, best, modelindex;
2731 vec_t dist, bestdist;
2736 G_FLOAT(OFS_RETURN) = -1;
2737 ed = G_EDICT(OFS_PARM0);
2738 point = G_VECTOR(OFS_PARM1);
2740 if (!ed || ed->e->free)
2742 modelindex = ed->v->modelindex;
2743 if (modelindex < 1 || modelindex >= MAX_MODELS)
2745 model = sv.models[modelindex];
2746 if (!model->brushq1.numsurfaces)
2749 // FIXME: implement rotation/scaling
2750 VectorSubtract(point, ed->v->origin, p);
2752 bestdist = 1000000000;
2753 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2755 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2756 dist = PlaneDiff(p, surf->plane);
2758 if (dist < bestdist)
2760 clippointtosurface(surf, p, clipped);
2761 VectorSubtract(clipped, p, clipped);
2762 dist += DotProduct(clipped, clipped);
2763 if (dist < bestdist)
2770 G_FLOAT(OFS_RETURN) = best;
2772 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2773 void PF_getsurfaceclippedpoint(void)
2778 VectorClear(G_VECTOR(OFS_RETURN));
2779 ed = G_EDICT(OFS_PARM0);
2780 if (!ed || ed->e->free)
2782 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2784 // FIXME: implement rotation/scaling
2785 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2786 clippointtosurface(surf, p, out);
2787 // FIXME: implement rotation/scaling
2788 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2791 #define MAX_PRFILES 256
2793 qfile_t *pr_files[MAX_PRFILES];
2795 void PR_Files_Init(void)
2797 memset(pr_files, 0, sizeof(pr_files));
2800 void PR_Files_CloseAll(void)
2803 for (i = 0;i < MAX_PRFILES;i++)
2806 FS_Close(pr_files[i]);
2811 //float(string s) stof = #81; // get numerical value from a string
2814 char string[STRINGTEMP_LENGTH];
2815 PF_VarString(0, string, sizeof(string));
2816 G_FLOAT(OFS_RETURN) = atof(string);
2819 //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
2822 int filenum, mode, i;
2823 char *modestring, *filename;
2824 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2825 if (pr_files[filenum] == NULL)
2827 if (filenum >= MAX_PRFILES)
2829 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2830 G_FLOAT(OFS_RETURN) = -2;
2833 mode = G_FLOAT(OFS_PARM1);
2836 case 0: // FILE_READ
2839 case 1: // FILE_APPEND
2842 case 2: // FILE_WRITE
2846 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2847 G_FLOAT(OFS_RETURN) = -3;
2850 filename = G_STRING(OFS_PARM0);
2851 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2852 // ../ is parent directory on many platforms
2853 // // is parent directory on Amiga
2854 // / at the beginning of a path is root on unix, and parent directory on Amiga
2855 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2856 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2857 for (i = 0;filename[i];i++)
2859 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2861 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);
2862 G_FLOAT(OFS_RETURN) = -4;
2866 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2868 if (pr_files[filenum] == NULL && modestring == "rb")
2869 pr_files[filenum] = FS_Open(filename, modestring, false);
2871 if (pr_files[filenum] == NULL)
2872 G_FLOAT(OFS_RETURN) = -1;
2874 G_FLOAT(OFS_RETURN) = filenum;
2877 //void(float fhandle) fclose = #111; // closes a file
2878 void PF_fclose(void)
2880 int filenum = G_FLOAT(OFS_PARM0);
2881 if (filenum < 0 || filenum >= MAX_PRFILES)
2883 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2886 if (pr_files[filenum] == NULL)
2888 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2891 FS_Close(pr_files[filenum]);
2892 pr_files[filenum] = NULL;
2895 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2899 static char string[STRINGTEMP_LENGTH];
2900 int filenum = G_FLOAT(OFS_PARM0);
2901 if (filenum < 0 || filenum >= MAX_PRFILES)
2903 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2906 if (pr_files[filenum] == NULL)
2908 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2914 c = FS_Getc(pr_files[filenum]);
2915 if (c == '\r' || c == '\n' || c < 0)
2917 if (end < STRINGTEMP_LENGTH - 1)
2921 // remove \n following \r
2923 c = FS_Getc(pr_files[filenum]);
2924 if (developer.integer)
2925 Con_Printf("fgets: %s\n", string);
2927 G_INT(OFS_RETURN) = PR_SetString(string);
2929 G_INT(OFS_RETURN) = 0;
2932 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2936 char string[STRINGTEMP_LENGTH];
2937 int filenum = G_FLOAT(OFS_PARM0);
2938 if (filenum < 0 || filenum >= MAX_PRFILES)
2940 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2943 if (pr_files[filenum] == NULL)
2945 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2948 PF_VarString(1, string, sizeof(string));
2949 if ((stringlength = strlen(string)))
2950 FS_Write(pr_files[filenum], string, stringlength);
2951 if (developer.integer)
2952 Con_Printf("fputs: %s\n", string);
2955 //float(string s) strlen = #114; // returns how many characters are in a string
2956 void PF_strlen(void)
2959 s = G_STRING(OFS_PARM0);
2961 G_FLOAT(OFS_RETURN) = strlen(s);
2963 G_FLOAT(OFS_RETURN) = 0;
2966 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2967 void PF_strcat(void)
2969 char *s = PR_GetTempString();
2970 PF_VarString(0, s, STRINGTEMP_LENGTH);
2971 G_INT(OFS_RETURN) = PR_SetString(s);
2974 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2975 void PF_substring(void)
2977 int i, start, length;
2978 char *s, *string = PR_GetTempString();
2979 s = G_STRING(OFS_PARM0);
2980 start = G_FLOAT(OFS_PARM1);
2981 length = G_FLOAT(OFS_PARM2);
2984 for (i = 0;i < start && *s;i++, s++);
2985 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2988 G_INT(OFS_RETURN) = PR_SetString(string);
2991 //vector(string s) stov = #117; // returns vector value from a string
2994 char string[STRINGTEMP_LENGTH];
2995 PF_VarString(0, string, sizeof(string));
2996 Math_atov(string, G_VECTOR(OFS_RETURN));
2999 //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)
3000 void PF_strzone(void)
3003 in = G_STRING(OFS_PARM0);
3004 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3006 G_INT(OFS_RETURN) = PR_SetString(out);
3009 //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!!!)
3010 void PF_strunzone(void)
3012 Mem_Free(G_STRING(OFS_PARM0));
3015 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3016 //this function originally written by KrimZon, made shorter by LordHavoc
3017 void PF_clientcommand (void)
3019 client_t *temp_client;
3022 //find client for this entity
3023 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3024 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3026 Con_Print("PF_clientcommand: entity is not a client\n");
3030 temp_client = host_client;
3031 host_client = svs.clients + i;
3032 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3033 host_client = temp_client;
3036 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3037 //this function originally written by KrimZon, made shorter by LordHavoc
3038 //20040203: rewritten by LordHavoc (no longer uses allocations)
3040 char *tokens[256], tokenbuf[4096];
3041 void PF_tokenize (void)
3045 p = G_STRING(OFS_PARM0);
3049 while(COM_ParseToken(&p, false))
3051 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3053 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3055 tokens[num_tokens++] = tokenbuf + pos;
3056 strcpy(tokenbuf + pos, com_token);
3057 pos += strlen(com_token) + 1;
3060 G_FLOAT(OFS_RETURN) = num_tokens;
3063 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3064 //this function originally written by KrimZon, made shorter by LordHavoc
3067 int token_num = G_FLOAT(OFS_PARM0);
3068 if (token_num >= 0 && token_num < num_tokens)
3069 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3071 G_INT(OFS_RETURN) = PR_SetString("");
3074 //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)
3075 void PF_setattachment (void)
3077 edict_t *e = G_EDICT(OFS_PARM0);
3078 edict_t *tagentity = G_EDICT(OFS_PARM1);
3079 char *tagname = G_STRING(OFS_PARM2);
3085 PF_WARNING("setattachment: can not modify world entity\n");
3087 PF_WARNING("setattachment: can not modify free entity\n");
3089 if (tagentity == NULL)
3090 tagentity = sv.edicts;
3092 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3094 v->edict = EDICT_TO_PROG(tagentity);
3096 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3099 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3101 modelindex = (int)tagentity->v->modelindex;
3102 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3104 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3105 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3106 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3108 // FIXME: use a model function to get tag info (need to handle skeletal)
3109 if (v->_float == 0 && model->alias.aliasnum_tags)
3110 for (i = 0;i < model->alias.aliasnum_tags;i++)
3111 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3114 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);
3117 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));
3122 /////////////////////////////////////////
3123 // DP_QC_FS_SEARCH extension
3125 // qc fs search handling
3126 #define MAX_SEARCHES 128
3128 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3130 void PR_Search_Init(void)
3132 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3135 void PR_Search_Reset(void)
3138 // reset the fssearch list
3139 for(i = 0; i < MAX_SEARCHES; i++)
3140 if(pr_fssearchlist[i])
3141 FS_FreeSearch(pr_fssearchlist[i]);
3142 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3149 float search_begin(string pattern, float caseinsensitive, float quiet)
3152 void PF_search_begin(void)
3156 int caseinsens, quiet;
3158 pattern = G_STRING(OFS_PARM0);
3160 PR_CheckEmptyString(pattern);
3162 caseinsens = G_FLOAT(OFS_PARM1);
3163 quiet = G_FLOAT(OFS_PARM2);
3165 for(handle = 0; handle < MAX_SEARCHES; handle++)
3166 if(!pr_fssearchlist[handle])
3169 if(handle >= MAX_SEARCHES)
3171 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3172 G_FLOAT(OFS_RETURN) = -2;
3176 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3177 G_FLOAT(OFS_RETURN) = -1;
3179 G_FLOAT(OFS_RETURN) = handle;
3186 void search_end(float handle)
3189 void PF_search_end(void)
3193 handle = G_FLOAT(OFS_PARM0);
3195 if(handle < 0 || handle >= MAX_SEARCHES)
3197 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3200 if(pr_fssearchlist[handle] == NULL)
3202 Con_Printf("PF_search_end: no such handle %i\n", handle);
3206 FS_FreeSearch(pr_fssearchlist[handle]);
3207 pr_fssearchlist[handle] = NULL;
3214 float search_getsize(float handle)
3217 void PF_search_getsize(void)
3221 handle = G_FLOAT(OFS_PARM0);
3223 if(handle < 0 || handle >= MAX_SEARCHES)
3225 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3228 if(pr_fssearchlist[handle] == NULL)
3230 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3234 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3239 VM_search_getfilename
3241 string search_getfilename(float handle, float num)
3244 void PF_search_getfilename(void)
3246 int handle, filenum;
3249 handle = G_FLOAT(OFS_PARM0);
3250 filenum = G_FLOAT(OFS_PARM1);
3252 if(handle < 0 || handle >= MAX_SEARCHES)
3254 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3257 if(pr_fssearchlist[handle] == NULL)
3259 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3262 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3264 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3268 tmp = PR_GetTempString();
3269 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3271 G_INT(OFS_RETURN) = PR_SetString(tmp);
3274 void PF_cvar_string (void)
3280 str = G_STRING(OFS_PARM0);
3281 var = Cvar_FindVar (str);
3283 tmp = PR_GetTempString();
3284 strcpy(tmp, var->string);
3286 G_INT(OFS_RETURN) = PR_SetString(tmp);
3291 builtin_t pr_builtin[] =
3294 PF_makevectors, // #1 void(entity e) makevectors
3295 PF_setorigin, // #2 void(entity e, vector o) setorigin
3296 PF_setmodel, // #3 void(entity e, string m) setmodel
3297 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3298 NULL, // #5 void(entity e, vector min, vector max) setabssize
3299 PF_break, // #6 void() break
3300 PF_random, // #7 float() random
3301 PF_sound, // #8 void(entity e, float chan, string samp) sound
3302 PF_normalize, // #9 vector(vector v) normalize
3303 PF_error, // #10 void(string e) error
3304 PF_objerror, // #11 void(string e) objerror
3305 PF_vlen, // #12 float(vector v) vlen
3306 PF_vectoyaw, // #13 float(vector v) vectoyaw
3307 PF_Spawn, // #14 entity() spawn
3308 PF_Remove, // #15 void(entity e) remove
3309 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3310 PF_checkclient, // #17 entity() clientlist
3311 PF_Find, // #18 entity(entity start, .string fld, string match) find
3312 PF_precache_sound, // #19 void(string s) precache_sound
3313 PF_precache_model, // #20 void(string s) precache_model
3314 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3315 PF_findradius, // #22 entity(vector org, float rad) findradius
3316 PF_bprint, // #23 void(string s) bprint
3317 PF_sprint, // #24 void(entity client, string s) sprint
3318 PF_dprint, // #25 void(string s) dprint
3319 PF_ftos, // #26 void(string s) ftos
3320 PF_vtos, // #27 void(string s) vtos
3321 PF_coredump, // #28 void() coredump
3322 PF_traceon, // #29 void() traceon
3323 PF_traceoff, // #30 void() traceoff
3324 PF_eprint, // #31 void(entity e) eprint
3325 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3327 PF_droptofloor, // #34 float() droptofloor
3328 PF_lightstyle, // #35 void(float style, string value) lightstyle
3329 PF_rint, // #36 float(float v) rint
3330 PF_floor, // #37 float(float v) floor
3331 PF_ceil, // #38 float(float v) ceil
3333 PF_checkbottom, // #40 float(entity e) checkbottom
3334 PF_pointcontents , // #41 float(vector v) pointcontents
3336 PF_fabs, // #43 float(float f) fabs
3337 PF_aim, // #44 vector(entity e, float speed) aim
3338 PF_cvar, // #45 float(string s) cvar
3339 PF_localcmd, // #46 void(string s) localcmd
3340 PF_nextent, // #47 entity(entity e) nextent
3341 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3342 PF_changeyaw, // #49 void() ChangeYaw
3344 PF_vectoangles, // #51 vector(vector v) vectoangles
3345 PF_WriteByte, // #52 void(float to, float f) WriteByte
3346 PF_WriteChar, // #53 void(float to, float f) WriteChar
3347 PF_WriteShort, // #54 void(float to, float f) WriteShort
3348 PF_WriteLong, // #55 void(float to, float f) WriteLong
3349 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3350 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3351 PF_WriteString, // #58 void(float to, string s) WriteString
3352 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3353 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3354 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3355 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3356 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3357 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3358 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3360 SV_MoveToGoal, // #67 void(float step) movetogoal
3361 PF_precache_file, // #68 string(string s) precache_file
3362 PF_makestatic, // #69 void(entity e) makestatic
3363 PF_changelevel, // #70 void(string s) changelevel
3365 PF_cvar_set, // #72 void(string var, string val) cvar_set
3366 PF_centerprint, // #73 void(entity client, strings) centerprint
3367 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3368 PF_precache_model, // #75 string(string s) precache_model2
3369 PF_precache_sound, // #76 string(string s) precache_sound2
3370 PF_precache_file, // #77 string(string s) precache_file2
3371 PF_setspawnparms, // #78 void(entity e) setspawnparms
3374 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3383 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3384 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3385 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3386 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3387 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3388 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3389 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3390 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3391 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3392 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3403 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3404 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3405 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3406 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3407 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3408 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3409 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3410 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3411 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3412 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3413 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3414 a a a a a a a a // #120-199
3415 a a a a a a a a a a // #200-299
3416 a a a a a a a a a a // #300-399
3417 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3418 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3419 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3420 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3421 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3422 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3423 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3424 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3425 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3426 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3427 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3428 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3429 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3430 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3431 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3432 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3433 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3434 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3435 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3436 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3437 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3438 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3439 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3440 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3441 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3442 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3443 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3444 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3445 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3446 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3448 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3449 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3450 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3451 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3452 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3453 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3454 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3455 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3456 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3457 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3458 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3459 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3460 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3461 PF_search_begin, // #444
3462 PF_search_end, // #445
3463 PF_search_getsize, // #446
3464 PF_search_getfilename, // #447
3465 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3466 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3467 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3477 a a a a // #460-499 (LordHavoc)
3480 builtin_t *pr_builtins = pr_builtin;
3481 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3483 void PR_Cmd_Init(void)
3485 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3490 void PR_Cmd_Reset(void)
3492 Mem_EmptyPool(pr_strings_mempool);
3494 PR_Files_CloseAll();