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 = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
530 G_FLOAT(OFS_RETURN) = yaw;
538 vector vectoangles(vector)
541 void PF_vectoangles (void)
547 value1 = G_VECTOR(OFS_PARM0);
549 if (value1[1] == 0 && value1[0] == 0)
559 // LordHavoc: optimized a bit
562 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
566 else if (value1[1] > 0)
571 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
572 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
577 G_FLOAT(OFS_RETURN+0) = pitch;
578 G_FLOAT(OFS_RETURN+1) = yaw;
579 G_FLOAT(OFS_RETURN+2) = 0;
586 Returns a number from 0<= num < 1
591 void PF_random (void)
595 num = (rand ()&0x7fff) / ((float)0x7fff);
597 G_FLOAT(OFS_RETURN) = num;
604 particle(origin, color, count)
607 void PF_particle (void)
613 org = G_VECTOR(OFS_PARM0);
614 dir = G_VECTOR(OFS_PARM1);
615 color = G_FLOAT(OFS_PARM2);
616 count = G_FLOAT(OFS_PARM3);
617 SV_StartParticle (org, dir, color, count);
627 void PF_ambientsound (void)
632 float vol, attenuation;
635 pos = G_VECTOR (OFS_PARM0);
636 samp = G_STRING(OFS_PARM1);
637 vol = G_FLOAT(OFS_PARM2);
638 attenuation = G_FLOAT(OFS_PARM3);
640 // check to see if samp was properly precached
641 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
642 if (!strcmp(*check,samp))
647 Con_Printf("no precache: %s\n", samp);
655 // add an svc_spawnambient command to the level signon packet
658 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
660 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
662 MSG_WriteVector(&sv.signon, pos, sv.protocol);
665 MSG_WriteShort (&sv.signon, soundnum);
667 MSG_WriteByte (&sv.signon, soundnum);
669 MSG_WriteByte (&sv.signon, vol*255);
670 MSG_WriteByte (&sv.signon, attenuation*64);
678 Each entity can have eight independant sound sources, like voice,
681 Channel 0 is an auto-allocate channel, the others override anything
682 already running on that entity/channel pair.
684 An attenuation of 0 will play full volume everywhere in the level.
685 Larger attenuations will drop off.
697 entity = G_EDICT(OFS_PARM0);
698 channel = G_FLOAT(OFS_PARM1);
699 sample = G_STRING(OFS_PARM2);
700 volume = G_FLOAT(OFS_PARM3) * 255;
701 attenuation = G_FLOAT(OFS_PARM4);
703 if (volume < 0 || volume > 255)
704 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
706 if (attenuation < 0 || attenuation > 4)
707 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
709 if (channel < 0 || channel > 7)
710 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
712 SV_StartSound (entity, channel, sample, volume, attenuation);
724 PF_ERROR("break: break statement\n");
731 Used for use tracing and shot targeting
732 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
733 if the tryents flag is set.
735 traceline (vector1, vector2, tryents)
738 void PF_traceline (void)
745 pr_xfunction->builtinsprofile += 30;
747 v1 = G_VECTOR(OFS_PARM0);
748 v2 = G_VECTOR(OFS_PARM1);
749 move = G_FLOAT(OFS_PARM2);
750 ent = G_EDICT(OFS_PARM3);
752 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
754 pr_global_struct->trace_allsolid = trace.allsolid;
755 pr_global_struct->trace_startsolid = trace.startsolid;
756 pr_global_struct->trace_fraction = trace.fraction;
757 pr_global_struct->trace_inwater = trace.inwater;
758 pr_global_struct->trace_inopen = trace.inopen;
759 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
760 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
761 pr_global_struct->trace_plane_dist = trace.plane.dist;
763 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
765 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
766 // FIXME: add trace_endcontents
774 Used for use tracing and shot targeting
775 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
776 if the tryents flag is set.
778 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
781 // LordHavoc: added this for my own use, VERY useful, similar to traceline
782 void PF_tracebox (void)
784 float *v1, *v2, *m1, *m2;
789 pr_xfunction->builtinsprofile += 30;
791 v1 = G_VECTOR(OFS_PARM0);
792 m1 = G_VECTOR(OFS_PARM1);
793 m2 = G_VECTOR(OFS_PARM2);
794 v2 = G_VECTOR(OFS_PARM3);
795 move = G_FLOAT(OFS_PARM4);
796 ent = G_EDICT(OFS_PARM5);
798 trace = SV_Move (v1, m1, m2, v2, move, ent);
800 pr_global_struct->trace_allsolid = trace.allsolid;
801 pr_global_struct->trace_startsolid = trace.startsolid;
802 pr_global_struct->trace_fraction = trace.fraction;
803 pr_global_struct->trace_inwater = trace.inwater;
804 pr_global_struct->trace_inopen = trace.inopen;
805 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
806 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
807 pr_global_struct->trace_plane_dist = trace.plane.dist;
809 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
811 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
814 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
815 void PF_TraceToss (void)
821 pr_xfunction->builtinsprofile += 600;
823 ent = G_EDICT(OFS_PARM0);
824 if (ent == sv.edicts)
825 PF_WARNING("tracetoss: can not use world entity\n");
826 ignore = G_EDICT(OFS_PARM1);
828 trace = SV_Trace_Toss (ent, ignore);
830 pr_global_struct->trace_allsolid = trace.allsolid;
831 pr_global_struct->trace_startsolid = trace.startsolid;
832 pr_global_struct->trace_fraction = trace.fraction;
833 pr_global_struct->trace_inwater = trace.inwater;
834 pr_global_struct->trace_inopen = trace.inopen;
835 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
836 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
837 pr_global_struct->trace_plane_dist = trace.plane.dist;
839 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
841 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
849 Returns true if the given entity can move to the given position from it's
850 current position by walking or rolling.
852 scalar checkpos (entity, vector)
855 void PF_checkpos (void)
859 //============================================================================
862 qbyte checkpvs[MAX_MAP_LEAFS/8];
864 int PF_newcheckclient (int check)
870 // cycle to the next one
872 check = bound(1, check, svs.maxclients);
873 if (check == svs.maxclients)
881 pr_xfunction->builtinsprofile++;
883 if (i == svs.maxclients+1)
885 // look up the client's edict
887 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
888 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
890 // found a valid client (possibly the same one again)
894 // get the PVS for the entity
895 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
897 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
898 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
907 Returns a client (or object that has a client enemy) that would be a
910 If there is more than one valid option, they are cycled each frame
912 If (self.origin + self.viewofs) is not in the PVS of the current target,
913 it is not returned at all.
918 int c_invis, c_notvis;
919 void PF_checkclient (void)
924 // find a new check if on a new frame
925 if (sv.time - sv.lastchecktime >= 0.1)
927 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
928 sv.lastchecktime = sv.time;
931 // return check if it might be visible
932 ent = EDICT_NUM(sv.lastcheck);
933 if (ent->e->free || ent->v->health <= 0)
935 RETURN_EDICT(sv.edicts);
939 // if current entity can't possibly see the check entity, return 0
940 self = PROG_TO_EDICT(pr_global_struct->self);
941 VectorAdd(self->v->origin, self->v->view_ofs, view);
942 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
945 RETURN_EDICT(sv.edicts);
949 // might be able to see it
954 //============================================================================
961 Sends text over to the client's execution buffer
963 stuffcmd (clientent, value)
966 void PF_stuffcmd (void)
972 entnum = G_EDICTNUM(OFS_PARM0);
973 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
975 Con_Print("Can't stuffcmd to a non-client\n");
978 str = G_STRING(OFS_PARM1);
981 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
982 Host_ClientCommands ("%s", str);
990 Sends text to server console
995 void PF_localcmd (void)
997 Cbuf_AddText(G_STRING(OFS_PARM0));
1009 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1019 void PF_cvar_set (void)
1021 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1028 Returns a chain of entities that have origins within a spherical area
1030 findradius (origin, radius)
1033 void PF_findradius (void)
1035 edict_t *ent, *chain;
1042 chain = (edict_t *)sv.edicts;
1044 org = G_VECTOR(OFS_PARM0);
1045 radius = G_FLOAT(OFS_PARM1);
1046 radius2 = radius * radius;
1048 ent = NEXT_EDICT(sv.edicts);
1049 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1051 pr_xfunction->builtinsprofile++;
1054 if (ent->v->solid == SOLID_NOT)
1057 // LordHavoc: compare against bounding box rather than center,
1058 // and use DotProduct instead of Length, major speedup
1059 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1060 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1061 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1062 if (DotProduct(eorg, eorg) > radius2)
1065 ent->v->chain = EDICT_TO_PROG(chain);
1069 RETURN_EDICT(chain);
1078 void PF_dprint (void)
1080 char string[STRINGTEMP_LENGTH];
1081 if (developer.integer)
1083 PF_VarString(0, string, sizeof(string));
1092 v = G_FLOAT(OFS_PARM0);
1094 s = PR_GetTempString();
1095 if ((float)((int)v) == v)
1096 sprintf(s, "%i", (int)v);
1098 sprintf(s, "%f", v);
1099 G_INT(OFS_RETURN) = PR_SetString(s);
1105 v = G_FLOAT(OFS_PARM0);
1106 G_FLOAT(OFS_RETURN) = fabs(v);
1112 s = PR_GetTempString();
1113 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1114 G_INT(OFS_RETURN) = PR_SetString(s);
1120 s = PR_GetTempString();
1121 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1122 G_INT(OFS_RETURN) = PR_SetString(s);
1125 void PF_Spawn (void)
1128 pr_xfunction->builtinsprofile += 20;
1133 void PF_Remove (void)
1136 pr_xfunction->builtinsprofile += 20;
1138 ed = G_EDICT(OFS_PARM0);
1139 if (ed == sv.edicts)
1140 PF_WARNING("remove: tried to remove world\n");
1141 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1142 PF_WARNING("remove: tried to remove a client\n");
1143 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1144 if (ed->e->free && developer.integer)
1145 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1150 // entity (entity start, .string field, string match) find = #5;
1158 e = G_EDICTNUM(OFS_PARM0);
1159 f = G_INT(OFS_PARM1);
1160 s = G_STRING(OFS_PARM2);
1163 RETURN_EDICT(sv.edicts);
1167 for (e++ ; e < sv.num_edicts ; e++)
1169 pr_xfunction->builtinsprofile++;
1183 RETURN_EDICT(sv.edicts);
1186 // LordHavoc: added this for searching float, int, and entity reference fields
1187 void PF_FindFloat (void)
1194 e = G_EDICTNUM(OFS_PARM0);
1195 f = G_INT(OFS_PARM1);
1196 s = G_FLOAT(OFS_PARM2);
1198 for (e++ ; e < sv.num_edicts ; e++)
1200 pr_xfunction->builtinsprofile++;
1204 if (E_FLOAT(ed,f) == s)
1211 RETURN_EDICT(sv.edicts);
1214 // chained search for strings in entity fields
1215 // entity(.string field, string match) findchain = #402;
1216 void PF_findchain (void)
1221 edict_t *ent, *chain;
1223 chain = (edict_t *)sv.edicts;
1225 f = G_INT(OFS_PARM0);
1226 s = G_STRING(OFS_PARM1);
1229 RETURN_EDICT(sv.edicts);
1233 ent = NEXT_EDICT(sv.edicts);
1234 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1236 pr_xfunction->builtinsprofile++;
1239 t = E_STRING(ent,f);
1245 ent->v->chain = EDICT_TO_PROG(chain);
1249 RETURN_EDICT(chain);
1252 // LordHavoc: chained search for float, int, and entity reference fields
1253 // entity(.string field, float match) findchainfloat = #403;
1254 void PF_findchainfloat (void)
1259 edict_t *ent, *chain;
1261 chain = (edict_t *)sv.edicts;
1263 f = G_INT(OFS_PARM0);
1264 s = G_FLOAT(OFS_PARM1);
1266 ent = NEXT_EDICT(sv.edicts);
1267 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1269 pr_xfunction->builtinsprofile++;
1272 if (E_FLOAT(ent,f) != s)
1275 ent->v->chain = EDICT_TO_PROG(chain);
1279 RETURN_EDICT(chain);
1282 // LordHavoc: search for flags in float fields
1283 void PF_findflags (void)
1290 e = G_EDICTNUM(OFS_PARM0);
1291 f = G_INT(OFS_PARM1);
1292 s = (int)G_FLOAT(OFS_PARM2);
1294 for (e++ ; e < sv.num_edicts ; e++)
1296 pr_xfunction->builtinsprofile++;
1300 if ((int)E_FLOAT(ed,f) & s)
1307 RETURN_EDICT(sv.edicts);
1310 // LordHavoc: chained search for flags in float fields
1311 void PF_findchainflags (void)
1316 edict_t *ent, *chain;
1318 chain = (edict_t *)sv.edicts;
1320 f = G_INT(OFS_PARM0);
1321 s = (int)G_FLOAT(OFS_PARM1);
1323 ent = NEXT_EDICT(sv.edicts);
1324 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1326 pr_xfunction->builtinsprofile++;
1329 if (!((int)E_FLOAT(ent,f) & s))
1332 ent->v->chain = EDICT_TO_PROG(chain);
1336 RETURN_EDICT(chain);
1339 void PR_CheckEmptyString (char *s)
1342 PF_ERROR("Bad string");
1345 void PF_precache_file (void)
1346 { // precache_file is only used to copy files with qcc, it does nothing
1347 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1350 void PF_precache_sound (void)
1354 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1356 if (sv.state != ss_loading)
1357 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1359 s = G_STRING(OFS_PARM0);
1360 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1361 PR_CheckEmptyString (s);
1363 for (i=0 ; i<limit ; i++)
1365 if (!sv.sound_precache[i])
1367 sv.sound_precache[i] = s;
1370 if (!strcmp(sv.sound_precache[i], s))
1373 PF_ERROR("PF_precache_sound: overflow");
1376 void PF_precache_model (void)
1380 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1382 if (sv.state != ss_loading)
1383 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1385 s = G_STRING(OFS_PARM0);
1386 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1388 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1389 PR_CheckEmptyString (s);
1391 for (i = 0;i < limit;i++)
1393 if (!sv.model_precache[i])
1395 sv.model_precache[i] = s;
1396 sv.models[i] = Mod_ForName (s, true, false, false);
1399 if (!strcmp(sv.model_precache[i], s))
1402 PF_ERROR("PF_precache_model: overflow");
1406 void PF_coredump (void)
1411 void PF_traceon (void)
1416 void PF_traceoff (void)
1421 void PF_eprint (void)
1423 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1430 float(float yaw, float dist) walkmove
1433 void PF_walkmove (void)
1441 // assume failure if it returns early
1442 G_FLOAT(OFS_RETURN) = 0;
1444 ent = PROG_TO_EDICT(pr_global_struct->self);
1445 if (ent == sv.edicts)
1446 PF_WARNING("walkmove: can not modify world entity\n");
1448 PF_WARNING("walkmove: can not modify free entity\n");
1449 yaw = G_FLOAT(OFS_PARM0);
1450 dist = G_FLOAT(OFS_PARM1);
1452 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1455 yaw = yaw*M_PI*2 / 360;
1457 move[0] = cos(yaw)*dist;
1458 move[1] = sin(yaw)*dist;
1461 // save program state, because SV_movestep may call other progs
1462 oldf = pr_xfunction;
1463 oldself = pr_global_struct->self;
1465 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1468 // restore program state
1469 pr_xfunction = oldf;
1470 pr_global_struct->self = oldself;
1480 void PF_droptofloor (void)
1486 // assume failure if it returns early
1487 G_FLOAT(OFS_RETURN) = 0;
1489 ent = PROG_TO_EDICT(pr_global_struct->self);
1490 if (ent == sv.edicts)
1491 PF_WARNING("droptofloor: can not modify world entity\n");
1493 PF_WARNING("droptofloor: can not modify free entity\n");
1495 VectorCopy (ent->v->origin, end);
1498 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1500 if (trace.fraction != 1)
1502 VectorCopy (trace.endpos, ent->v->origin);
1503 SV_LinkEdict (ent, false);
1504 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1505 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1506 G_FLOAT(OFS_RETURN) = 1;
1507 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1508 ent->e->suspendedinairflag = true;
1516 void(float style, string value) lightstyle
1519 void PF_lightstyle (void)
1526 style = G_FLOAT(OFS_PARM0);
1527 val = G_STRING(OFS_PARM1);
1529 // change the string in sv
1530 sv.lightstyles[style] = val;
1532 // send message to all clients on this server
1533 if (sv.state != ss_active)
1536 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1538 if (client->netconnection)
1540 MSG_WriteChar (&client->message, svc_lightstyle);
1541 MSG_WriteChar (&client->message,style);
1542 MSG_WriteString (&client->message, val);
1550 f = G_FLOAT(OFS_PARM0);
1552 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1554 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1556 void PF_floor (void)
1558 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1562 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1571 void PF_checkbottom (void)
1573 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1581 void PF_pointcontents (void)
1583 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1590 entity nextent(entity)
1593 void PF_nextent (void)
1598 i = G_EDICTNUM(OFS_PARM0);
1601 pr_xfunction->builtinsprofile++;
1603 if (i == sv.num_edicts)
1605 RETURN_EDICT(sv.edicts);
1621 Pick a vector for the player to shoot along
1622 vector aim(entity, missilespeed)
1627 edict_t *ent, *check, *bestent;
1628 vec3_t start, dir, end, bestdir;
1631 float dist, bestdist;
1634 // assume failure if it returns early
1635 VectorClear(G_VECTOR(OFS_RETURN));
1637 ent = G_EDICT(OFS_PARM0);
1638 if (ent == sv.edicts)
1639 PF_WARNING("aim: can not use world entity\n");
1641 PF_WARNING("aim: can not use free entity\n");
1642 speed = G_FLOAT(OFS_PARM1);
1644 VectorCopy (ent->v->origin, start);
1647 // try sending a trace straight
1648 VectorCopy (pr_global_struct->v_forward, dir);
1649 VectorMA (start, 2048, dir, end);
1650 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1651 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1652 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1654 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1659 // try all possible entities
1660 VectorCopy (dir, bestdir);
1661 bestdist = sv_aim.value;
1664 check = NEXT_EDICT(sv.edicts);
1665 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1667 pr_xfunction->builtinsprofile++;
1668 if (check->v->takedamage != DAMAGE_AIM)
1672 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1673 continue; // don't aim at teammate
1674 for (j=0 ; j<3 ; j++)
1675 end[j] = check->v->origin[j]
1676 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1677 VectorSubtract (end, start, dir);
1678 VectorNormalize (dir);
1679 dist = DotProduct (dir, pr_global_struct->v_forward);
1680 if (dist < bestdist)
1681 continue; // to far to turn
1682 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1683 if (tr.ent == check)
1684 { // can shoot at this one
1692 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1693 dist = DotProduct (dir, pr_global_struct->v_forward);
1694 VectorScale (pr_global_struct->v_forward, dist, end);
1696 VectorNormalize (end);
1697 VectorCopy (end, G_VECTOR(OFS_RETURN));
1701 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1709 This was a major timewaster in progs, so it was converted to C
1712 void PF_changeyaw (void)
1715 float ideal, current, move, speed;
1717 ent = PROG_TO_EDICT(pr_global_struct->self);
1718 if (ent == sv.edicts)
1719 PF_WARNING("changeyaw: can not modify world entity\n");
1721 PF_WARNING("changeyaw: can not modify free entity\n");
1722 current = ANGLEMOD(ent->v->angles[1]);
1723 ideal = ent->v->ideal_yaw;
1724 speed = ent->v->yaw_speed;
1726 if (current == ideal)
1728 move = ideal - current;
1729 if (ideal > current)
1750 ent->v->angles[1] = ANGLEMOD (current + move);
1758 void PF_changepitch (void)
1761 float ideal, current, move, speed;
1764 ent = G_EDICT(OFS_PARM0);
1765 if (ent == sv.edicts)
1766 PF_WARNING("changepitch: can not modify world entity\n");
1768 PF_WARNING("changepitch: can not modify free entity\n");
1769 current = ANGLEMOD( ent->v->angles[0] );
1770 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1771 ideal = val->_float;
1774 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1777 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1778 speed = val->_float;
1781 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1785 if (current == ideal)
1787 move = ideal - current;
1788 if (ideal > current)
1809 ent->v->angles[0] = ANGLEMOD (current + move);
1813 ===============================================================================
1817 ===============================================================================
1820 #define MSG_BROADCAST 0 // unreliable to all
1821 #define MSG_ONE 1 // reliable to one (msg_entity)
1822 #define MSG_ALL 2 // reliable to all
1823 #define MSG_INIT 3 // write to the init string
1825 sizebuf_t *WriteDest (void)
1831 dest = G_FLOAT(OFS_PARM0);
1835 return &sv.datagram;
1838 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1839 entnum = NUM_FOR_EDICT(ent);
1840 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1841 Host_Error("WriteDest: tried to write to non-client\n");
1842 return &svs.clients[entnum-1].message;
1845 return &sv.reliable_datagram;
1851 Host_Error("WriteDest: bad destination");
1858 void PF_WriteByte (void)
1860 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1863 void PF_WriteChar (void)
1865 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1868 void PF_WriteShort (void)
1870 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1873 void PF_WriteLong (void)
1875 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1878 void PF_WriteAngle (void)
1880 if (sv.protocol == PROTOCOL_DARKPLACES5)
1881 MSG_WriteAngle16i (WriteDest(), G_FLOAT(OFS_PARM1));
1883 MSG_WriteAngle8i (WriteDest(), G_FLOAT(OFS_PARM1));
1886 void PF_WriteCoord (void)
1888 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1891 void PF_WriteString (void)
1893 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1897 void PF_WriteEntity (void)
1899 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1902 //=============================================================================
1904 void PF_makestatic (void)
1909 ent = G_EDICT(OFS_PARM0);
1910 if (ent == sv.edicts)
1911 PF_WARNING("makestatic: can not modify world entity\n");
1913 PF_WARNING("makestatic: can not modify free entity\n");
1916 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1921 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1922 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1923 MSG_WriteShort (&sv.signon, ent->v->frame);
1927 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1928 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1929 MSG_WriteByte (&sv.signon, ent->v->frame);
1932 MSG_WriteByte (&sv.signon, ent->v->colormap);
1933 MSG_WriteByte (&sv.signon, ent->v->skin);
1934 for (i=0 ; i<3 ; i++)
1936 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1937 MSG_WriteAngle8i(&sv.signon, ent->v->angles[i]);
1940 // throw the entity away now
1944 //=============================================================================
1951 void PF_setspawnparms (void)
1957 ent = G_EDICT(OFS_PARM0);
1958 i = NUM_FOR_EDICT(ent);
1959 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1961 Con_Print("tried to setspawnparms on a non-client\n");
1965 // copy spawn parms out of the client_t
1966 client = svs.clients + i-1;
1967 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1968 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1976 void PF_changelevel (void)
1980 // make sure we don't issue two changelevels
1981 if (svs.changelevel_issued)
1983 svs.changelevel_issued = true;
1985 s = G_STRING(OFS_PARM0);
1986 Cbuf_AddText (va("changelevel %s\n",s));
1991 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1996 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
2001 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2008 Returns a vector of length < 1
2013 void PF_randomvec (void)
2018 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2019 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2020 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2022 while (DotProduct(temp, temp) >= 1);
2023 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2030 Returns a color vector indicating the lighting at the requested point.
2032 (Internal Operation note: actually measures the light beneath the point, just like
2033 the model lighting on the client)
2038 void PF_GetLight (void)
2040 vec3_t ambientcolor, diffusecolor, diffusenormal;
2042 p = G_VECTOR(OFS_PARM0);
2043 VectorClear(ambientcolor);
2044 VectorClear(diffusecolor);
2045 VectorClear(diffusenormal);
2046 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2047 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2048 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2051 #define MAX_QC_CVARS 128
2052 cvar_t qc_cvar[MAX_QC_CVARS];
2055 void PF_registercvar (void)
2059 name = G_STRING(OFS_PARM0);
2060 value = G_STRING(OFS_PARM1);
2061 G_FLOAT(OFS_RETURN) = 0;
2062 // first check to see if it has already been defined
2063 if (Cvar_FindVar (name))
2066 // check for overlap with a command
2067 if (Cmd_Exists (name))
2069 Con_Printf("PF_registercvar: %s is a command\n", name);
2073 if (currentqc_cvar >= MAX_QC_CVARS)
2074 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2076 // copy the name and value
2077 variable = &qc_cvar[currentqc_cvar++];
2078 variable->name = Z_Malloc (strlen(name)+1);
2079 strcpy (variable->name, name);
2080 variable->string = Z_Malloc (strlen(value)+1);
2081 strcpy (variable->string, value);
2082 variable->value = atof (value);
2084 Cvar_RegisterVariable(variable);
2085 G_FLOAT(OFS_RETURN) = 1; // success
2092 returns the minimum of two supplied floats
2099 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2101 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2102 else if (pr_argc >= 3)
2105 float f = G_FLOAT(OFS_PARM0);
2106 for (i = 1;i < pr_argc;i++)
2107 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2108 f = G_FLOAT((OFS_PARM0+i*3));
2109 G_FLOAT(OFS_RETURN) = f;
2113 G_FLOAT(OFS_RETURN) = 0;
2114 PF_WARNING("min: must supply at least 2 floats\n");
2122 returns the maximum of two supplied floats
2129 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2131 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2132 else if (pr_argc >= 3)
2135 float f = G_FLOAT(OFS_PARM0);
2136 for (i = 1;i < pr_argc;i++)
2137 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2138 f = G_FLOAT((OFS_PARM0+i*3));
2139 G_FLOAT(OFS_RETURN) = f;
2143 G_FLOAT(OFS_RETURN) = 0;
2144 PF_WARNING("max: must supply at least 2 floats\n");
2152 returns number bounded by supplied range
2154 min(min, value, max)
2157 void PF_bound (void)
2159 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2166 returns a raised to power b
2173 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2180 copies data from one entity to another
2182 copyentity(src, dst)
2185 void PF_copyentity (void)
2188 in = G_EDICT(OFS_PARM0);
2189 if (in == sv.edicts)
2190 PF_WARNING("copyentity: can not read world entity\n");
2192 PF_WARNING("copyentity: can not read free entity\n");
2193 out = G_EDICT(OFS_PARM1);
2194 if (out == sv.edicts)
2195 PF_WARNING("copyentity: can not modify world entity\n");
2197 PF_WARNING("copyentity: can not modify free entity\n");
2198 memcpy(out->v, in->v, progs->entityfields * 4);
2205 sets the color of a client and broadcasts the update to all connected clients
2207 setcolor(clientent, value)
2210 void PF_setcolor (void)
2216 entnum = G_EDICTNUM(OFS_PARM0);
2217 i = G_FLOAT(OFS_PARM1);
2219 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2221 Con_Print("tried to setcolor a non-client\n");
2225 client = svs.clients + entnum-1;
2226 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2229 client->old_colors = i;
2230 client->edict->v->team = (i & 15) + 1;
2232 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2233 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2234 MSG_WriteByte (&sv.reliable_datagram, i);
2241 effect(origin, modelname, startframe, framecount, framerate)
2244 void PF_effect (void)
2248 s = G_STRING(OFS_PARM1);
2250 PF_WARNING("effect: no model specified\n");
2252 i = SV_ModelIndex(s);
2254 PF_WARNING("effect: model not precached\n");
2255 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2258 void PF_te_blood (void)
2260 if (G_FLOAT(OFS_PARM2) < 1)
2262 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263 MSG_WriteByte(&sv.datagram, TE_BLOOD);
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_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2270 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2271 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2273 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2276 void PF_te_bloodshower (void)
2278 if (G_FLOAT(OFS_PARM3) < 1)
2280 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2281 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2289 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2291 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2293 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2296 void PF_te_explosionrgb (void)
2298 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2301 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2305 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2306 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2307 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2310 void PF_te_particlecube (void)
2312 if (G_FLOAT(OFS_PARM3) < 1)
2314 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2315 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2317 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2318 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2319 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2321 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2322 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2323 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2325 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2326 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2329 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2331 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2332 // gravity true/false
2333 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2335 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2338 void PF_te_particlerain (void)
2340 if (G_FLOAT(OFS_PARM3) < 1)
2342 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2343 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2345 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2346 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2347 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2349 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2350 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2351 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2354 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2357 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2359 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2362 void PF_te_particlesnow (void)
2364 if (G_FLOAT(OFS_PARM3) < 1)
2366 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2367 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2369 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2370 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2373 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2374 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2375 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2377 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2378 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2379 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2381 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2383 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2386 void PF_te_spark (void)
2388 if (G_FLOAT(OFS_PARM2) < 1)
2390 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2391 MSG_WriteByte(&sv.datagram, TE_SPARK);
2393 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2394 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2395 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2397 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2398 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2399 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2401 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2404 void PF_te_gunshotquad (void)
2406 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2407 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2409 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2410 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2414 void PF_te_spikequad (void)
2416 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2417 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2419 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2420 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2421 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2424 void PF_te_superspikequad (void)
2426 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2427 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2429 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2430 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2431 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2434 void PF_te_explosionquad (void)
2436 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2437 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2439 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2440 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2441 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2444 void PF_te_smallflash (void)
2446 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2447 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2449 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2450 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2451 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2454 void PF_te_customflash (void)
2456 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2458 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2459 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
2465 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2467 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2469 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2470 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2471 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2474 void PF_te_gunshot (void)
2476 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2477 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2479 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2480 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2481 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2484 void PF_te_spike (void)
2486 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2487 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2489 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2490 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2491 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2494 void PF_te_superspike (void)
2496 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2497 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2499 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2500 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2501 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2504 void PF_te_explosion (void)
2506 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2507 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2509 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2510 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2511 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2514 void PF_te_tarexplosion (void)
2516 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2517 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2519 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2520 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2521 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2524 void PF_te_wizspike (void)
2526 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2527 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2529 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2530 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2531 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2534 void PF_te_knightspike (void)
2536 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2537 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2539 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2540 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2541 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2544 void PF_te_lavasplash (void)
2546 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2547 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2549 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2550 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2551 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2554 void PF_te_teleport (void)
2556 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2557 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2559 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2560 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2561 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2564 void PF_te_explosion2 (void)
2566 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2567 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2569 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2570 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2571 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2573 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2574 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2577 void PF_te_lightning1 (void)
2579 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2580 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2582 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2584 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2585 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2586 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2588 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2589 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2590 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2593 void PF_te_lightning2 (void)
2595 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2596 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2598 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2600 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2601 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2602 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2604 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2605 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2606 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2609 void PF_te_lightning3 (void)
2611 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2612 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2614 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2616 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2617 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2618 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2620 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2621 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2622 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2625 void PF_te_beam (void)
2627 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2628 MSG_WriteByte(&sv.datagram, TE_BEAM);
2630 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2632 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2633 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2634 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2636 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2637 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2638 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2641 void PF_te_plasmaburn (void)
2643 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2644 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2645 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2646 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2647 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2650 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2653 vec3_t v1, clipplanenormal, normal;
2654 vec_t clipplanedist, clipdist;
2656 if (surf->flags & SURF_PLANEBACK)
2657 VectorNegate(surf->plane->normal, normal);
2659 VectorCopy(surf->plane->normal, normal);
2660 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2662 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2663 VectorNormalizeFast(v1);
2664 CrossProduct(v1, normal, clipplanenormal);
2665 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2666 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2669 clipdist = -clipdist;
2670 VectorMA(out, clipdist, clipplanenormal, out);
2675 static msurface_t *getsurface(edict_t *ed, int surfnum)
2679 if (!ed || ed->e->free)
2681 modelindex = ed->v->modelindex;
2682 if (modelindex < 1 || modelindex >= MAX_MODELS)
2684 model = sv.models[modelindex];
2685 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2687 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2691 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2692 void PF_getsurfacenumpoints(void)
2695 // return 0 if no such surface
2696 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2698 G_FLOAT(OFS_RETURN) = 0;
2702 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2704 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2705 void PF_getsurfacepoint(void)
2710 VectorClear(G_VECTOR(OFS_RETURN));
2711 ed = G_EDICT(OFS_PARM0);
2712 if (!ed || ed->e->free)
2714 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2716 pointnum = G_FLOAT(OFS_PARM2);
2717 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2719 // FIXME: implement rotation/scaling
2720 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2722 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2723 void PF_getsurfacenormal(void)
2726 VectorClear(G_VECTOR(OFS_RETURN));
2727 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2729 // FIXME: implement rotation/scaling
2730 if (surf->flags & SURF_PLANEBACK)
2731 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2733 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2735 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2736 void PF_getsurfacetexture(void)
2739 G_INT(OFS_RETURN) = 0;
2740 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2742 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2744 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2745 void PF_getsurfacenearpoint(void)
2747 int surfnum, best, modelindex;
2749 vec_t dist, bestdist;
2754 G_FLOAT(OFS_RETURN) = -1;
2755 ed = G_EDICT(OFS_PARM0);
2756 point = G_VECTOR(OFS_PARM1);
2758 if (!ed || ed->e->free)
2760 modelindex = ed->v->modelindex;
2761 if (modelindex < 1 || modelindex >= MAX_MODELS)
2763 model = sv.models[modelindex];
2764 if (!model->brushq1.numsurfaces)
2767 // FIXME: implement rotation/scaling
2768 VectorSubtract(point, ed->v->origin, p);
2770 bestdist = 1000000000;
2771 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2773 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2774 dist = PlaneDiff(p, surf->plane);
2776 if (dist < bestdist)
2778 clippointtosurface(surf, p, clipped);
2779 VectorSubtract(clipped, p, clipped);
2780 dist += DotProduct(clipped, clipped);
2781 if (dist < bestdist)
2788 G_FLOAT(OFS_RETURN) = best;
2790 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2791 void PF_getsurfaceclippedpoint(void)
2796 VectorClear(G_VECTOR(OFS_RETURN));
2797 ed = G_EDICT(OFS_PARM0);
2798 if (!ed || ed->e->free)
2800 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2802 // FIXME: implement rotation/scaling
2803 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2804 clippointtosurface(surf, p, out);
2805 // FIXME: implement rotation/scaling
2806 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2809 #define MAX_PRFILES 256
2811 qfile_t *pr_files[MAX_PRFILES];
2813 void PR_Files_Init(void)
2815 memset(pr_files, 0, sizeof(pr_files));
2818 void PR_Files_CloseAll(void)
2821 for (i = 0;i < MAX_PRFILES;i++)
2824 FS_Close(pr_files[i]);
2829 //float(string s) stof = #81; // get numerical value from a string
2832 char string[STRINGTEMP_LENGTH];
2833 PF_VarString(0, string, sizeof(string));
2834 G_FLOAT(OFS_RETURN) = atof(string);
2837 //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
2840 int filenum, mode, i;
2841 char *modestring, *filename;
2842 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2843 if (pr_files[filenum] == NULL)
2845 if (filenum >= MAX_PRFILES)
2847 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2848 G_FLOAT(OFS_RETURN) = -2;
2851 mode = G_FLOAT(OFS_PARM1);
2854 case 0: // FILE_READ
2857 case 1: // FILE_APPEND
2860 case 2: // FILE_WRITE
2864 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2865 G_FLOAT(OFS_RETURN) = -3;
2868 filename = G_STRING(OFS_PARM0);
2869 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2870 // ../ is parent directory on many platforms
2871 // // is parent directory on Amiga
2872 // / at the beginning of a path is root on unix, and parent directory on Amiga
2873 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2874 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2875 for (i = 0;filename[i];i++)
2877 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2879 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);
2880 G_FLOAT(OFS_RETURN) = -4;
2884 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2886 if (pr_files[filenum] == NULL && modestring == "rb")
2887 pr_files[filenum] = FS_Open(filename, modestring, false);
2889 if (pr_files[filenum] == NULL)
2890 G_FLOAT(OFS_RETURN) = -1;
2892 G_FLOAT(OFS_RETURN) = filenum;
2895 //void(float fhandle) fclose = #111; // closes a file
2896 void PF_fclose(void)
2898 int filenum = G_FLOAT(OFS_PARM0);
2899 if (filenum < 0 || filenum >= MAX_PRFILES)
2901 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2904 if (pr_files[filenum] == NULL)
2906 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2909 FS_Close(pr_files[filenum]);
2910 pr_files[filenum] = NULL;
2913 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2917 static char string[STRINGTEMP_LENGTH];
2918 int filenum = G_FLOAT(OFS_PARM0);
2919 if (filenum < 0 || filenum >= MAX_PRFILES)
2921 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2924 if (pr_files[filenum] == NULL)
2926 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2932 c = FS_Getc(pr_files[filenum]);
2933 if (c == '\r' || c == '\n' || c < 0)
2935 if (end < STRINGTEMP_LENGTH - 1)
2939 // remove \n following \r
2941 c = FS_Getc(pr_files[filenum]);
2942 if (developer.integer)
2943 Con_Printf("fgets: %s\n", string);
2945 G_INT(OFS_RETURN) = PR_SetString(string);
2947 G_INT(OFS_RETURN) = 0;
2950 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2954 char string[STRINGTEMP_LENGTH];
2955 int filenum = G_FLOAT(OFS_PARM0);
2956 if (filenum < 0 || filenum >= MAX_PRFILES)
2958 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2961 if (pr_files[filenum] == NULL)
2963 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2966 PF_VarString(1, string, sizeof(string));
2967 if ((stringlength = strlen(string)))
2968 FS_Write(pr_files[filenum], string, stringlength);
2969 if (developer.integer)
2970 Con_Printf("fputs: %s\n", string);
2973 //float(string s) strlen = #114; // returns how many characters are in a string
2974 void PF_strlen(void)
2977 s = G_STRING(OFS_PARM0);
2979 G_FLOAT(OFS_RETURN) = strlen(s);
2981 G_FLOAT(OFS_RETURN) = 0;
2984 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2985 void PF_strcat(void)
2987 char *s = PR_GetTempString();
2988 PF_VarString(0, s, STRINGTEMP_LENGTH);
2989 G_INT(OFS_RETURN) = PR_SetString(s);
2992 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2993 void PF_substring(void)
2995 int i, start, length;
2996 char *s, *string = PR_GetTempString();
2997 s = G_STRING(OFS_PARM0);
2998 start = G_FLOAT(OFS_PARM1);
2999 length = G_FLOAT(OFS_PARM2);
3002 for (i = 0;i < start && *s;i++, s++);
3003 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
3006 G_INT(OFS_RETURN) = PR_SetString(string);
3009 //vector(string s) stov = #117; // returns vector value from a string
3012 char string[STRINGTEMP_LENGTH];
3013 PF_VarString(0, string, sizeof(string));
3014 Math_atov(string, G_VECTOR(OFS_RETURN));
3017 //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)
3018 void PF_strzone(void)
3021 in = G_STRING(OFS_PARM0);
3022 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3024 G_INT(OFS_RETURN) = PR_SetString(out);
3027 //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!!!)
3028 void PF_strunzone(void)
3030 Mem_Free(G_STRING(OFS_PARM0));
3033 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3034 //this function originally written by KrimZon, made shorter by LordHavoc
3035 void PF_clientcommand (void)
3037 client_t *temp_client;
3040 //find client for this entity
3041 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3042 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3044 Con_Print("PF_clientcommand: entity is not a client\n");
3048 temp_client = host_client;
3049 host_client = svs.clients + i;
3050 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3051 host_client = temp_client;
3054 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3055 //this function originally written by KrimZon, made shorter by LordHavoc
3056 //20040203: rewritten by LordHavoc (no longer uses allocations)
3058 char *tokens[256], tokenbuf[4096];
3059 void PF_tokenize (void)
3063 p = G_STRING(OFS_PARM0);
3067 while(COM_ParseToken(&p, false))
3069 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3071 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3073 tokens[num_tokens++] = tokenbuf + pos;
3074 strcpy(tokenbuf + pos, com_token);
3075 pos += strlen(com_token) + 1;
3078 G_FLOAT(OFS_RETURN) = num_tokens;
3081 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3082 //this function originally written by KrimZon, made shorter by LordHavoc
3085 int token_num = G_FLOAT(OFS_PARM0);
3086 if (token_num >= 0 && token_num < num_tokens)
3087 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3089 G_INT(OFS_RETURN) = PR_SetString("");
3092 //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)
3093 void PF_setattachment (void)
3095 edict_t *e = G_EDICT(OFS_PARM0);
3096 edict_t *tagentity = G_EDICT(OFS_PARM1);
3097 char *tagname = G_STRING(OFS_PARM2);
3103 PF_WARNING("setattachment: can not modify world entity\n");
3105 PF_WARNING("setattachment: can not modify free entity\n");
3107 if (tagentity == NULL)
3108 tagentity = sv.edicts;
3110 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3112 v->edict = EDICT_TO_PROG(tagentity);
3114 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3117 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3119 modelindex = (int)tagentity->v->modelindex;
3120 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3122 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3123 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3124 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3126 // FIXME: use a model function to get tag info (need to handle skeletal)
3127 if (v->_float == 0 && model->alias.aliasnum_tags)
3128 for (i = 0;i < model->alias.aliasnum_tags;i++)
3129 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3132 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);
3135 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));
3140 /////////////////////////////////////////
3141 // DP_QC_FS_SEARCH extension
3143 // qc fs search handling
3144 #define MAX_SEARCHES 128
3146 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3148 void PR_Search_Init(void)
3150 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3153 void PR_Search_Reset(void)
3156 // reset the fssearch list
3157 for(i = 0; i < MAX_SEARCHES; i++)
3158 if(pr_fssearchlist[i])
3159 FS_FreeSearch(pr_fssearchlist[i]);
3160 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3167 float search_begin(string pattern, float caseinsensitive, float quiet)
3170 void PF_search_begin(void)
3174 int caseinsens, quiet;
3176 pattern = G_STRING(OFS_PARM0);
3178 PR_CheckEmptyString(pattern);
3180 caseinsens = G_FLOAT(OFS_PARM1);
3181 quiet = G_FLOAT(OFS_PARM2);
3183 for(handle = 0; handle < MAX_SEARCHES; handle++)
3184 if(!pr_fssearchlist[handle])
3187 if(handle >= MAX_SEARCHES)
3189 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3190 G_FLOAT(OFS_RETURN) = -2;
3194 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3195 G_FLOAT(OFS_RETURN) = -1;
3197 G_FLOAT(OFS_RETURN) = handle;
3204 void search_end(float handle)
3207 void PF_search_end(void)
3211 handle = G_FLOAT(OFS_PARM0);
3213 if(handle < 0 || handle >= MAX_SEARCHES)
3215 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3218 if(pr_fssearchlist[handle] == NULL)
3220 Con_Printf("PF_search_end: no such handle %i\n", handle);
3224 FS_FreeSearch(pr_fssearchlist[handle]);
3225 pr_fssearchlist[handle] = NULL;
3232 float search_getsize(float handle)
3235 void PF_search_getsize(void)
3239 handle = G_FLOAT(OFS_PARM0);
3241 if(handle < 0 || handle >= MAX_SEARCHES)
3243 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3246 if(pr_fssearchlist[handle] == NULL)
3248 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3252 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3257 VM_search_getfilename
3259 string search_getfilename(float handle, float num)
3262 void PF_search_getfilename(void)
3264 int handle, filenum;
3267 handle = G_FLOAT(OFS_PARM0);
3268 filenum = G_FLOAT(OFS_PARM1);
3270 if(handle < 0 || handle >= MAX_SEARCHES)
3272 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3275 if(pr_fssearchlist[handle] == NULL)
3277 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3280 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3282 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3286 tmp = PR_GetTempString();
3287 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3289 G_INT(OFS_RETURN) = PR_SetString(tmp);
3292 void PF_cvar_string (void)
3298 str = G_STRING(OFS_PARM0);
3299 var = Cvar_FindVar (str);
3301 tmp = PR_GetTempString();
3302 strcpy(tmp, var->string);
3304 G_INT(OFS_RETURN) = PR_SetString(tmp);
3309 builtin_t pr_builtin[] =
3312 PF_makevectors, // #1 void(entity e) makevectors
3313 PF_setorigin, // #2 void(entity e, vector o) setorigin
3314 PF_setmodel, // #3 void(entity e, string m) setmodel
3315 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3316 NULL, // #5 void(entity e, vector min, vector max) setabssize
3317 PF_break, // #6 void() break
3318 PF_random, // #7 float() random
3319 PF_sound, // #8 void(entity e, float chan, string samp) sound
3320 PF_normalize, // #9 vector(vector v) normalize
3321 PF_error, // #10 void(string e) error
3322 PF_objerror, // #11 void(string e) objerror
3323 PF_vlen, // #12 float(vector v) vlen
3324 PF_vectoyaw, // #13 float(vector v) vectoyaw
3325 PF_Spawn, // #14 entity() spawn
3326 PF_Remove, // #15 void(entity e) remove
3327 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3328 PF_checkclient, // #17 entity() clientlist
3329 PF_Find, // #18 entity(entity start, .string fld, string match) find
3330 PF_precache_sound, // #19 void(string s) precache_sound
3331 PF_precache_model, // #20 void(string s) precache_model
3332 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3333 PF_findradius, // #22 entity(vector org, float rad) findradius
3334 PF_bprint, // #23 void(string s) bprint
3335 PF_sprint, // #24 void(entity client, string s) sprint
3336 PF_dprint, // #25 void(string s) dprint
3337 PF_ftos, // #26 void(string s) ftos
3338 PF_vtos, // #27 void(string s) vtos
3339 PF_coredump, // #28 void() coredump
3340 PF_traceon, // #29 void() traceon
3341 PF_traceoff, // #30 void() traceoff
3342 PF_eprint, // #31 void(entity e) eprint
3343 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3345 PF_droptofloor, // #34 float() droptofloor
3346 PF_lightstyle, // #35 void(float style, string value) lightstyle
3347 PF_rint, // #36 float(float v) rint
3348 PF_floor, // #37 float(float v) floor
3349 PF_ceil, // #38 float(float v) ceil
3351 PF_checkbottom, // #40 float(entity e) checkbottom
3352 PF_pointcontents , // #41 float(vector v) pointcontents
3354 PF_fabs, // #43 float(float f) fabs
3355 PF_aim, // #44 vector(entity e, float speed) aim
3356 PF_cvar, // #45 float(string s) cvar
3357 PF_localcmd, // #46 void(string s) localcmd
3358 PF_nextent, // #47 entity(entity e) nextent
3359 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3360 PF_changeyaw, // #49 void() ChangeYaw
3362 PF_vectoangles, // #51 vector(vector v) vectoangles
3363 PF_WriteByte, // #52 void(float to, float f) WriteByte
3364 PF_WriteChar, // #53 void(float to, float f) WriteChar
3365 PF_WriteShort, // #54 void(float to, float f) WriteShort
3366 PF_WriteLong, // #55 void(float to, float f) WriteLong
3367 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3368 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3369 PF_WriteString, // #58 void(float to, string s) WriteString
3370 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3371 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3372 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3373 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3374 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3375 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3376 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3378 SV_MoveToGoal, // #67 void(float step) movetogoal
3379 PF_precache_file, // #68 string(string s) precache_file
3380 PF_makestatic, // #69 void(entity e) makestatic
3381 PF_changelevel, // #70 void(string s) changelevel
3383 PF_cvar_set, // #72 void(string var, string val) cvar_set
3384 PF_centerprint, // #73 void(entity client, strings) centerprint
3385 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3386 PF_precache_model, // #75 string(string s) precache_model2
3387 PF_precache_sound, // #76 string(string s) precache_sound2
3388 PF_precache_file, // #77 string(string s) precache_file2
3389 PF_setspawnparms, // #78 void(entity e) setspawnparms
3392 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3401 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3402 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3403 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3404 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3405 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3406 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3407 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3408 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3409 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3410 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3421 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3422 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3423 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3424 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3425 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3426 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3427 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3428 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3429 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3430 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3431 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3432 a a a a a a a a // #120-199
3433 a a a a a a a a a a // #200-299
3434 a a a a a a a a a a // #300-399
3435 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3436 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3437 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3438 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3439 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3440 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3441 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3442 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3443 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3444 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3445 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3446 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3447 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3448 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3449 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3450 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3451 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3452 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3453 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3454 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3455 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3456 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3457 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3458 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3459 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3460 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3461 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3462 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3463 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3464 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3465 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3466 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3467 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3468 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3469 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3470 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3471 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3472 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3473 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3474 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3475 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3476 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3477 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3478 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3479 PF_search_begin, // #444
3480 PF_search_end, // #445
3481 PF_search_getsize, // #446
3482 PF_search_getfilename, // #447
3483 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3484 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3485 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3495 a a a a // #460-499 (LordHavoc)
3498 builtin_t *pr_builtins = pr_builtin;
3499 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3501 void PR_Cmd_Init(void)
3503 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3508 void PR_Cmd_Reset(void)
3510 Mem_EmptyPool(pr_strings_mempool);
3512 PR_Files_CloseAll();