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;
633 int i, soundnum, large;
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 for (i=0 ; i<3 ; i++)
663 MSG_WriteDPCoord(&sv.signon, pos[i]);
666 MSG_WriteShort (&sv.signon, soundnum);
668 MSG_WriteByte (&sv.signon, soundnum);
670 MSG_WriteByte (&sv.signon, vol*255);
671 MSG_WriteByte (&sv.signon, attenuation*64);
679 Each entity can have eight independant sound sources, like voice,
682 Channel 0 is an auto-allocate channel, the others override anything
683 already running on that entity/channel pair.
685 An attenuation of 0 will play full volume everywhere in the level.
686 Larger attenuations will drop off.
698 entity = G_EDICT(OFS_PARM0);
699 channel = G_FLOAT(OFS_PARM1);
700 sample = G_STRING(OFS_PARM2);
701 volume = G_FLOAT(OFS_PARM3) * 255;
702 attenuation = G_FLOAT(OFS_PARM4);
704 if (volume < 0 || volume > 255)
705 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
707 if (attenuation < 0 || attenuation > 4)
708 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
710 if (channel < 0 || channel > 7)
711 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
713 SV_StartSound (entity, channel, sample, volume, attenuation);
725 PF_ERROR("break: break statement\n");
732 Used for use tracing and shot targeting
733 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
734 if the tryents flag is set.
736 traceline (vector1, vector2, tryents)
739 void PF_traceline (void)
746 pr_xfunction->builtinsprofile += 30;
748 v1 = G_VECTOR(OFS_PARM0);
749 v2 = G_VECTOR(OFS_PARM1);
750 move = G_FLOAT(OFS_PARM2);
751 ent = G_EDICT(OFS_PARM3);
753 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
755 pr_global_struct->trace_allsolid = trace.allsolid;
756 pr_global_struct->trace_startsolid = trace.startsolid;
757 pr_global_struct->trace_fraction = trace.fraction;
758 pr_global_struct->trace_inwater = trace.inwater;
759 pr_global_struct->trace_inopen = trace.inopen;
760 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
761 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
762 pr_global_struct->trace_plane_dist = trace.plane.dist;
764 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
766 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
767 // FIXME: add trace_endcontents
775 Used for use tracing and shot targeting
776 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
777 if the tryents flag is set.
779 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
782 // LordHavoc: added this for my own use, VERY useful, similar to traceline
783 void PF_tracebox (void)
785 float *v1, *v2, *m1, *m2;
790 pr_xfunction->builtinsprofile += 30;
792 v1 = G_VECTOR(OFS_PARM0);
793 m1 = G_VECTOR(OFS_PARM1);
794 m2 = G_VECTOR(OFS_PARM2);
795 v2 = G_VECTOR(OFS_PARM3);
796 move = G_FLOAT(OFS_PARM4);
797 ent = G_EDICT(OFS_PARM5);
799 trace = SV_Move (v1, m1, m2, v2, move, ent);
801 pr_global_struct->trace_allsolid = trace.allsolid;
802 pr_global_struct->trace_startsolid = trace.startsolid;
803 pr_global_struct->trace_fraction = trace.fraction;
804 pr_global_struct->trace_inwater = trace.inwater;
805 pr_global_struct->trace_inopen = trace.inopen;
806 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
807 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
808 pr_global_struct->trace_plane_dist = trace.plane.dist;
810 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
812 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
815 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
816 void PF_TraceToss (void)
822 pr_xfunction->builtinsprofile += 600;
824 ent = G_EDICT(OFS_PARM0);
825 if (ent == sv.edicts)
826 PF_WARNING("tracetoss: can not use world entity\n");
827 ignore = G_EDICT(OFS_PARM1);
829 trace = SV_Trace_Toss (ent, ignore);
831 pr_global_struct->trace_allsolid = trace.allsolid;
832 pr_global_struct->trace_startsolid = trace.startsolid;
833 pr_global_struct->trace_fraction = trace.fraction;
834 pr_global_struct->trace_inwater = trace.inwater;
835 pr_global_struct->trace_inopen = trace.inopen;
836 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
837 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
838 pr_global_struct->trace_plane_dist = trace.plane.dist;
840 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
842 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
850 Returns true if the given entity can move to the given position from it's
851 current position by walking or rolling.
853 scalar checkpos (entity, vector)
856 void PF_checkpos (void)
860 //============================================================================
863 qbyte checkpvs[MAX_MAP_LEAFS/8];
865 int PF_newcheckclient (int check)
871 // cycle to the next one
873 check = bound(1, check, svs.maxclients);
874 if (check == svs.maxclients)
882 pr_xfunction->builtinsprofile++;
884 if (i == svs.maxclients+1)
886 // look up the client's edict
888 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
889 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
891 // found a valid client (possibly the same one again)
895 // get the PVS for the entity
896 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
898 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
899 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
908 Returns a client (or object that has a client enemy) that would be a
911 If there is more than one valid option, they are cycled each frame
913 If (self.origin + self.viewofs) is not in the PVS of the current target,
914 it is not returned at all.
919 int c_invis, c_notvis;
920 void PF_checkclient (void)
925 // find a new check if on a new frame
926 if (sv.time - sv.lastchecktime >= 0.1)
928 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
929 sv.lastchecktime = sv.time;
932 // return check if it might be visible
933 ent = EDICT_NUM(sv.lastcheck);
934 if (ent->e->free || ent->v->health <= 0)
936 RETURN_EDICT(sv.edicts);
940 // if current entity can't possibly see the check entity, return 0
941 self = PROG_TO_EDICT(pr_global_struct->self);
942 VectorAdd(self->v->origin, self->v->view_ofs, view);
943 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
946 RETURN_EDICT(sv.edicts);
950 // might be able to see it
955 //============================================================================
962 Sends text over to the client's execution buffer
964 stuffcmd (clientent, value)
967 void PF_stuffcmd (void)
973 entnum = G_EDICTNUM(OFS_PARM0);
974 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
976 Con_Print("Can't stuffcmd to a non-client\n");
979 str = G_STRING(OFS_PARM1);
982 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
983 Host_ClientCommands ("%s", str);
991 Sends text to server console
996 void PF_localcmd (void)
998 Cbuf_AddText(G_STRING(OFS_PARM0));
1010 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1020 void PF_cvar_set (void)
1022 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1029 Returns a chain of entities that have origins within a spherical area
1031 findradius (origin, radius)
1034 void PF_findradius (void)
1036 edict_t *ent, *chain;
1043 chain = (edict_t *)sv.edicts;
1045 org = G_VECTOR(OFS_PARM0);
1046 radius = G_FLOAT(OFS_PARM1);
1047 radius2 = radius * radius;
1049 ent = NEXT_EDICT(sv.edicts);
1050 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1052 pr_xfunction->builtinsprofile++;
1055 if (ent->v->solid == SOLID_NOT)
1058 // LordHavoc: compare against bounding box rather than center,
1059 // and use DotProduct instead of Length, major speedup
1060 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1061 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1062 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1063 if (DotProduct(eorg, eorg) > radius2)
1066 ent->v->chain = EDICT_TO_PROG(chain);
1070 RETURN_EDICT(chain);
1079 void PF_dprint (void)
1081 char string[STRINGTEMP_LENGTH];
1082 if (developer.integer)
1084 PF_VarString(0, string, sizeof(string));
1093 v = G_FLOAT(OFS_PARM0);
1095 s = PR_GetTempString();
1096 if ((float)((int)v) == v)
1097 sprintf(s, "%i", (int)v);
1099 sprintf(s, "%f", v);
1100 G_INT(OFS_RETURN) = PR_SetString(s);
1106 v = G_FLOAT(OFS_PARM0);
1107 G_FLOAT(OFS_RETURN) = fabs(v);
1113 s = PR_GetTempString();
1114 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1115 G_INT(OFS_RETURN) = PR_SetString(s);
1121 s = PR_GetTempString();
1122 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1123 G_INT(OFS_RETURN) = PR_SetString(s);
1126 void PF_Spawn (void)
1129 pr_xfunction->builtinsprofile += 20;
1134 void PF_Remove (void)
1137 pr_xfunction->builtinsprofile += 20;
1139 ed = G_EDICT(OFS_PARM0);
1140 if (ed == sv.edicts)
1141 PF_WARNING("remove: tried to remove world\n");
1142 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1143 PF_WARNING("remove: tried to remove a client\n");
1144 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1145 if (ed->e->free && developer.integer)
1146 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1151 // entity (entity start, .string field, string match) find = #5;
1159 e = G_EDICTNUM(OFS_PARM0);
1160 f = G_INT(OFS_PARM1);
1161 s = G_STRING(OFS_PARM2);
1164 RETURN_EDICT(sv.edicts);
1168 for (e++ ; e < sv.num_edicts ; e++)
1170 pr_xfunction->builtinsprofile++;
1184 RETURN_EDICT(sv.edicts);
1187 // LordHavoc: added this for searching float, int, and entity reference fields
1188 void PF_FindFloat (void)
1195 e = G_EDICTNUM(OFS_PARM0);
1196 f = G_INT(OFS_PARM1);
1197 s = G_FLOAT(OFS_PARM2);
1199 for (e++ ; e < sv.num_edicts ; e++)
1201 pr_xfunction->builtinsprofile++;
1205 if (E_FLOAT(ed,f) == s)
1212 RETURN_EDICT(sv.edicts);
1215 // chained search for strings in entity fields
1216 // entity(.string field, string match) findchain = #402;
1217 void PF_findchain (void)
1222 edict_t *ent, *chain;
1224 chain = (edict_t *)sv.edicts;
1226 f = G_INT(OFS_PARM0);
1227 s = G_STRING(OFS_PARM1);
1230 RETURN_EDICT(sv.edicts);
1234 ent = NEXT_EDICT(sv.edicts);
1235 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1237 pr_xfunction->builtinsprofile++;
1240 t = E_STRING(ent,f);
1246 ent->v->chain = EDICT_TO_PROG(chain);
1250 RETURN_EDICT(chain);
1253 // LordHavoc: chained search for float, int, and entity reference fields
1254 // entity(.string field, float match) findchainfloat = #403;
1255 void PF_findchainfloat (void)
1260 edict_t *ent, *chain;
1262 chain = (edict_t *)sv.edicts;
1264 f = G_INT(OFS_PARM0);
1265 s = G_FLOAT(OFS_PARM1);
1267 ent = NEXT_EDICT(sv.edicts);
1268 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1270 pr_xfunction->builtinsprofile++;
1273 if (E_FLOAT(ent,f) != s)
1276 ent->v->chain = EDICT_TO_PROG(chain);
1280 RETURN_EDICT(chain);
1283 // LordHavoc: search for flags in float fields
1284 void PF_findflags (void)
1291 e = G_EDICTNUM(OFS_PARM0);
1292 f = G_INT(OFS_PARM1);
1293 s = (int)G_FLOAT(OFS_PARM2);
1295 for (e++ ; e < sv.num_edicts ; e++)
1297 pr_xfunction->builtinsprofile++;
1301 if ((int)E_FLOAT(ed,f) & s)
1308 RETURN_EDICT(sv.edicts);
1311 // LordHavoc: chained search for flags in float fields
1312 void PF_findchainflags (void)
1317 edict_t *ent, *chain;
1319 chain = (edict_t *)sv.edicts;
1321 f = G_INT(OFS_PARM0);
1322 s = (int)G_FLOAT(OFS_PARM1);
1324 ent = NEXT_EDICT(sv.edicts);
1325 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1327 pr_xfunction->builtinsprofile++;
1330 if (!((int)E_FLOAT(ent,f) & s))
1333 ent->v->chain = EDICT_TO_PROG(chain);
1337 RETURN_EDICT(chain);
1340 void PR_CheckEmptyString (char *s)
1343 PF_ERROR("Bad string");
1346 void PF_precache_file (void)
1347 { // precache_file is only used to copy files with qcc, it does nothing
1348 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1351 void PF_precache_sound (void)
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<MAX_SOUNDS ; 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)
1381 if (sv.state != ss_loading)
1382 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1384 s = G_STRING(OFS_PARM0);
1385 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1387 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1388 PR_CheckEmptyString (s);
1390 for (i=0 ; i<MAX_MODELS ; i++)
1392 if (!sv.model_precache[i])
1394 sv.model_precache[i] = s;
1395 sv.models[i] = Mod_ForName (s, true, false, false);
1398 if (!strcmp(sv.model_precache[i], s))
1401 PF_ERROR("PF_precache_model: overflow");
1405 void PF_coredump (void)
1410 void PF_traceon (void)
1415 void PF_traceoff (void)
1420 void PF_eprint (void)
1422 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1429 float(float yaw, float dist) walkmove
1432 void PF_walkmove (void)
1440 // assume failure if it returns early
1441 G_FLOAT(OFS_RETURN) = 0;
1443 ent = PROG_TO_EDICT(pr_global_struct->self);
1444 if (ent == sv.edicts)
1445 PF_WARNING("walkmove: can not modify world entity\n");
1447 PF_WARNING("walkmove: can not modify free entity\n");
1448 yaw = G_FLOAT(OFS_PARM0);
1449 dist = G_FLOAT(OFS_PARM1);
1451 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1454 yaw = yaw*M_PI*2 / 360;
1456 move[0] = cos(yaw)*dist;
1457 move[1] = sin(yaw)*dist;
1460 // save program state, because SV_movestep may call other progs
1461 oldf = pr_xfunction;
1462 oldself = pr_global_struct->self;
1464 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1467 // restore program state
1468 pr_xfunction = oldf;
1469 pr_global_struct->self = oldself;
1479 void PF_droptofloor (void)
1485 // assume failure if it returns early
1486 G_FLOAT(OFS_RETURN) = 0;
1488 ent = PROG_TO_EDICT(pr_global_struct->self);
1489 if (ent == sv.edicts)
1490 PF_WARNING("droptofloor: can not modify world entity\n");
1492 PF_WARNING("droptofloor: can not modify free entity\n");
1494 VectorCopy (ent->v->origin, end);
1497 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1499 if (trace.fraction != 1)
1501 VectorCopy (trace.endpos, ent->v->origin);
1502 SV_LinkEdict (ent, false);
1503 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1504 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1505 G_FLOAT(OFS_RETURN) = 1;
1506 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1507 ent->e->suspendedinairflag = true;
1515 void(float style, string value) lightstyle
1518 void PF_lightstyle (void)
1525 style = G_FLOAT(OFS_PARM0);
1526 val = G_STRING(OFS_PARM1);
1528 // change the string in sv
1529 sv.lightstyles[style] = val;
1531 // send message to all clients on this server
1532 if (sv.state != ss_active)
1535 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1537 if (client->netconnection)
1539 MSG_WriteChar (&client->message, svc_lightstyle);
1540 MSG_WriteChar (&client->message,style);
1541 MSG_WriteString (&client->message, val);
1549 f = G_FLOAT(OFS_PARM0);
1551 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1553 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1555 void PF_floor (void)
1557 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1561 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1570 void PF_checkbottom (void)
1572 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1580 void PF_pointcontents (void)
1582 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1589 entity nextent(entity)
1592 void PF_nextent (void)
1597 i = G_EDICTNUM(OFS_PARM0);
1600 pr_xfunction->builtinsprofile++;
1602 if (i == sv.num_edicts)
1604 RETURN_EDICT(sv.edicts);
1620 Pick a vector for the player to shoot along
1621 vector aim(entity, missilespeed)
1626 edict_t *ent, *check, *bestent;
1627 vec3_t start, dir, end, bestdir;
1630 float dist, bestdist;
1633 // assume failure if it returns early
1634 VectorClear(G_VECTOR(OFS_RETURN));
1636 ent = G_EDICT(OFS_PARM0);
1637 if (ent == sv.edicts)
1638 PF_WARNING("aim: can not use world entity\n");
1640 PF_WARNING("aim: can not use free entity\n");
1641 speed = G_FLOAT(OFS_PARM1);
1643 VectorCopy (ent->v->origin, start);
1646 // try sending a trace straight
1647 VectorCopy (pr_global_struct->v_forward, dir);
1648 VectorMA (start, 2048, dir, end);
1649 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1650 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1651 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1653 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1658 // try all possible entities
1659 VectorCopy (dir, bestdir);
1660 bestdist = sv_aim.value;
1663 check = NEXT_EDICT(sv.edicts);
1664 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1666 pr_xfunction->builtinsprofile++;
1667 if (check->v->takedamage != DAMAGE_AIM)
1671 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1672 continue; // don't aim at teammate
1673 for (j=0 ; j<3 ; j++)
1674 end[j] = check->v->origin[j]
1675 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1676 VectorSubtract (end, start, dir);
1677 VectorNormalize (dir);
1678 dist = DotProduct (dir, pr_global_struct->v_forward);
1679 if (dist < bestdist)
1680 continue; // to far to turn
1681 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1682 if (tr.ent == check)
1683 { // can shoot at this one
1691 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1692 dist = DotProduct (dir, pr_global_struct->v_forward);
1693 VectorScale (pr_global_struct->v_forward, dist, end);
1695 VectorNormalize (end);
1696 VectorCopy (end, G_VECTOR(OFS_RETURN));
1700 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1708 This was a major timewaster in progs, so it was converted to C
1711 void PF_changeyaw (void)
1714 float ideal, current, move, speed;
1716 ent = PROG_TO_EDICT(pr_global_struct->self);
1717 if (ent == sv.edicts)
1718 PF_WARNING("changeyaw: can not modify world entity\n");
1720 PF_WARNING("changeyaw: can not modify free entity\n");
1721 current = ANGLEMOD(ent->v->angles[1]);
1722 ideal = ent->v->ideal_yaw;
1723 speed = ent->v->yaw_speed;
1725 if (current == ideal)
1727 move = ideal - current;
1728 if (ideal > current)
1749 ent->v->angles[1] = ANGLEMOD (current + move);
1757 void PF_changepitch (void)
1760 float ideal, current, move, speed;
1763 ent = G_EDICT(OFS_PARM0);
1764 if (ent == sv.edicts)
1765 PF_WARNING("changepitch: can not modify world entity\n");
1767 PF_WARNING("changepitch: can not modify free entity\n");
1768 current = ANGLEMOD( ent->v->angles[0] );
1769 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1770 ideal = val->_float;
1773 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1776 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1777 speed = val->_float;
1780 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1784 if (current == ideal)
1786 move = ideal - current;
1787 if (ideal > current)
1808 ent->v->angles[0] = ANGLEMOD (current + move);
1812 ===============================================================================
1816 ===============================================================================
1819 #define MSG_BROADCAST 0 // unreliable to all
1820 #define MSG_ONE 1 // reliable to one (msg_entity)
1821 #define MSG_ALL 2 // reliable to all
1822 #define MSG_INIT 3 // write to the init string
1824 sizebuf_t *WriteDest (void)
1830 dest = G_FLOAT(OFS_PARM0);
1834 return &sv.datagram;
1837 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1838 entnum = NUM_FOR_EDICT(ent);
1839 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1840 Host_Error("WriteDest: tried to write to non-client\n");
1841 return &svs.clients[entnum-1].message;
1844 return &sv.reliable_datagram;
1850 Host_Error("WriteDest: bad destination");
1857 void PF_WriteByte (void)
1859 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1862 void PF_WriteChar (void)
1864 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1867 void PF_WriteShort (void)
1869 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1872 void PF_WriteLong (void)
1874 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1877 void PF_WriteAngle (void)
1879 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1882 void PF_WriteCoord (void)
1884 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
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_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1933 MSG_WriteAngle(&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 #define MAX_QC_CVARS 128
2048 cvar_t qc_cvar[MAX_QC_CVARS];
2051 void PF_registercvar (void)
2055 name = G_STRING(OFS_PARM0);
2056 value = G_STRING(OFS_PARM1);
2057 G_FLOAT(OFS_RETURN) = 0;
2058 // first check to see if it has already been defined
2059 if (Cvar_FindVar (name))
2062 // check for overlap with a command
2063 if (Cmd_Exists (name))
2065 Con_Printf("PF_registercvar: %s is a command\n", name);
2069 if (currentqc_cvar >= MAX_QC_CVARS)
2070 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2072 // copy the name and value
2073 variable = &qc_cvar[currentqc_cvar++];
2074 variable->name = Z_Malloc (strlen(name)+1);
2075 strcpy (variable->name, name);
2076 variable->string = Z_Malloc (strlen(value)+1);
2077 strcpy (variable->string, value);
2078 variable->value = atof (value);
2080 Cvar_RegisterVariable(variable);
2081 G_FLOAT(OFS_RETURN) = 1; // success
2088 returns the minimum of two supplied floats
2095 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2097 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2098 else if (pr_argc >= 3)
2101 float f = G_FLOAT(OFS_PARM0);
2102 for (i = 1;i < pr_argc;i++)
2103 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2104 f = G_FLOAT((OFS_PARM0+i*3));
2105 G_FLOAT(OFS_RETURN) = f;
2109 G_FLOAT(OFS_RETURN) = 0;
2110 PF_WARNING("min: must supply at least 2 floats\n");
2118 returns the maximum of two supplied floats
2125 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2127 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2128 else if (pr_argc >= 3)
2131 float f = G_FLOAT(OFS_PARM0);
2132 for (i = 1;i < pr_argc;i++)
2133 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2134 f = G_FLOAT((OFS_PARM0+i*3));
2135 G_FLOAT(OFS_RETURN) = f;
2139 G_FLOAT(OFS_RETURN) = 0;
2140 PF_WARNING("max: must supply at least 2 floats\n");
2148 returns number bounded by supplied range
2150 min(min, value, max)
2153 void PF_bound (void)
2155 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2162 returns a raised to power b
2169 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2176 copies data from one entity to another
2178 copyentity(src, dst)
2181 void PF_copyentity (void)
2184 in = G_EDICT(OFS_PARM0);
2185 if (in == sv.edicts)
2186 PF_WARNING("copyentity: can not read world entity\n");
2188 PF_WARNING("copyentity: can not read free entity\n");
2189 out = G_EDICT(OFS_PARM1);
2190 if (out == sv.edicts)
2191 PF_WARNING("copyentity: can not modify world entity\n");
2193 PF_WARNING("copyentity: can not modify free entity\n");
2194 memcpy(out->v, in->v, progs->entityfields * 4);
2201 sets the color of a client and broadcasts the update to all connected clients
2203 setcolor(clientent, value)
2206 void PF_setcolor (void)
2212 entnum = G_EDICTNUM(OFS_PARM0);
2213 i = G_FLOAT(OFS_PARM1);
2215 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2217 Con_Print("tried to setcolor a non-client\n");
2221 client = svs.clients + entnum-1;
2222 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2225 client->old_colors = i;
2226 client->edict->v->team = (i & 15) + 1;
2228 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2229 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2230 MSG_WriteByte (&sv.reliable_datagram, i);
2237 effect(origin, modelname, startframe, framecount, framerate)
2240 void PF_effect (void)
2243 s = G_STRING(OFS_PARM1);
2245 PF_WARNING("effect: no model specified\n");
2247 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2250 void PF_te_blood (void)
2252 if (G_FLOAT(OFS_PARM2) < 1)
2254 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2255 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2257 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2261 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2262 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2263 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2265 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2268 void PF_te_bloodshower (void)
2270 if (G_FLOAT(OFS_PARM3) < 1)
2272 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2273 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2275 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2277 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2283 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2285 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2288 void PF_te_explosionrgb (void)
2290 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2291 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2293 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2294 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2295 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2297 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2298 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2299 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2302 void PF_te_particlecube (void)
2304 if (G_FLOAT(OFS_PARM3) < 1)
2306 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2307 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2309 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2310 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2311 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2313 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2314 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2315 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2317 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2318 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2319 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2321 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2323 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2324 // gravity true/false
2325 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2327 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2330 void PF_te_particlerain (void)
2332 if (G_FLOAT(OFS_PARM3) < 1)
2334 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2335 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2337 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2338 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2339 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2341 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2342 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2343 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2345 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2346 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2347 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2349 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2351 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2354 void PF_te_particlesnow (void)
2356 if (G_FLOAT(OFS_PARM3) < 1)
2358 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2359 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2361 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2362 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2365 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2366 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2367 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2369 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2370 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2371 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2373 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2375 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2378 void PF_te_spark (void)
2380 if (G_FLOAT(OFS_PARM2) < 1)
2382 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2383 MSG_WriteByte(&sv.datagram, TE_SPARK);
2385 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2386 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2387 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2389 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2390 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2391 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2393 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2396 void PF_te_gunshotquad (void)
2398 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2399 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2401 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2402 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2403 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2406 void PF_te_spikequad (void)
2408 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2409 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2411 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2412 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2416 void PF_te_superspikequad (void)
2418 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2419 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2421 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2426 void PF_te_explosionquad (void)
2428 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2429 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2431 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2432 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2436 void PF_te_smallflash (void)
2438 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2439 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2441 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2442 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2446 void PF_te_customflash (void)
2448 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2450 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2451 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2453 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2454 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2457 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2459 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2461 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2462 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2463 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2466 void PF_te_gunshot (void)
2468 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2469 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2471 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2476 void PF_te_spike (void)
2478 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2479 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2481 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2482 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2483 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2486 void PF_te_superspike (void)
2488 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2489 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2491 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2496 void PF_te_explosion (void)
2498 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2499 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2501 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2506 void PF_te_tarexplosion (void)
2508 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2509 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2511 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2516 void PF_te_wizspike (void)
2518 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2519 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2521 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2522 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2523 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2526 void PF_te_knightspike (void)
2528 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2529 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2531 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2536 void PF_te_lavasplash (void)
2538 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2539 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2541 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2542 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2543 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2546 void PF_te_teleport (void)
2548 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2549 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2551 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2552 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2553 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2556 void PF_te_explosion2 (void)
2558 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2559 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2561 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2562 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2563 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2565 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2566 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2569 void PF_te_lightning1 (void)
2571 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2572 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2574 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2576 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2577 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2578 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2580 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2581 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2582 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2585 void PF_te_lightning2 (void)
2587 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2588 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2590 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2592 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2593 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2594 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2596 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2597 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2598 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2601 void PF_te_lightning3 (void)
2603 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2604 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2606 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2608 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2609 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2610 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2612 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2613 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2614 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2617 void PF_te_beam (void)
2619 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2620 MSG_WriteByte(&sv.datagram, TE_BEAM);
2622 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2624 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2625 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2626 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2628 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2629 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2630 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2633 void PF_te_plasmaburn (void)
2635 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2636 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2637 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2638 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2639 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2642 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2645 vec3_t v1, clipplanenormal, normal;
2646 vec_t clipplanedist, clipdist;
2648 if (surf->flags & SURF_PLANEBACK)
2649 VectorNegate(surf->plane->normal, normal);
2651 VectorCopy(surf->plane->normal, normal);
2652 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2654 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2655 VectorNormalizeFast(v1);
2656 CrossProduct(v1, normal, clipplanenormal);
2657 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2658 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2661 clipdist = -clipdist;
2662 VectorMA(out, clipdist, clipplanenormal, out);
2667 static msurface_t *getsurface(edict_t *ed, int surfnum)
2671 if (!ed || ed->e->free)
2673 modelindex = ed->v->modelindex;
2674 if (modelindex < 1 || modelindex >= MAX_MODELS)
2676 model = sv.models[modelindex];
2677 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2679 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2683 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2684 void PF_getsurfacenumpoints(void)
2687 // return 0 if no such surface
2688 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2690 G_FLOAT(OFS_RETURN) = 0;
2694 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2696 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2697 void PF_getsurfacepoint(void)
2702 VectorClear(G_VECTOR(OFS_RETURN));
2703 ed = G_EDICT(OFS_PARM0);
2704 if (!ed || ed->e->free)
2706 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2708 pointnum = G_FLOAT(OFS_PARM2);
2709 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2711 // FIXME: implement rotation/scaling
2712 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2714 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2715 void PF_getsurfacenormal(void)
2718 VectorClear(G_VECTOR(OFS_RETURN));
2719 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2721 // FIXME: implement rotation/scaling
2722 if (surf->flags & SURF_PLANEBACK)
2723 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2725 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2727 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2728 void PF_getsurfacetexture(void)
2731 G_INT(OFS_RETURN) = 0;
2732 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2734 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2736 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2737 void PF_getsurfacenearpoint(void)
2739 int surfnum, best, modelindex;
2741 vec_t dist, bestdist;
2746 G_FLOAT(OFS_RETURN) = -1;
2747 ed = G_EDICT(OFS_PARM0);
2748 point = G_VECTOR(OFS_PARM1);
2750 if (!ed || ed->e->free)
2752 modelindex = ed->v->modelindex;
2753 if (modelindex < 1 || modelindex >= MAX_MODELS)
2755 model = sv.models[modelindex];
2756 if (!model->brushq1.numsurfaces)
2759 // FIXME: implement rotation/scaling
2760 VectorSubtract(point, ed->v->origin, p);
2762 bestdist = 1000000000;
2763 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2765 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2766 dist = PlaneDiff(p, surf->plane);
2768 if (dist < bestdist)
2770 clippointtosurface(surf, p, clipped);
2771 VectorSubtract(clipped, p, clipped);
2772 dist += DotProduct(clipped, clipped);
2773 if (dist < bestdist)
2780 G_FLOAT(OFS_RETURN) = best;
2782 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2783 void PF_getsurfaceclippedpoint(void)
2788 VectorClear(G_VECTOR(OFS_RETURN));
2789 ed = G_EDICT(OFS_PARM0);
2790 if (!ed || ed->e->free)
2792 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2794 // FIXME: implement rotation/scaling
2795 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2796 clippointtosurface(surf, p, out);
2797 // FIXME: implement rotation/scaling
2798 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2801 #define MAX_PRFILES 256
2803 qfile_t *pr_files[MAX_PRFILES];
2805 void PR_Files_Init(void)
2807 memset(pr_files, 0, sizeof(pr_files));
2810 void PR_Files_CloseAll(void)
2813 for (i = 0;i < MAX_PRFILES;i++)
2816 FS_Close(pr_files[i]);
2821 //float(string s) stof = #81; // get numerical value from a string
2824 char string[STRINGTEMP_LENGTH];
2825 PF_VarString(0, string, sizeof(string));
2826 G_FLOAT(OFS_RETURN) = atof(string);
2829 //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
2832 int filenum, mode, i;
2833 char *modestring, *filename;
2834 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2835 if (pr_files[filenum] == NULL)
2837 if (filenum >= MAX_PRFILES)
2839 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2840 G_FLOAT(OFS_RETURN) = -2;
2843 mode = G_FLOAT(OFS_PARM1);
2846 case 0: // FILE_READ
2849 case 1: // FILE_APPEND
2852 case 2: // FILE_WRITE
2856 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2857 G_FLOAT(OFS_RETURN) = -3;
2860 filename = G_STRING(OFS_PARM0);
2861 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2862 // ../ is parent directory on many platforms
2863 // // is parent directory on Amiga
2864 // / at the beginning of a path is root on unix, and parent directory on Amiga
2865 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2866 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2867 for (i = 0;filename[i];i++)
2869 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2871 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);
2872 G_FLOAT(OFS_RETURN) = -4;
2876 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2878 if (pr_files[filenum] == NULL && modestring == "rb")
2879 pr_files[filenum] = FS_Open(filename, modestring, false);
2881 if (pr_files[filenum] == NULL)
2882 G_FLOAT(OFS_RETURN) = -1;
2884 G_FLOAT(OFS_RETURN) = filenum;
2887 //void(float fhandle) fclose = #111; // closes a file
2888 void PF_fclose(void)
2890 int filenum = G_FLOAT(OFS_PARM0);
2891 if (filenum < 0 || filenum >= MAX_PRFILES)
2893 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2896 if (pr_files[filenum] == NULL)
2898 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2901 FS_Close(pr_files[filenum]);
2902 pr_files[filenum] = NULL;
2905 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2909 static char string[STRINGTEMP_LENGTH];
2910 int filenum = G_FLOAT(OFS_PARM0);
2911 if (filenum < 0 || filenum >= MAX_PRFILES)
2913 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2916 if (pr_files[filenum] == NULL)
2918 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2924 c = FS_Getc(pr_files[filenum]);
2925 if (c == '\r' || c == '\n' || c < 0)
2927 if (end < STRINGTEMP_LENGTH - 1)
2931 // remove \n following \r
2933 c = FS_Getc(pr_files[filenum]);
2934 if (developer.integer)
2935 Con_Printf("fgets: %s\n", string);
2937 G_INT(OFS_RETURN) = PR_SetString(string);
2939 G_INT(OFS_RETURN) = 0;
2942 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2946 char string[STRINGTEMP_LENGTH];
2947 int filenum = G_FLOAT(OFS_PARM0);
2948 if (filenum < 0 || filenum >= MAX_PRFILES)
2950 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2953 if (pr_files[filenum] == NULL)
2955 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2958 PF_VarString(1, string, sizeof(string));
2959 if ((stringlength = strlen(string)))
2960 FS_Write(pr_files[filenum], string, stringlength);
2961 if (developer.integer)
2962 Con_Printf("fputs: %s\n", string);
2965 //float(string s) strlen = #114; // returns how many characters are in a string
2966 void PF_strlen(void)
2969 s = G_STRING(OFS_PARM0);
2971 G_FLOAT(OFS_RETURN) = strlen(s);
2973 G_FLOAT(OFS_RETURN) = 0;
2976 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2977 void PF_strcat(void)
2979 char *s = PR_GetTempString();
2980 PF_VarString(0, s, STRINGTEMP_LENGTH);
2981 G_INT(OFS_RETURN) = PR_SetString(s);
2984 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2985 void PF_substring(void)
2987 int i, start, length;
2988 char *s, *string = PR_GetTempString();
2989 s = G_STRING(OFS_PARM0);
2990 start = G_FLOAT(OFS_PARM1);
2991 length = G_FLOAT(OFS_PARM2);
2994 for (i = 0;i < start && *s;i++, s++);
2995 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2998 G_INT(OFS_RETURN) = PR_SetString(string);
3001 //vector(string s) stov = #117; // returns vector value from a string
3004 char string[STRINGTEMP_LENGTH];
3005 PF_VarString(0, string, sizeof(string));
3006 Math_atov(string, G_VECTOR(OFS_RETURN));
3009 //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)
3010 void PF_strzone(void)
3013 in = G_STRING(OFS_PARM0);
3014 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3016 G_INT(OFS_RETURN) = PR_SetString(out);
3019 //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!!!)
3020 void PF_strunzone(void)
3022 Mem_Free(G_STRING(OFS_PARM0));
3025 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3026 //this function originally written by KrimZon, made shorter by LordHavoc
3027 void PF_clientcommand (void)
3029 client_t *temp_client;
3032 //find client for this entity
3033 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3034 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3036 Con_Print("PF_clientcommand: entity is not a client\n");
3040 temp_client = host_client;
3041 host_client = svs.clients + i;
3042 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3043 host_client = temp_client;
3046 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3047 //this function originally written by KrimZon, made shorter by LordHavoc
3048 //20040203: rewritten by LordHavoc (no longer uses allocations)
3050 char *tokens[256], tokenbuf[4096];
3051 void PF_tokenize (void)
3055 p = G_STRING(OFS_PARM0);
3059 while(COM_ParseToken(&p, false))
3061 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3063 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3065 tokens[num_tokens++] = tokenbuf + pos;
3066 strcpy(tokenbuf + pos, com_token);
3067 pos += strlen(com_token) + 1;
3070 G_FLOAT(OFS_RETURN) = num_tokens;
3073 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3074 //this function originally written by KrimZon, made shorter by LordHavoc
3077 int token_num = G_FLOAT(OFS_PARM0);
3078 if (token_num >= 0 && token_num < num_tokens)
3079 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3081 G_INT(OFS_RETURN) = PR_SetString("");
3084 //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)
3085 void PF_setattachment (void)
3087 edict_t *e = G_EDICT(OFS_PARM0);
3088 edict_t *tagentity = G_EDICT(OFS_PARM1);
3089 char *tagname = G_STRING(OFS_PARM2);
3095 PF_WARNING("setattachment: can not modify world entity\n");
3097 PF_WARNING("setattachment: can not modify free entity\n");
3099 if (tagentity == NULL)
3100 tagentity = sv.edicts;
3102 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3104 v->edict = EDICT_TO_PROG(tagentity);
3106 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3109 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3111 modelindex = (int)tagentity->v->modelindex;
3112 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3114 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3115 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3116 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3118 // FIXME: use a model function to get tag info (need to handle skeletal)
3119 if (v->_float == 0 && model->alias.aliasnum_tags)
3120 for (i = 0;i < model->alias.aliasnum_tags;i++)
3121 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3124 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);
3127 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));
3132 /////////////////////////////////////////
3133 // DP_QC_FS_SEARCH extension
3135 // qc fs search handling
3136 #define MAX_SEARCHES 128
3138 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3140 void PR_Search_Init(void)
3142 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3145 void PR_Search_Reset(void)
3148 // reset the fssearch list
3149 for(i = 0; i < MAX_SEARCHES; i++)
3150 if(pr_fssearchlist[i])
3151 FS_FreeSearch(pr_fssearchlist[i]);
3152 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3159 float search_begin(string pattern, float caseinsensitive, float quiet)
3162 void PF_search_begin(void)
3166 int caseinsens, quiet;
3168 pattern = G_STRING(OFS_PARM0);
3170 PR_CheckEmptyString(pattern);
3172 caseinsens = G_FLOAT(OFS_PARM1);
3173 quiet = G_FLOAT(OFS_PARM2);
3175 for(handle = 0; handle < MAX_SEARCHES; handle++)
3176 if(!pr_fssearchlist[handle])
3179 if(handle >= MAX_SEARCHES)
3181 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3182 G_FLOAT(OFS_RETURN) = -2;
3186 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3187 G_FLOAT(OFS_RETURN) = -1;
3189 G_FLOAT(OFS_RETURN) = handle;
3196 void search_end(float handle)
3199 void PF_search_end(void)
3203 handle = G_FLOAT(OFS_PARM0);
3205 if(handle < 0 || handle >= MAX_SEARCHES)
3207 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3210 if(pr_fssearchlist[handle] == NULL)
3212 Con_Printf("PF_search_end: no such handle %i\n", handle);
3216 FS_FreeSearch(pr_fssearchlist[handle]);
3217 pr_fssearchlist[handle] = NULL;
3224 float search_getsize(float handle)
3227 void PF_search_getsize(void)
3231 handle = G_FLOAT(OFS_PARM0);
3233 if(handle < 0 || handle >= MAX_SEARCHES)
3235 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3238 if(pr_fssearchlist[handle] == NULL)
3240 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3244 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3249 VM_search_getfilename
3251 string search_getfilename(float handle, float num)
3254 void PF_search_getfilename(void)
3256 int handle, filenum;
3259 handle = G_FLOAT(OFS_PARM0);
3260 filenum = G_FLOAT(OFS_PARM1);
3262 if(handle < 0 || handle >= MAX_SEARCHES)
3264 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3267 if(pr_fssearchlist[handle] == NULL)
3269 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3272 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3274 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3278 tmp = PR_GetTempString();
3279 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3281 G_INT(OFS_RETURN) = PR_SetString(tmp);
3284 void PF_cvar_string (void)
3290 str = G_STRING(OFS_PARM0);
3291 var = Cvar_FindVar (str);
3293 tmp = PR_GetTempString();
3294 strcpy(tmp, var->string);
3296 G_INT(OFS_RETURN) = PR_SetString(tmp);
3301 builtin_t pr_builtin[] =
3304 PF_makevectors, // #1 void(entity e) makevectors
3305 PF_setorigin, // #2 void(entity e, vector o) setorigin
3306 PF_setmodel, // #3 void(entity e, string m) setmodel
3307 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3308 NULL, // #5 void(entity e, vector min, vector max) setabssize
3309 PF_break, // #6 void() break
3310 PF_random, // #7 float() random
3311 PF_sound, // #8 void(entity e, float chan, string samp) sound
3312 PF_normalize, // #9 vector(vector v) normalize
3313 PF_error, // #10 void(string e) error
3314 PF_objerror, // #11 void(string e) objerror
3315 PF_vlen, // #12 float(vector v) vlen
3316 PF_vectoyaw, // #13 float(vector v) vectoyaw
3317 PF_Spawn, // #14 entity() spawn
3318 PF_Remove, // #15 void(entity e) remove
3319 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3320 PF_checkclient, // #17 entity() clientlist
3321 PF_Find, // #18 entity(entity start, .string fld, string match) find
3322 PF_precache_sound, // #19 void(string s) precache_sound
3323 PF_precache_model, // #20 void(string s) precache_model
3324 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3325 PF_findradius, // #22 entity(vector org, float rad) findradius
3326 PF_bprint, // #23 void(string s) bprint
3327 PF_sprint, // #24 void(entity client, string s) sprint
3328 PF_dprint, // #25 void(string s) dprint
3329 PF_ftos, // #26 void(string s) ftos
3330 PF_vtos, // #27 void(string s) vtos
3331 PF_coredump, // #28 void() coredump
3332 PF_traceon, // #29 void() traceon
3333 PF_traceoff, // #30 void() traceoff
3334 PF_eprint, // #31 void(entity e) eprint
3335 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3337 PF_droptofloor, // #34 float() droptofloor
3338 PF_lightstyle, // #35 void(float style, string value) lightstyle
3339 PF_rint, // #36 float(float v) rint
3340 PF_floor, // #37 float(float v) floor
3341 PF_ceil, // #38 float(float v) ceil
3343 PF_checkbottom, // #40 float(entity e) checkbottom
3344 PF_pointcontents , // #41 float(vector v) pointcontents
3346 PF_fabs, // #43 float(float f) fabs
3347 PF_aim, // #44 vector(entity e, float speed) aim
3348 PF_cvar, // #45 float(string s) cvar
3349 PF_localcmd, // #46 void(string s) localcmd
3350 PF_nextent, // #47 entity(entity e) nextent
3351 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3352 PF_changeyaw, // #49 void() ChangeYaw
3354 PF_vectoangles, // #51 vector(vector v) vectoangles
3355 PF_WriteByte, // #52 void(float to, float f) WriteByte
3356 PF_WriteChar, // #53 void(float to, float f) WriteChar
3357 PF_WriteShort, // #54 void(float to, float f) WriteShort
3358 PF_WriteLong, // #55 void(float to, float f) WriteLong
3359 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3360 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3361 PF_WriteString, // #58 void(float to, string s) WriteString
3362 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3363 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3364 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3365 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3366 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3367 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3368 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3370 SV_MoveToGoal, // #67 void(float step) movetogoal
3371 PF_precache_file, // #68 string(string s) precache_file
3372 PF_makestatic, // #69 void(entity e) makestatic
3373 PF_changelevel, // #70 void(string s) changelevel
3375 PF_cvar_set, // #72 void(string var, string val) cvar_set
3376 PF_centerprint, // #73 void(entity client, strings) centerprint
3377 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3378 PF_precache_model, // #75 string(string s) precache_model2
3379 PF_precache_sound, // #76 string(string s) precache_sound2
3380 PF_precache_file, // #77 string(string s) precache_file2
3381 PF_setspawnparms, // #78 void(entity e) setspawnparms
3384 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3393 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3394 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3395 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3396 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3397 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3398 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3399 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3400 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3401 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3402 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3413 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3414 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3415 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3416 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3417 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3418 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3419 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3420 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3421 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3422 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3423 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3424 a a a a a a a a // #120-199
3425 a a a a a a a a a a // #200-299
3426 a a a a a a a a a a // #300-399
3427 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3428 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3429 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3430 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3431 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3432 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3433 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3434 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3435 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3436 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3437 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3438 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3439 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3440 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3441 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3442 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3443 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3444 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3445 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3446 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3448 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3449 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3450 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3451 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3452 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3453 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3454 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3455 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3456 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3457 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3458 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3459 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3460 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3461 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3462 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3463 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3464 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3465 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3466 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3467 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3468 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3469 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3470 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3471 PF_search_begin, // #444
3472 PF_search_end, // #445
3473 PF_search_getsize, // #446
3474 PF_search_getfilename, // #447
3475 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3476 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3477 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3487 a a a a // #460-499 (LordHavoc)
3490 builtin_t *pr_builtins = pr_builtin;
3491 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3493 void PR_Cmd_Init(void)
3495 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3500 void PR_Cmd_Reset(void)
3502 Mem_EmptyPool(pr_strings_mempool);
3504 PR_Files_CloseAll();