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 =
82 "DP_ENT_CUSTOMCOLORMAP "
83 "DP_ENT_EXTERIORMODELTOCLIENT "
85 "DP_ENT_LOWPRECISION "
88 "DP_GFX_EXTERNALTEXTURES "
90 "DP_GFX_QUAKE3MODELTAGS "
94 "DP_HALFLIFE_MAP_CVAR "
98 "DP_MOVETYPEBOUNCEMISSILE "
105 "DP_QC_FINDCHAINFLOAT "
107 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
112 "DP_QC_SINCOSSQRTPOW "
115 "DP_QC_TRACE_MOVETYPE_HITMODEL "
116 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
117 "DP_QC_VECTORVECTORS "
123 "DP_SV_DRAWONLYTOCLIENT "
125 "DP_SV_EXTERIORMODELTOCLIENT "
126 "DP_SV_NODRAWTOCLIENT "
127 "DP_SV_PLAYERPHYSICS "
133 "DP_TE_EXPLOSIONRGB "
135 "DP_TE_PARTICLECUBE "
136 "DP_TE_PARTICLERAIN "
137 "DP_TE_PARTICLESNOW "
139 "DP_TE_QUADEFFECTS1 "
142 "DP_TE_STANDARDEFFECTBUILTINS "
145 "KRIMZON_SV_PARSECLIENTCOMMAND "
151 qboolean checkextension(char *name)
156 for (e = ENGINE_EXTENSIONS;*e;e++)
163 while (*e && *e != ' ')
165 if (e - start == len)
166 if (!strncasecmp(start, name, len))
176 returns true if the extension is supported by the server
178 checkextension(extensionname)
181 void PF_checkextension (void)
183 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
190 This is a TERMINAL error, which will kill off the entire server.
199 char string[STRINGTEMP_LENGTH];
201 PF_VarString(0, string, sizeof(string));
202 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
203 ed = PROG_TO_EDICT(pr_global_struct->self);
206 PF_ERROR("Program error");
213 Dumps out self, then an error message. The program is aborted and self is
214 removed, but the level can continue.
219 void PF_objerror (void)
222 char string[STRINGTEMP_LENGTH];
224 PF_VarString(0, string, sizeof(string));
225 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
226 ed = PROG_TO_EDICT(pr_global_struct->self);
236 Writes new values for v_forward, v_up, and v_right based on angles
240 void PF_makevectors (void)
242 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
249 Writes new values for v_forward, v_up, and v_right based on the given forward vector
250 vectorvectors(vector, vector)
253 void PF_vectorvectors (void)
255 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
256 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
263 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.
265 setorigin (entity, origin)
268 void PF_setorigin (void)
273 e = G_EDICT(OFS_PARM0);
275 PF_WARNING("setorigin: can not modify world entity\n");
277 PF_WARNING("setorigin: can not modify free entity\n");
278 org = G_VECTOR(OFS_PARM1);
279 VectorCopy (org, e->v->origin);
280 SV_LinkEdict (e, false);
284 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
288 for (i=0 ; i<3 ; i++)
290 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
292 // set derived values
293 VectorCopy (min, e->v->mins);
294 VectorCopy (max, e->v->maxs);
295 VectorSubtract (max, min, e->v->size);
297 SV_LinkEdict (e, false);
304 the size box is rotated by the current angle
305 LordHavoc: no it isn't...
307 setsize (entity, minvector, maxvector)
310 void PF_setsize (void)
315 e = G_EDICT(OFS_PARM0);
317 PF_WARNING("setsize: can not modify world entity\n");
319 PF_WARNING("setsize: can not modify free entity\n");
320 min = G_VECTOR(OFS_PARM1);
321 max = G_VECTOR(OFS_PARM2);
322 SetMinMaxSize (e, min, max, false);
330 setmodel(entity, model)
333 void PF_setmodel (void)
340 e = G_EDICT(OFS_PARM0);
342 PF_WARNING("setmodel: can not modify world entity\n");
344 PF_WARNING("setmodel: can not modify free entity\n");
345 m = G_STRING(OFS_PARM1);
347 // check to see if model was properly precached
348 for (i=0, check = sv.model_precache ; *check ; i++, check++)
349 if (!strcmp(*check, m))
353 PF_WARNING("setmodel: no precache\n");
356 e->v->model = PR_SetString(*check);
357 e->v->modelindex = i;
359 mod = sv.models[ (int)e->v->modelindex];
362 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
364 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
371 broadcast print to everyone on server
376 void PF_bprint (void)
378 char string[STRINGTEMP_LENGTH];
379 PF_VarString(0, string, sizeof(string));
380 SV_BroadcastPrintf("%s", string);
387 single print to a specific client
389 sprint(clientent, value)
392 void PF_sprint (void)
396 char string[STRINGTEMP_LENGTH];
398 entnum = G_EDICTNUM(OFS_PARM0);
400 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
402 Con_Printf ("tried to sprint to a non-client\n");
406 client = svs.clients + entnum-1;
407 if (!client->netconnection)
409 PF_VarString(1, string, sizeof(string));
410 MSG_WriteChar(&client->message,svc_print);
411 MSG_WriteString(&client->message, string);
419 single print to a specific client
421 centerprint(clientent, value)
424 void PF_centerprint (void)
428 char string[STRINGTEMP_LENGTH];
430 entnum = G_EDICTNUM(OFS_PARM0);
432 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
434 Con_Printf ("tried to sprint to a non-client\n");
438 client = svs.clients + entnum-1;
439 if (!client->netconnection)
441 PF_VarString(1, string, sizeof(string));
442 MSG_WriteChar(&client->message,svc_centerprint);
443 MSG_WriteString(&client->message, string);
451 vector normalize(vector)
454 void PF_normalize (void)
460 value1 = G_VECTOR(OFS_PARM0);
462 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
466 newvalue[0] = newvalue[1] = newvalue[2] = 0;
470 newvalue[0] = value1[0] * new;
471 newvalue[1] = value1[1] * new;
472 newvalue[2] = value1[2] * new;
475 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
490 value1 = G_VECTOR(OFS_PARM0);
492 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
495 G_FLOAT(OFS_RETURN) = new;
502 float vectoyaw(vector)
505 void PF_vectoyaw (void)
510 value1 = G_VECTOR(OFS_PARM0);
512 if (value1[1] == 0 && value1[0] == 0)
516 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
521 G_FLOAT(OFS_RETURN) = yaw;
529 vector vectoangles(vector)
532 void PF_vectoangles (void)
538 value1 = G_VECTOR(OFS_PARM0);
540 if (value1[1] == 0 && value1[0] == 0)
550 // LordHavoc: optimized a bit
553 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
557 else if (value1[1] > 0)
562 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
563 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
568 G_FLOAT(OFS_RETURN+0) = pitch;
569 G_FLOAT(OFS_RETURN+1) = yaw;
570 G_FLOAT(OFS_RETURN+2) = 0;
577 Returns a number from 0<= num < 1
582 void PF_random (void)
586 num = (rand ()&0x7fff) / ((float)0x7fff);
588 G_FLOAT(OFS_RETURN) = num;
595 particle(origin, color, count)
598 void PF_particle (void)
604 org = G_VECTOR(OFS_PARM0);
605 dir = G_VECTOR(OFS_PARM1);
606 color = G_FLOAT(OFS_PARM2);
607 count = G_FLOAT(OFS_PARM3);
608 SV_StartParticle (org, dir, color, count);
618 void PF_ambientsound (void)
623 float vol, attenuation;
624 int i, soundnum, large;
626 pos = G_VECTOR (OFS_PARM0);
627 samp = G_STRING(OFS_PARM1);
628 vol = G_FLOAT(OFS_PARM2);
629 attenuation = G_FLOAT(OFS_PARM3);
631 // check to see if samp was properly precached
632 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
633 if (!strcmp(*check,samp))
638 Con_Printf ("no precache: %s\n", samp);
646 // add an svc_spawnambient command to the level signon packet
649 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
651 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
653 for (i=0 ; i<3 ; i++)
654 MSG_WriteDPCoord(&sv.signon, pos[i]);
657 MSG_WriteShort (&sv.signon, soundnum);
659 MSG_WriteByte (&sv.signon, soundnum);
661 MSG_WriteByte (&sv.signon, vol*255);
662 MSG_WriteByte (&sv.signon, attenuation*64);
670 Each entity can have eight independant sound sources, like voice,
673 Channel 0 is an auto-allocate channel, the others override anything
674 already running on that entity/channel pair.
676 An attenuation of 0 will play full volume everywhere in the level.
677 Larger attenuations will drop off.
689 entity = G_EDICT(OFS_PARM0);
690 channel = G_FLOAT(OFS_PARM1);
691 sample = G_STRING(OFS_PARM2);
692 volume = G_FLOAT(OFS_PARM3) * 255;
693 attenuation = G_FLOAT(OFS_PARM4);
695 if (volume < 0 || volume > 255)
696 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
698 if (attenuation < 0 || attenuation > 4)
699 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
701 if (channel < 0 || channel > 7)
702 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
704 SV_StartSound (entity, channel, sample, volume, attenuation);
716 PF_ERROR("break: break statement\n");
723 Used for use tracing and shot targeting
724 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
725 if the tryents flag is set.
727 traceline (vector1, vector2, tryents)
730 void PF_traceline (void)
737 pr_xfunction->builtinsprofile += 30;
739 v1 = G_VECTOR(OFS_PARM0);
740 v2 = G_VECTOR(OFS_PARM1);
741 nomonsters = G_FLOAT(OFS_PARM2);
742 ent = G_EDICT(OFS_PARM3);
744 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
746 pr_global_struct->trace_allsolid = trace.allsolid;
747 pr_global_struct->trace_startsolid = trace.startsolid;
748 pr_global_struct->trace_fraction = trace.fraction;
749 pr_global_struct->trace_inwater = trace.inwater;
750 pr_global_struct->trace_inopen = trace.inopen;
751 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
752 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
753 pr_global_struct->trace_plane_dist = trace.plane.dist;
755 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
757 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
758 // FIXME: add trace_endcontents
766 Used for use tracing and shot targeting
767 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
768 if the tryents flag is set.
770 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
773 // LordHavoc: added this for my own use, VERY useful, similar to traceline
774 void PF_tracebox (void)
776 float *v1, *v2, *m1, *m2;
781 pr_xfunction->builtinsprofile += 30;
783 v1 = G_VECTOR(OFS_PARM0);
784 m1 = G_VECTOR(OFS_PARM1);
785 m2 = G_VECTOR(OFS_PARM2);
786 v2 = G_VECTOR(OFS_PARM3);
787 nomonsters = G_FLOAT(OFS_PARM4);
788 ent = G_EDICT(OFS_PARM5);
790 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
792 pr_global_struct->trace_allsolid = trace.allsolid;
793 pr_global_struct->trace_startsolid = trace.startsolid;
794 pr_global_struct->trace_fraction = trace.fraction;
795 pr_global_struct->trace_inwater = trace.inwater;
796 pr_global_struct->trace_inopen = trace.inopen;
797 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
798 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
799 pr_global_struct->trace_plane_dist = trace.plane.dist;
801 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
803 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
806 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
807 void PF_TraceToss (void)
813 pr_xfunction->builtinsprofile += 600;
815 ent = G_EDICT(OFS_PARM0);
816 if (ent == sv.edicts)
817 PF_WARNING("tracetoss: can not use world entity\n");
818 ignore = G_EDICT(OFS_PARM1);
820 trace = SV_Trace_Toss (ent, ignore);
822 pr_global_struct->trace_allsolid = trace.allsolid;
823 pr_global_struct->trace_startsolid = trace.startsolid;
824 pr_global_struct->trace_fraction = trace.fraction;
825 pr_global_struct->trace_inwater = trace.inwater;
826 pr_global_struct->trace_inopen = trace.inopen;
827 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
828 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
829 pr_global_struct->trace_plane_dist = trace.plane.dist;
831 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
833 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
841 Returns true if the given entity can move to the given position from it's
842 current position by walking or rolling.
844 scalar checkpos (entity, vector)
847 void PF_checkpos (void)
851 //============================================================================
854 qbyte checkpvs[MAX_MAP_LEAFS/8];
856 int PF_newcheckclient (int check)
862 // cycle to the next one
864 check = bound(1, check, svs.maxclients);
865 if (check == svs.maxclients)
873 pr_xfunction->builtinsprofile++;
875 if (i == svs.maxclients+1)
877 // look up the client's edict
879 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
880 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
882 // found a valid client (possibly the same one again)
886 // get the PVS for the entity
887 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
889 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
890 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
899 Returns a client (or object that has a client enemy) that would be a
902 If there is more than one valid option, they are cycled each frame
904 If (self.origin + self.viewofs) is not in the PVS of the current target,
905 it is not returned at all.
910 int c_invis, c_notvis;
911 void PF_checkclient (void)
916 // find a new check if on a new frame
917 if (sv.time - sv.lastchecktime >= 0.1)
919 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
920 sv.lastchecktime = sv.time;
923 // return check if it might be visible
924 ent = EDICT_NUM(sv.lastcheck);
925 if (ent->e->free || ent->v->health <= 0)
927 RETURN_EDICT(sv.edicts);
931 // if current entity can't possibly see the check entity, return 0
932 self = PROG_TO_EDICT(pr_global_struct->self);
933 VectorAdd(self->v->origin, self->v->view_ofs, view);
934 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
937 RETURN_EDICT(sv.edicts);
941 // might be able to see it
946 //============================================================================
953 Sends text over to the client's execution buffer
955 stuffcmd (clientent, value)
958 void PF_stuffcmd (void)
964 entnum = G_EDICTNUM(OFS_PARM0);
965 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
967 Con_Printf("Can't stuffcmd to a non-client");
970 str = G_STRING(OFS_PARM1);
973 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
974 Host_ClientCommands ("%s", str);
982 Sends text to server console
987 void PF_localcmd (void)
989 Cbuf_AddText(G_STRING(OFS_PARM0));
1001 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1011 void PF_cvar_set (void)
1013 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1020 Returns a chain of entities that have origins within a spherical area
1022 findradius (origin, radius)
1025 void PF_findradius (void)
1027 edict_t *ent, *chain;
1034 chain = (edict_t *)sv.edicts;
1036 org = G_VECTOR(OFS_PARM0);
1037 radius = G_FLOAT(OFS_PARM1);
1038 radius2 = radius * radius;
1040 ent = NEXT_EDICT(sv.edicts);
1041 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1043 pr_xfunction->builtinsprofile++;
1046 if (ent->v->solid == SOLID_NOT)
1049 // LordHavoc: compare against bounding box rather than center,
1050 // and use DotProduct instead of Length, major speedup
1051 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1052 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1053 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1054 if (DotProduct(eorg, eorg) > radius2)
1057 ent->v->chain = EDICT_TO_PROG(chain);
1061 RETURN_EDICT(chain);
1070 void PF_dprint (void)
1072 char string[STRINGTEMP_LENGTH];
1073 if (developer.integer)
1075 PF_VarString(0, string, sizeof(string));
1076 Con_Printf("%s",string);
1084 v = G_FLOAT(OFS_PARM0);
1086 s = PR_GetTempString();
1087 if ((float)((int)v) == v)
1088 sprintf(s, "%i", (int)v);
1090 sprintf(s, "%f", v);
1091 G_INT(OFS_RETURN) = PR_SetString(s);
1097 v = G_FLOAT(OFS_PARM0);
1098 G_FLOAT(OFS_RETURN) = fabs(v);
1104 s = PR_GetTempString();
1105 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1106 G_INT(OFS_RETURN) = PR_SetString(s);
1112 s = PR_GetTempString();
1113 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1114 G_INT(OFS_RETURN) = PR_SetString(s);
1117 void PF_Spawn (void)
1120 pr_xfunction->builtinsprofile += 20;
1125 void PF_Remove (void)
1128 pr_xfunction->builtinsprofile += 20;
1130 ed = G_EDICT(OFS_PARM0);
1131 if (ed == sv.edicts)
1132 PF_WARNING("remove: tried to remove world\n");
1133 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1134 PF_WARNING("remove: tried to remove a client\n");
1135 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1136 if (ed->e->free && developer.integer)
1137 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1142 // entity (entity start, .string field, string match) find = #5;
1150 e = G_EDICTNUM(OFS_PARM0);
1151 f = G_INT(OFS_PARM1);
1152 s = G_STRING(OFS_PARM2);
1155 RETURN_EDICT(sv.edicts);
1159 for (e++ ; e < sv.num_edicts ; e++)
1161 pr_xfunction->builtinsprofile++;
1175 RETURN_EDICT(sv.edicts);
1178 // LordHavoc: added this for searching float, int, and entity reference fields
1179 void PF_FindFloat (void)
1186 e = G_EDICTNUM(OFS_PARM0);
1187 f = G_INT(OFS_PARM1);
1188 s = G_FLOAT(OFS_PARM2);
1190 for (e++ ; e < sv.num_edicts ; e++)
1192 pr_xfunction->builtinsprofile++;
1196 if (E_FLOAT(ed,f) == s)
1203 RETURN_EDICT(sv.edicts);
1206 // chained search for strings in entity fields
1207 // entity(.string field, string match) findchain = #402;
1208 void PF_findchain (void)
1213 edict_t *ent, *chain;
1215 chain = (edict_t *)sv.edicts;
1217 f = G_INT(OFS_PARM0);
1218 s = G_STRING(OFS_PARM1);
1221 RETURN_EDICT(sv.edicts);
1225 ent = NEXT_EDICT(sv.edicts);
1226 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1228 pr_xfunction->builtinsprofile++;
1231 t = E_STRING(ent,f);
1237 ent->v->chain = EDICT_TO_PROG(chain);
1241 RETURN_EDICT(chain);
1244 // LordHavoc: chained search for float, int, and entity reference fields
1245 // entity(.string field, float match) findchainfloat = #403;
1246 void PF_findchainfloat (void)
1251 edict_t *ent, *chain;
1253 chain = (edict_t *)sv.edicts;
1255 f = G_INT(OFS_PARM0);
1256 s = G_FLOAT(OFS_PARM1);
1258 ent = NEXT_EDICT(sv.edicts);
1259 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1261 pr_xfunction->builtinsprofile++;
1264 if (E_FLOAT(ent,f) != s)
1267 ent->v->chain = EDICT_TO_PROG(chain);
1271 RETURN_EDICT(chain);
1274 void PR_CheckEmptyString (char *s)
1277 PF_ERROR("Bad string");
1280 void PF_precache_file (void)
1281 { // precache_file is only used to copy files with qcc, it does nothing
1282 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1285 void PF_precache_sound (void)
1290 if (sv.state != ss_loading)
1291 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1293 s = G_STRING(OFS_PARM0);
1294 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1295 PR_CheckEmptyString (s);
1297 for (i=0 ; i<MAX_SOUNDS ; i++)
1299 if (!sv.sound_precache[i])
1301 sv.sound_precache[i] = s;
1304 if (!strcmp(sv.sound_precache[i], s))
1307 PF_ERROR("PF_precache_sound: overflow");
1310 void PF_precache_model (void)
1315 if (sv.state != ss_loading)
1316 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1318 s = G_STRING(OFS_PARM0);
1319 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1321 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1322 PR_CheckEmptyString (s);
1324 for (i=0 ; i<MAX_MODELS ; i++)
1326 if (!sv.model_precache[i])
1328 sv.model_precache[i] = s;
1329 sv.models[i] = Mod_ForName (s, true, false, false);
1332 if (!strcmp(sv.model_precache[i], s))
1335 PF_ERROR("PF_precache_model: overflow");
1339 void PF_coredump (void)
1344 void PF_traceon (void)
1349 void PF_traceoff (void)
1354 void PF_eprint (void)
1356 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1363 float(float yaw, float dist) walkmove
1366 void PF_walkmove (void)
1374 // assume failure if it returns early
1375 G_FLOAT(OFS_RETURN) = 0;
1377 ent = PROG_TO_EDICT(pr_global_struct->self);
1378 if (ent == sv.edicts)
1379 PF_WARNING("walkmove: can not modify world entity\n");
1381 PF_WARNING("walkmove: can not modify free entity\n");
1382 yaw = G_FLOAT(OFS_PARM0);
1383 dist = G_FLOAT(OFS_PARM1);
1385 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1388 yaw = yaw*M_PI*2 / 360;
1390 move[0] = cos(yaw)*dist;
1391 move[1] = sin(yaw)*dist;
1394 // save program state, because SV_movestep may call other progs
1395 oldf = pr_xfunction;
1396 oldself = pr_global_struct->self;
1398 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1401 // restore program state
1402 pr_xfunction = oldf;
1403 pr_global_struct->self = oldself;
1413 void PF_droptofloor (void)
1419 // assume failure if it returns early
1420 G_FLOAT(OFS_RETURN) = 0;
1422 ent = PROG_TO_EDICT(pr_global_struct->self);
1423 if (ent == sv.edicts)
1424 PF_WARNING("droptofloor: can not modify world entity\n");
1426 PF_WARNING("droptofloor: can not modify free entity\n");
1428 VectorCopy (ent->v->origin, end);
1431 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1433 if (trace.fraction != 1)
1435 VectorCopy (trace.endpos, ent->v->origin);
1436 SV_LinkEdict (ent, false);
1437 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1438 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1439 G_FLOAT(OFS_RETURN) = 1;
1440 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1441 ent->e->suspendedinairflag = true;
1449 void(float style, string value) lightstyle
1452 void PF_lightstyle (void)
1459 style = G_FLOAT(OFS_PARM0);
1460 val = G_STRING(OFS_PARM1);
1462 // change the string in sv
1463 sv.lightstyles[style] = val;
1465 // send message to all clients on this server
1466 if (sv.state != ss_active)
1469 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1471 if (client->netconnection)
1473 MSG_WriteChar (&client->message, svc_lightstyle);
1474 MSG_WriteChar (&client->message,style);
1475 MSG_WriteString (&client->message, val);
1483 f = G_FLOAT(OFS_PARM0);
1485 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1487 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1489 void PF_floor (void)
1491 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1495 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1504 void PF_checkbottom (void)
1506 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1514 void PF_pointcontents (void)
1516 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1523 entity nextent(entity)
1526 void PF_nextent (void)
1531 i = G_EDICTNUM(OFS_PARM0);
1534 pr_xfunction->builtinsprofile++;
1536 if (i == sv.num_edicts)
1538 RETURN_EDICT(sv.edicts);
1554 Pick a vector for the player to shoot along
1555 vector aim(entity, missilespeed)
1560 edict_t *ent, *check, *bestent;
1561 vec3_t start, dir, end, bestdir;
1564 float dist, bestdist;
1567 // assume failure if it returns early
1568 VectorClear(G_VECTOR(OFS_RETURN));
1570 ent = G_EDICT(OFS_PARM0);
1571 if (ent == sv.edicts)
1572 PF_WARNING("aim: can not use world entity\n");
1574 PF_WARNING("aim: can not use free entity\n");
1575 speed = G_FLOAT(OFS_PARM1);
1577 VectorCopy (ent->v->origin, start);
1580 // try sending a trace straight
1581 VectorCopy (pr_global_struct->v_forward, dir);
1582 VectorMA (start, 2048, dir, end);
1583 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1584 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1585 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1587 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1592 // try all possible entities
1593 VectorCopy (dir, bestdir);
1594 bestdist = sv_aim.value;
1597 check = NEXT_EDICT(sv.edicts);
1598 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1600 pr_xfunction->builtinsprofile++;
1601 if (check->v->takedamage != DAMAGE_AIM)
1605 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1606 continue; // don't aim at teammate
1607 for (j=0 ; j<3 ; j++)
1608 end[j] = check->v->origin[j]
1609 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1610 VectorSubtract (end, start, dir);
1611 VectorNormalize (dir);
1612 dist = DotProduct (dir, pr_global_struct->v_forward);
1613 if (dist < bestdist)
1614 continue; // to far to turn
1615 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1616 if (tr.ent == check)
1617 { // can shoot at this one
1625 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1626 dist = DotProduct (dir, pr_global_struct->v_forward);
1627 VectorScale (pr_global_struct->v_forward, dist, end);
1629 VectorNormalize (end);
1630 VectorCopy (end, G_VECTOR(OFS_RETURN));
1634 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1642 This was a major timewaster in progs, so it was converted to C
1645 void PF_changeyaw (void)
1648 float ideal, current, move, speed;
1650 ent = PROG_TO_EDICT(pr_global_struct->self);
1651 if (ent == sv.edicts)
1652 PF_WARNING("changeyaw: can not modify world entity\n");
1654 PF_WARNING("changeyaw: can not modify free entity\n");
1655 current = ANGLEMOD(ent->v->angles[1]);
1656 ideal = ent->v->ideal_yaw;
1657 speed = ent->v->yaw_speed;
1659 if (current == ideal)
1661 move = ideal - current;
1662 if (ideal > current)
1683 ent->v->angles[1] = ANGLEMOD (current + move);
1691 void PF_changepitch (void)
1694 float ideal, current, move, speed;
1697 ent = G_EDICT(OFS_PARM0);
1698 if (ent == sv.edicts)
1699 PF_WARNING("changepitch: can not modify world entity\n");
1701 PF_WARNING("changepitch: can not modify free entity\n");
1702 current = ANGLEMOD( ent->v->angles[0] );
1703 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1704 ideal = val->_float;
1707 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1710 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1711 speed = val->_float;
1714 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1718 if (current == ideal)
1720 move = ideal - current;
1721 if (ideal > current)
1742 ent->v->angles[0] = ANGLEMOD (current + move);
1746 ===============================================================================
1750 ===============================================================================
1753 #define MSG_BROADCAST 0 // unreliable to all
1754 #define MSG_ONE 1 // reliable to one (msg_entity)
1755 #define MSG_ALL 2 // reliable to all
1756 #define MSG_INIT 3 // write to the init string
1758 sizebuf_t *WriteDest (void)
1764 dest = G_FLOAT(OFS_PARM0);
1768 return &sv.datagram;
1771 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1772 entnum = NUM_FOR_EDICT(ent);
1773 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1774 Host_Error("WriteDest: tried to write to non-client\n");
1775 return &svs.clients[entnum-1].message;
1778 return &sv.reliable_datagram;
1784 Host_Error("WriteDest: bad destination");
1791 void PF_WriteByte (void)
1793 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1796 void PF_WriteChar (void)
1798 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1801 void PF_WriteShort (void)
1803 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1806 void PF_WriteLong (void)
1808 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1811 void PF_WriteAngle (void)
1813 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1816 void PF_WriteCoord (void)
1818 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1821 void PF_WriteString (void)
1823 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1827 void PF_WriteEntity (void)
1829 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1832 //=============================================================================
1834 void PF_makestatic (void)
1839 ent = G_EDICT(OFS_PARM0);
1840 if (ent == sv.edicts)
1841 PF_WARNING("makestatic: can not modify world entity\n");
1843 PF_WARNING("makestatic: can not modify free entity\n");
1846 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1851 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1852 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1853 MSG_WriteShort (&sv.signon, ent->v->frame);
1857 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1858 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1859 MSG_WriteByte (&sv.signon, ent->v->frame);
1862 MSG_WriteByte (&sv.signon, ent->v->colormap);
1863 MSG_WriteByte (&sv.signon, ent->v->skin);
1864 for (i=0 ; i<3 ; i++)
1866 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1867 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1870 // throw the entity away now
1874 //=============================================================================
1881 void PF_setspawnparms (void)
1887 ent = G_EDICT(OFS_PARM0);
1888 i = NUM_FOR_EDICT(ent);
1889 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1891 Con_Printf("tried to setspawnparms on a non-client\n");
1895 // copy spawn parms out of the client_t
1896 client = svs.clients + i-1;
1897 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1898 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1906 void PF_changelevel (void)
1910 // make sure we don't issue two changelevels
1911 if (svs.changelevel_issued)
1913 svs.changelevel_issued = true;
1915 s = G_STRING(OFS_PARM0);
1916 Cbuf_AddText (va("changelevel %s\n",s));
1921 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1926 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1931 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1938 Returns a vector of length < 1
1943 void PF_randomvec (void)
1948 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1949 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1950 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1952 while (DotProduct(temp, temp) >= 1);
1953 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1960 Returns a color vector indicating the lighting at the requested point.
1962 (Internal Operation note: actually measures the light beneath the point, just like
1963 the model lighting on the client)
1968 void PF_GetLight (void)
1970 vec3_t ambientcolor, diffusecolor, diffusenormal;
1972 p = G_VECTOR(OFS_PARM0);
1973 VectorClear(ambientcolor);
1974 VectorClear(diffusecolor);
1975 VectorClear(diffusenormal);
1976 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1977 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1978 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1981 #define MAX_QC_CVARS 128
1982 cvar_t qc_cvar[MAX_QC_CVARS];
1985 void PF_registercvar (void)
1989 name = G_STRING(OFS_PARM0);
1990 value = G_STRING(OFS_PARM1);
1991 G_FLOAT(OFS_RETURN) = 0;
1992 // first check to see if it has already been defined
1993 if (Cvar_FindVar (name))
1996 // check for overlap with a command
1997 if (Cmd_Exists (name))
1999 Con_Printf ("PF_registercvar: %s is a command\n", name);
2003 if (currentqc_cvar >= MAX_QC_CVARS)
2004 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2006 // copy the name and value
2007 variable = &qc_cvar[currentqc_cvar++];
2008 variable->name = Z_Malloc (strlen(name)+1);
2009 strcpy (variable->name, name);
2010 variable->string = Z_Malloc (strlen(value)+1);
2011 strcpy (variable->string, value);
2012 variable->value = atof (value);
2014 Cvar_RegisterVariable(variable);
2015 G_FLOAT(OFS_RETURN) = 1; // success
2022 returns the minimum of two supplied floats
2029 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2031 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2032 else if (pr_argc >= 3)
2035 float f = G_FLOAT(OFS_PARM0);
2036 for (i = 1;i < pr_argc;i++)
2037 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2038 f = G_FLOAT((OFS_PARM0+i*3));
2039 G_FLOAT(OFS_RETURN) = f;
2043 G_FLOAT(OFS_RETURN) = 0;
2044 PF_WARNING("min: must supply at least 2 floats\n");
2052 returns the maximum of two supplied floats
2059 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2061 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2062 else if (pr_argc >= 3)
2065 float f = G_FLOAT(OFS_PARM0);
2066 for (i = 1;i < pr_argc;i++)
2067 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2068 f = G_FLOAT((OFS_PARM0+i*3));
2069 G_FLOAT(OFS_RETURN) = f;
2073 G_FLOAT(OFS_RETURN) = 0;
2074 PF_WARNING("max: must supply at least 2 floats\n");
2082 returns number bounded by supplied range
2084 min(min, value, max)
2087 void PF_bound (void)
2089 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2096 returns a raised to power b
2103 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2110 copies data from one entity to another
2112 copyentity(src, dst)
2115 void PF_copyentity (void)
2118 in = G_EDICT(OFS_PARM0);
2119 if (in == sv.edicts)
2120 PF_WARNING("copyentity: can not read world entity\n");
2122 PF_WARNING("copyentity: can not read free entity\n");
2123 out = G_EDICT(OFS_PARM1);
2124 if (out == sv.edicts)
2125 PF_WARNING("copyentity: can not modify world entity\n");
2127 PF_WARNING("copyentity: can not modify free entity\n");
2128 memcpy(out->v, in->v, progs->entityfields * 4);
2135 sets the color of a client and broadcasts the update to all connected clients
2137 setcolor(clientent, value)
2140 void PF_setcolor (void)
2146 entnum = G_EDICTNUM(OFS_PARM0);
2147 i = G_FLOAT(OFS_PARM1);
2149 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2151 Con_Printf ("tried to setcolor a non-client\n");
2155 client = svs.clients + entnum-1;
2156 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2159 client->old_colors = i;
2160 client->edict->v->team = (i & 15) + 1;
2162 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2163 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2164 MSG_WriteByte (&sv.reliable_datagram, i);
2171 effect(origin, modelname, startframe, framecount, framerate)
2174 void PF_effect (void)
2177 s = G_STRING(OFS_PARM1);
2179 PF_WARNING("effect: no model specified\n");
2181 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2184 void PF_te_blood (void)
2186 if (G_FLOAT(OFS_PARM2) < 1)
2188 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2189 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2191 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2192 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2193 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2195 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2196 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2197 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2199 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2202 void PF_te_bloodshower (void)
2204 if (G_FLOAT(OFS_PARM3) < 1)
2206 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2207 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2209 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2210 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2211 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2213 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2214 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2215 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2217 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2219 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2222 void PF_te_explosionrgb (void)
2224 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2225 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2227 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2228 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2229 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2231 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2232 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2233 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2236 void PF_te_particlecube (void)
2238 if (G_FLOAT(OFS_PARM3) < 1)
2240 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2241 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2243 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2244 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2245 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2247 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2248 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2249 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2251 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2252 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2253 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2255 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2257 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2258 // gravity true/false
2259 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2261 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2264 void PF_te_particlerain (void)
2266 if (G_FLOAT(OFS_PARM3) < 1)
2268 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2269 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2271 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2272 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2273 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2275 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2277 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2283 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2285 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2288 void PF_te_particlesnow (void)
2290 if (G_FLOAT(OFS_PARM3) < 1)
2292 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2293 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2295 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2296 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2297 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2299 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2300 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2301 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2304 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2305 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2307 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2309 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2312 void PF_te_spark (void)
2314 if (G_FLOAT(OFS_PARM2) < 1)
2316 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2317 MSG_WriteByte(&sv.datagram, TE_SPARK);
2319 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2320 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2321 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2323 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2324 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2325 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2327 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2330 void PF_te_gunshotquad (void)
2332 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2333 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2335 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2336 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2337 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2340 void PF_te_spikequad (void)
2342 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2343 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2345 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2346 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2347 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2350 void PF_te_superspikequad (void)
2352 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2353 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2355 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2356 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2357 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2360 void PF_te_explosionquad (void)
2362 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2363 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2365 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2366 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2367 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2370 void PF_te_smallflash (void)
2372 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2373 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2375 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2376 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2377 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2380 void PF_te_customflash (void)
2382 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2384 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2385 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2387 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2388 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2389 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2391 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2393 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2395 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2396 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2397 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2400 void PF_te_gunshot (void)
2402 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2403 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2405 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2406 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2407 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2410 void PF_te_spike (void)
2412 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2413 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2415 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2416 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2417 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2420 void PF_te_superspike (void)
2422 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2423 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2425 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2426 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2427 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2430 void PF_te_explosion (void)
2432 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2433 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2435 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2436 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2437 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2440 void PF_te_tarexplosion (void)
2442 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2443 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2445 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2446 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2447 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2450 void PF_te_wizspike (void)
2452 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2453 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2456 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2457 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2460 void PF_te_knightspike (void)
2462 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2463 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2465 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2466 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2467 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2470 void PF_te_lavasplash (void)
2472 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2473 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2475 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2476 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2477 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2480 void PF_te_teleport (void)
2482 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2483 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2485 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2486 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2487 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2490 void PF_te_explosion2 (void)
2492 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2493 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2495 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2496 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2497 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2499 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2502 void PF_te_lightning1 (void)
2504 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2505 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2507 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2509 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2510 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2511 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2515 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2518 void PF_te_lightning2 (void)
2520 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2521 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2523 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2525 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2526 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2527 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2529 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2531 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2534 void PF_te_lightning3 (void)
2536 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2537 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2539 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2541 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2542 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2543 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2545 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2547 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2550 void PF_te_beam (void)
2552 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2553 MSG_WriteByte(&sv.datagram, TE_BEAM);
2555 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2557 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2558 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2559 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2561 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2562 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2563 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2566 void PF_te_plasmaburn (void)
2568 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2569 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2570 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2571 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2572 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2575 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2578 vec3_t v1, clipplanenormal, normal;
2579 vec_t clipplanedist, clipdist;
2581 if (surf->flags & SURF_PLANEBACK)
2582 VectorNegate(surf->plane->normal, normal);
2584 VectorCopy(surf->plane->normal, normal);
2585 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2587 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2588 VectorNormalizeFast(v1);
2589 CrossProduct(v1, normal, clipplanenormal);
2590 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2591 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2594 clipdist = -clipdist;
2595 VectorMA(out, clipdist, clipplanenormal, out);
2600 static msurface_t *getsurface(edict_t *ed, int surfnum)
2604 if (!ed || ed->e->free)
2606 modelindex = ed->v->modelindex;
2607 if (modelindex < 1 || modelindex >= MAX_MODELS)
2609 model = sv.models[modelindex];
2610 if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
2612 return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2616 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2617 void PF_getsurfacenumpoints(void)
2620 // return 0 if no such surface
2621 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2623 G_FLOAT(OFS_RETURN) = 0;
2627 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2629 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2630 void PF_getsurfacepoint(void)
2635 VectorClear(G_VECTOR(OFS_RETURN));
2636 ed = G_EDICT(OFS_PARM0);
2637 if (!ed || ed->e->free)
2639 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2641 pointnum = G_FLOAT(OFS_PARM2);
2642 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2644 // FIXME: implement rotation/scaling
2645 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2647 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2648 void PF_getsurfacenormal(void)
2651 VectorClear(G_VECTOR(OFS_RETURN));
2652 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2654 // FIXME: implement rotation/scaling
2655 if (surf->flags & SURF_PLANEBACK)
2656 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2658 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2660 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2661 void PF_getsurfacetexture(void)
2664 G_INT(OFS_RETURN) = 0;
2665 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2667 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2669 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2670 void PF_getsurfacenearpoint(void)
2672 int surfnum, best, modelindex;
2674 vec_t dist, bestdist;
2679 G_FLOAT(OFS_RETURN) = -1;
2680 ed = G_EDICT(OFS_PARM0);
2681 point = G_VECTOR(OFS_PARM1);
2683 if (!ed || ed->e->free)
2685 modelindex = ed->v->modelindex;
2686 if (modelindex < 1 || modelindex >= MAX_MODELS)
2688 model = sv.models[modelindex];
2689 if (!model->brushq1.numsurfaces)
2692 // FIXME: implement rotation/scaling
2693 VectorSubtract(point, ed->v->origin, p);
2695 bestdist = 1000000000;
2696 for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++)
2698 surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2699 dist = PlaneDiff(p, surf->plane);
2701 if (dist < bestdist)
2703 clippointtosurface(surf, p, clipped);
2704 VectorSubtract(clipped, p, clipped);
2705 dist += DotProduct(clipped, clipped);
2706 if (dist < bestdist)
2713 G_FLOAT(OFS_RETURN) = best;
2715 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2716 void PF_getsurfaceclippedpoint(void)
2721 VectorClear(G_VECTOR(OFS_RETURN));
2722 ed = G_EDICT(OFS_PARM0);
2723 if (!ed || ed->e->free)
2725 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2727 // FIXME: implement rotation/scaling
2728 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2729 clippointtosurface(surf, p, out);
2730 // FIXME: implement rotation/scaling
2731 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2734 #define MAX_PRFILES 256
2736 qfile_t *pr_files[MAX_PRFILES];
2738 void PR_Files_Init(void)
2740 memset(pr_files, 0, sizeof(pr_files));
2743 void PR_Files_CloseAll(void)
2746 for (i = 0;i < MAX_PRFILES;i++)
2749 FS_Close(pr_files[i]);
2754 //float(string s) stof = #81; // get numerical value from a string
2757 char string[STRINGTEMP_LENGTH];
2758 PF_VarString(0, string, sizeof(string));
2759 G_FLOAT(OFS_RETURN) = atof(string);
2762 //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
2766 char *modestring, *filename;
2767 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2768 if (pr_files[filenum] == NULL)
2770 if (filenum >= MAX_PRFILES)
2772 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2773 G_FLOAT(OFS_RETURN) = -2;
2776 mode = G_FLOAT(OFS_PARM1);
2779 case 0: // FILE_READ
2782 case 1: // FILE_APPEND
2785 case 2: // FILE_WRITE
2789 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2790 G_FLOAT(OFS_RETURN) = -3;
2793 filename = G_STRING(OFS_PARM0);
2794 // .. is parent directory on many platforms
2795 // / is parent directory on Amiga
2796 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2797 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2798 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2800 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2801 G_FLOAT(OFS_RETURN) = -4;
2804 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2805 if (pr_files[filenum] == NULL)
2806 G_FLOAT(OFS_RETURN) = -1;
2808 G_FLOAT(OFS_RETURN) = filenum;
2811 //void(float fhandle) fclose = #111; // closes a file
2812 void PF_fclose(void)
2814 int filenum = G_FLOAT(OFS_PARM0);
2815 if (filenum < 0 || filenum >= MAX_PRFILES)
2817 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2820 if (pr_files[filenum] == NULL)
2822 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2825 FS_Close(pr_files[filenum]);
2826 pr_files[filenum] = NULL;
2829 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2833 static char string[STRINGTEMP_LENGTH];
2834 int filenum = G_FLOAT(OFS_PARM0);
2835 if (filenum < 0 || filenum >= MAX_PRFILES)
2837 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2840 if (pr_files[filenum] == NULL)
2842 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2848 c = FS_Getc(pr_files[filenum]);
2849 if (c == '\r' || c == '\n' || c < 0)
2851 if (end < STRINGTEMP_LENGTH - 1)
2855 // remove \n following \r
2857 c = FS_Getc(pr_files[filenum]);
2858 if (developer.integer)
2859 Con_Printf("fgets: %s\n", string);
2861 G_INT(OFS_RETURN) = PR_SetString(string);
2863 G_INT(OFS_RETURN) = 0;
2866 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2870 char string[STRINGTEMP_LENGTH];
2871 int filenum = G_FLOAT(OFS_PARM0);
2872 if (filenum < 0 || filenum >= MAX_PRFILES)
2874 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2877 if (pr_files[filenum] == NULL)
2879 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2882 PF_VarString(1, string, sizeof(string));
2883 if ((stringlength = strlen(string)))
2884 FS_Write(pr_files[filenum], string, stringlength);
2885 if (developer.integer)
2886 Con_Printf("fputs: %s\n", string);
2889 //float(string s) strlen = #114; // returns how many characters are in a string
2890 void PF_strlen(void)
2893 s = G_STRING(OFS_PARM0);
2895 G_FLOAT(OFS_RETURN) = strlen(s);
2897 G_FLOAT(OFS_RETURN) = 0;
2900 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2901 void PF_strcat(void)
2903 char *s = PR_GetTempString();
2904 PF_VarString(0, s, STRINGTEMP_LENGTH);
2905 G_INT(OFS_RETURN) = PR_SetString(s);
2908 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2909 void PF_substring(void)
2911 int i, start, length;
2912 char *s, *string = PR_GetTempString();
2913 s = G_STRING(OFS_PARM0);
2914 start = G_FLOAT(OFS_PARM1);
2915 length = G_FLOAT(OFS_PARM2);
2918 for (i = 0;i < start && *s;i++, s++);
2919 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2922 G_INT(OFS_RETURN) = PR_SetString(string);
2925 //vector(string s) stov = #117; // returns vector value from a string
2928 char string[STRINGTEMP_LENGTH];
2929 PF_VarString(0, string, sizeof(string));
2930 Math_atov(string, G_VECTOR(OFS_RETURN));
2933 //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)
2934 void PF_strzone(void)
2937 in = G_STRING(OFS_PARM0);
2938 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2940 G_INT(OFS_RETURN) = PR_SetString(out);
2943 //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!!!)
2944 void PF_strunzone(void)
2946 Mem_Free(G_STRING(OFS_PARM0));
2949 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2950 //this function originally written by KrimZon, made shorter by LordHavoc
2951 void PF_clientcommand (void)
2953 client_t *temp_client;
2956 //find client for this entity
2957 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2958 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2960 Con_Printf("PF_clientcommand: entity is not a client");
2964 temp_client = host_client;
2965 host_client = svs.clients + i;
2966 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2967 host_client = temp_client;
2970 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2971 //this function originally written by KrimZon, made shorter by LordHavoc
2972 char **tokens = NULL;
2973 int max_tokens, num_tokens = 0;
2974 void PF_tokenize (void)
2978 str = G_STRING(OFS_PARM0);
2983 for (i=0;i<num_tokens;i++)
2989 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2990 max_tokens = strlen(str);
2992 for (p = str;COM_ParseToken(&p, false) && num_tokens < max_tokens;num_tokens++)
2994 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2995 strcpy(tokens[num_tokens], com_token);
2998 G_FLOAT(OFS_RETURN) = num_tokens;
3001 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3002 //this function originally written by KrimZon, made shorter by LordHavoc
3005 int token_num = G_FLOAT(OFS_PARM0);
3006 if (token_num >= 0 && token_num < num_tokens)
3007 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3009 G_INT(OFS_RETURN) = PR_SetString("");
3012 //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)
3013 void PF_setattachment (void)
3015 edict_t *e = G_EDICT(OFS_PARM0);
3016 edict_t *tagentity = G_EDICT(OFS_PARM1);
3017 char *tagname = G_STRING(OFS_PARM2);
3023 PF_WARNING("setattachment: can not modify world entity\n");
3025 PF_WARNING("setattachment: can not modify free entity\n");
3027 if (tagentity == NULL)
3028 tagentity = sv.edicts;
3030 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3032 v->edict = EDICT_TO_PROG(tagentity);
3034 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3037 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3039 modelindex = (int)tagentity->v->modelindex;
3040 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3042 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3043 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3044 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3046 if (v->_float == 0 && model->alias.aliasnum_tags)
3047 for (i = 0;i < model->alias.aliasnum_tags;i++)
3048 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3051 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);
3054 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));
3059 /////////////////////////////////////////
3060 // DP_QC_FS_SEARCH extension
3062 // qc fs search handling
3063 #define MAX_SEARCHES 128
3065 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3067 void PR_Search_Init(void)
3069 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3072 void PR_Search_Reset(void)
3075 // reset the fssearch list
3076 for(i = 0; i < MAX_SEARCHES; i++)
3077 if(pr_fssearchlist[i])
3078 FS_FreeSearch(pr_fssearchlist[i]);
3079 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3086 float search_begin(string pattern, float caseinsensitive, float quiet)
3089 void PF_search_begin(void)
3093 int caseinsens, quiet;
3095 pattern = G_STRING(OFS_PARM0);
3097 PR_CheckEmptyString(pattern);
3099 caseinsens = G_FLOAT(OFS_PARM1);
3100 quiet = G_FLOAT(OFS_PARM2);
3102 for(handle = 0; handle < MAX_SEARCHES; handle++)
3103 if(!pr_fssearchlist[handle])
3106 if(handle >= MAX_SEARCHES)
3108 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3109 G_FLOAT(OFS_RETURN) = -2;
3113 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3114 G_FLOAT(OFS_RETURN) = -1;
3116 G_FLOAT(OFS_RETURN) = handle;
3123 void search_end(float handle)
3126 void PF_search_end(void)
3130 handle = G_FLOAT(OFS_PARM0);
3132 if(handle < 0 || handle >= MAX_SEARCHES)
3134 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3137 if(pr_fssearchlist[handle] == NULL)
3139 Con_Printf("PF_search_end: no such handle %i\n", handle);
3143 FS_FreeSearch(pr_fssearchlist[handle]);
3144 pr_fssearchlist[handle] = NULL;
3151 float search_getsize(float handle)
3154 void PF_search_getsize(void)
3158 handle = G_FLOAT(OFS_PARM0);
3160 if(handle < 0 || handle >= MAX_SEARCHES)
3162 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3165 if(pr_fssearchlist[handle] == NULL)
3167 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3171 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3176 VM_search_getfilename
3178 string search_getfilename(float handle, float num)
3181 void PF_search_getfilename(void)
3183 int handle, filenum;
3186 handle = G_FLOAT(OFS_PARM0);
3187 filenum = G_FLOAT(OFS_PARM1);
3189 if(handle < 0 || handle >= MAX_SEARCHES)
3191 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3194 if(pr_fssearchlist[handle] == NULL)
3196 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3199 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3201 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3205 tmp = PR_GetTempString();
3206 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3208 G_INT(OFS_RETURN) = PR_SetString(tmp);
3211 void PF_cvar_string (void)
3217 str = G_STRING(OFS_PARM0);
3218 var = Cvar_FindVar (str);
3220 tmp = PR_GetTempString();
3221 strcpy(tmp, var->string);
3223 G_INT(OFS_RETURN) = PR_SetString(tmp);
3228 builtin_t pr_builtin[] =
3231 PF_makevectors, // #1 void(entity e) makevectors
3232 PF_setorigin, // #2 void(entity e, vector o) setorigin
3233 PF_setmodel, // #3 void(entity e, string m) setmodel
3234 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3235 NULL, // #5 void(entity e, vector min, vector max) setabssize
3236 PF_break, // #6 void() break
3237 PF_random, // #7 float() random
3238 PF_sound, // #8 void(entity e, float chan, string samp) sound
3239 PF_normalize, // #9 vector(vector v) normalize
3240 PF_error, // #10 void(string e) error
3241 PF_objerror, // #11 void(string e) objerror
3242 PF_vlen, // #12 float(vector v) vlen
3243 PF_vectoyaw, // #13 float(vector v) vectoyaw
3244 PF_Spawn, // #14 entity() spawn
3245 PF_Remove, // #15 void(entity e) remove
3246 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3247 PF_checkclient, // #17 entity() clientlist
3248 PF_Find, // #18 entity(entity start, .string fld, string match) find
3249 PF_precache_sound, // #19 void(string s) precache_sound
3250 PF_precache_model, // #20 void(string s) precache_model
3251 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3252 PF_findradius, // #22 entity(vector org, float rad) findradius
3253 PF_bprint, // #23 void(string s) bprint
3254 PF_sprint, // #24 void(entity client, string s) sprint
3255 PF_dprint, // #25 void(string s) dprint
3256 PF_ftos, // #26 void(string s) ftos
3257 PF_vtos, // #27 void(string s) vtos
3258 PF_coredump, // #28 void() coredump
3259 PF_traceon, // #29 void() traceon
3260 PF_traceoff, // #30 void() traceoff
3261 PF_eprint, // #31 void(entity e) eprint
3262 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3264 PF_droptofloor, // #34 float() droptofloor
3265 PF_lightstyle, // #35 void(float style, string value) lightstyle
3266 PF_rint, // #36 float(float v) rint
3267 PF_floor, // #37 float(float v) floor
3268 PF_ceil, // #38 float(float v) ceil
3270 PF_checkbottom, // #40 float(entity e) checkbottom
3271 PF_pointcontents , // #41 float(vector v) pointcontents
3273 PF_fabs, // #43 float(float f) fabs
3274 PF_aim, // #44 vector(entity e, float speed) aim
3275 PF_cvar, // #45 float(string s) cvar
3276 PF_localcmd, // #46 void(string s) localcmd
3277 PF_nextent, // #47 entity(entity e) nextent
3278 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3279 PF_changeyaw, // #49 void() ChangeYaw
3281 PF_vectoangles, // #51 vector(vector v) vectoangles
3282 PF_WriteByte, // #52 void(float to, float f) WriteByte
3283 PF_WriteChar, // #53 void(float to, float f) WriteChar
3284 PF_WriteShort, // #54 void(float to, float f) WriteShort
3285 PF_WriteLong, // #55 void(float to, float f) WriteLong
3286 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3287 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3288 PF_WriteString, // #58 void(float to, string s) WriteString
3289 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3290 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3291 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3292 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3293 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3294 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3295 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3297 SV_MoveToGoal, // #67 void(float step) movetogoal
3298 PF_precache_file, // #68 string(string s) precache_file
3299 PF_makestatic, // #69 void(entity e) makestatic
3300 PF_changelevel, // #70 void(string s) changelevel
3302 PF_cvar_set, // #72 void(string var, string val) cvar_set
3303 PF_centerprint, // #73 void(entity client, strings) centerprint
3304 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3305 PF_precache_model, // #75 string(string s) precache_model2
3306 PF_precache_sound, // #76 string(string s) precache_sound2
3307 PF_precache_file, // #77 string(string s) precache_file2
3308 PF_setspawnparms, // #78 void(entity e) setspawnparms
3311 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3320 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3321 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3322 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3323 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3324 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3325 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3326 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3327 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3328 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3329 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3340 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3341 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3342 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3343 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3344 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3345 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3346 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3347 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3348 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3349 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3350 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3351 a a a a a a a a // #120-199
3352 a a a a a a a a a a // #200-299
3353 a a a a a a a a a a // #300-399
3354 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3355 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3356 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3357 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3358 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3359 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3360 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3361 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3362 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3363 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3364 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3365 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3366 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3367 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3368 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3369 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3370 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3371 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3372 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3373 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3374 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3375 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3376 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3377 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3378 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3379 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3380 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3381 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3382 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3383 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3384 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3385 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3386 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3387 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3388 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3389 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3390 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3391 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3392 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3393 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3394 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3395 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3396 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3397 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3398 PF_search_begin, // #444
3399 PF_search_end, // #445
3400 PF_search_getsize, // #446
3401 PF_search_getfilename, // #447
3402 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3404 a a a a a // #450-499 (LordHavoc)
3407 builtin_t *pr_builtins = pr_builtin;
3408 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3410 void PR_Cmd_Init(void)
3412 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3417 void PR_Cmd_Reset(void)
3419 Mem_EmptyPool(pr_strings_mempool);
3421 PR_Files_CloseAll();