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 "
101 "DP_MOVETYPEWALK_NONCLIENTS "
107 "DP_QC_FINDCHAINFLAGS "
108 "DP_QC_FINDCHAINFLOAT "
111 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
115 "DP_QC_MULTIPLETEMPSTRINGS "
117 "DP_QC_SINCOSSQRTPOW "
120 "DP_QC_TRACE_MOVETYPE_HITMODEL "
121 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
122 "DP_QC_VECTORVECTORS "
126 "DP_SND_DIRECTIONLESSATTNNONE "
131 "DP_SV_DRAWONLYTOCLIENT "
133 "DP_SV_EXTERIORMODELTOCLIENT "
134 "DP_SV_NODRAWTOCLIENT "
135 "DP_SV_PLAYERPHYSICS "
136 "DP_SV_ROTATINGBMODEL "
142 "DP_TE_EXPLOSIONRGB "
144 "DP_TE_PARTICLECUBE "
145 "DP_TE_PARTICLERAIN "
146 "DP_TE_PARTICLESNOW "
148 "DP_TE_QUADEFFECTS1 "
151 "DP_TE_STANDARDEFFECTBUILTINS "
154 "KRIMZON_SV_PARSECLIENTCOMMAND "
157 "TENEBRAE_GFX_DLIGHTS "
161 qboolean checkextension(char *name)
166 for (e = ENGINE_EXTENSIONS;*e;e++)
173 while (*e && *e != ' ')
175 if (e - start == len)
176 if (!strncasecmp(start, name, len))
186 returns true if the extension is supported by the server
188 checkextension(extensionname)
191 void PF_checkextension (void)
193 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
200 This is a TERMINAL error, which will kill off the entire server.
209 char string[STRINGTEMP_LENGTH];
211 PF_VarString(0, string, sizeof(string));
212 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
213 ed = PROG_TO_EDICT(pr_global_struct->self);
216 PF_ERROR("Program error");
223 Dumps out self, then an error message. The program is aborted and self is
224 removed, but the level can continue.
229 void PF_objerror (void)
232 char string[STRINGTEMP_LENGTH];
234 PF_VarString(0, string, sizeof(string));
235 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
236 ed = PROG_TO_EDICT(pr_global_struct->self);
246 Writes new values for v_forward, v_up, and v_right based on angles
250 void PF_makevectors (void)
252 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
259 Writes new values for v_forward, v_up, and v_right based on the given forward vector
260 vectorvectors(vector, vector)
263 void PF_vectorvectors (void)
265 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
266 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
273 This is the only valid way to move an object without using the physics of the world (setting velocity and waiting). Directly changing origin will not set internal links correctly, so clipping would be messed up. This should be called when an object is spawned, and then only if it is teleported.
275 setorigin (entity, origin)
278 void PF_setorigin (void)
283 e = G_EDICT(OFS_PARM0);
285 PF_WARNING("setorigin: can not modify world entity\n");
287 PF_WARNING("setorigin: can not modify free entity\n");
288 org = G_VECTOR(OFS_PARM1);
289 VectorCopy (org, e->v->origin);
290 SV_LinkEdict (e, false);
294 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
298 for (i=0 ; i<3 ; i++)
300 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
302 // set derived values
303 VectorCopy (min, e->v->mins);
304 VectorCopy (max, e->v->maxs);
305 VectorSubtract (max, min, e->v->size);
307 SV_LinkEdict (e, false);
314 the size box is rotated by the current angle
315 LordHavoc: no it isn't...
317 setsize (entity, minvector, maxvector)
320 void PF_setsize (void)
325 e = G_EDICT(OFS_PARM0);
327 PF_WARNING("setsize: can not modify world entity\n");
329 PF_WARNING("setsize: can not modify free entity\n");
330 min = G_VECTOR(OFS_PARM1);
331 max = G_VECTOR(OFS_PARM2);
332 SetMinMaxSize (e, min, max, false);
340 setmodel(entity, model)
343 void PF_setmodel (void)
350 e = G_EDICT(OFS_PARM0);
352 PF_WARNING("setmodel: can not modify world entity\n");
354 PF_WARNING("setmodel: can not modify free entity\n");
355 m = G_STRING(OFS_PARM1);
357 // check to see if model was properly precached
358 for (i=0, check = sv.model_precache ; *check ; i++, check++)
359 if (!strcmp(*check, m))
363 PF_WARNING("setmodel: no precache\n");
366 e->v->model = PR_SetString(*check);
367 e->v->modelindex = i;
369 mod = sv.models[ (int)e->v->modelindex];
372 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
374 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
381 broadcast print to everyone on server
386 void PF_bprint (void)
388 char string[STRINGTEMP_LENGTH];
389 PF_VarString(0, string, sizeof(string));
390 SV_BroadcastPrint(string);
397 single print to a specific client
399 sprint(clientent, value)
402 void PF_sprint (void)
406 char string[STRINGTEMP_LENGTH];
408 entnum = G_EDICTNUM(OFS_PARM0);
410 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
412 Con_Print("tried to sprint to a non-client\n");
416 client = svs.clients + entnum-1;
417 if (!client->netconnection)
419 PF_VarString(1, string, sizeof(string));
420 MSG_WriteChar(&client->message,svc_print);
421 MSG_WriteString(&client->message, string);
429 single print to a specific client
431 centerprint(clientent, value)
434 void PF_centerprint (void)
438 char string[STRINGTEMP_LENGTH];
440 entnum = G_EDICTNUM(OFS_PARM0);
442 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
444 Con_Print("tried to sprint to a non-client\n");
448 client = svs.clients + entnum-1;
449 if (!client->netconnection)
451 PF_VarString(1, string, sizeof(string));
452 MSG_WriteChar(&client->message,svc_centerprint);
453 MSG_WriteString(&client->message, string);
461 vector normalize(vector)
464 void PF_normalize (void)
470 value1 = G_VECTOR(OFS_PARM0);
472 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
476 newvalue[0] = newvalue[1] = newvalue[2] = 0;
480 newvalue[0] = value1[0] * new;
481 newvalue[1] = value1[1] * new;
482 newvalue[2] = value1[2] * new;
485 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
500 value1 = G_VECTOR(OFS_PARM0);
502 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
505 G_FLOAT(OFS_RETURN) = new;
512 float vectoyaw(vector)
515 void PF_vectoyaw (void)
520 value1 = G_VECTOR(OFS_PARM0);
522 if (value1[1] == 0 && value1[0] == 0)
526 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
531 G_FLOAT(OFS_RETURN) = yaw;
539 vector vectoangles(vector)
542 void PF_vectoangles (void)
548 value1 = G_VECTOR(OFS_PARM0);
550 if (value1[1] == 0 && value1[0] == 0)
560 // LordHavoc: optimized a bit
563 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
567 else if (value1[1] > 0)
572 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
573 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
578 G_FLOAT(OFS_RETURN+0) = pitch;
579 G_FLOAT(OFS_RETURN+1) = yaw;
580 G_FLOAT(OFS_RETURN+2) = 0;
587 Returns a number from 0<= num < 1
592 void PF_random (void)
596 num = (rand ()&0x7fff) / ((float)0x7fff);
598 G_FLOAT(OFS_RETURN) = num;
605 particle(origin, color, count)
608 void PF_particle (void)
614 org = G_VECTOR(OFS_PARM0);
615 dir = G_VECTOR(OFS_PARM1);
616 color = G_FLOAT(OFS_PARM2);
617 count = G_FLOAT(OFS_PARM3);
618 SV_StartParticle (org, dir, color, count);
628 void PF_ambientsound (void)
633 float vol, attenuation;
634 int i, soundnum, large;
636 pos = G_VECTOR (OFS_PARM0);
637 samp = G_STRING(OFS_PARM1);
638 vol = G_FLOAT(OFS_PARM2);
639 attenuation = G_FLOAT(OFS_PARM3);
641 // check to see if samp was properly precached
642 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
643 if (!strcmp(*check,samp))
648 Con_Printf("no precache: %s\n", samp);
656 // add an svc_spawnambient command to the level signon packet
659 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
661 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
663 for (i=0 ; i<3 ; i++)
664 MSG_WriteDPCoord(&sv.signon, pos[i]);
667 MSG_WriteShort (&sv.signon, soundnum);
669 MSG_WriteByte (&sv.signon, soundnum);
671 MSG_WriteByte (&sv.signon, vol*255);
672 MSG_WriteByte (&sv.signon, attenuation*64);
680 Each entity can have eight independant sound sources, like voice,
683 Channel 0 is an auto-allocate channel, the others override anything
684 already running on that entity/channel pair.
686 An attenuation of 0 will play full volume everywhere in the level.
687 Larger attenuations will drop off.
699 entity = G_EDICT(OFS_PARM0);
700 channel = G_FLOAT(OFS_PARM1);
701 sample = G_STRING(OFS_PARM2);
702 volume = G_FLOAT(OFS_PARM3) * 255;
703 attenuation = G_FLOAT(OFS_PARM4);
705 if (volume < 0 || volume > 255)
706 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
708 if (attenuation < 0 || attenuation > 4)
709 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
711 if (channel < 0 || channel > 7)
712 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
714 SV_StartSound (entity, channel, sample, volume, attenuation);
726 PF_ERROR("break: break statement\n");
733 Used for use tracing and shot targeting
734 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
735 if the tryents flag is set.
737 traceline (vector1, vector2, tryents)
740 void PF_traceline (void)
747 pr_xfunction->builtinsprofile += 30;
749 v1 = G_VECTOR(OFS_PARM0);
750 v2 = G_VECTOR(OFS_PARM1);
751 move = G_FLOAT(OFS_PARM2);
752 ent = G_EDICT(OFS_PARM3);
754 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
756 pr_global_struct->trace_allsolid = trace.allsolid;
757 pr_global_struct->trace_startsolid = trace.startsolid;
758 pr_global_struct->trace_fraction = trace.fraction;
759 pr_global_struct->trace_inwater = trace.inwater;
760 pr_global_struct->trace_inopen = trace.inopen;
761 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
762 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
763 pr_global_struct->trace_plane_dist = trace.plane.dist;
765 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
767 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
768 // FIXME: add trace_endcontents
776 Used for use tracing and shot targeting
777 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
778 if the tryents flag is set.
780 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
783 // LordHavoc: added this for my own use, VERY useful, similar to traceline
784 void PF_tracebox (void)
786 float *v1, *v2, *m1, *m2;
791 pr_xfunction->builtinsprofile += 30;
793 v1 = G_VECTOR(OFS_PARM0);
794 m1 = G_VECTOR(OFS_PARM1);
795 m2 = G_VECTOR(OFS_PARM2);
796 v2 = G_VECTOR(OFS_PARM3);
797 move = G_FLOAT(OFS_PARM4);
798 ent = G_EDICT(OFS_PARM5);
800 trace = SV_Move (v1, m1, m2, v2, move, ent);
802 pr_global_struct->trace_allsolid = trace.allsolid;
803 pr_global_struct->trace_startsolid = trace.startsolid;
804 pr_global_struct->trace_fraction = trace.fraction;
805 pr_global_struct->trace_inwater = trace.inwater;
806 pr_global_struct->trace_inopen = trace.inopen;
807 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
808 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
809 pr_global_struct->trace_plane_dist = trace.plane.dist;
811 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
813 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
816 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
817 void PF_TraceToss (void)
823 pr_xfunction->builtinsprofile += 600;
825 ent = G_EDICT(OFS_PARM0);
826 if (ent == sv.edicts)
827 PF_WARNING("tracetoss: can not use world entity\n");
828 ignore = G_EDICT(OFS_PARM1);
830 trace = SV_Trace_Toss (ent, ignore);
832 pr_global_struct->trace_allsolid = trace.allsolid;
833 pr_global_struct->trace_startsolid = trace.startsolid;
834 pr_global_struct->trace_fraction = trace.fraction;
835 pr_global_struct->trace_inwater = trace.inwater;
836 pr_global_struct->trace_inopen = trace.inopen;
837 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
838 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
839 pr_global_struct->trace_plane_dist = trace.plane.dist;
841 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
843 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
851 Returns true if the given entity can move to the given position from it's
852 current position by walking or rolling.
854 scalar checkpos (entity, vector)
857 void PF_checkpos (void)
861 //============================================================================
864 qbyte checkpvs[MAX_MAP_LEAFS/8];
866 int PF_newcheckclient (int check)
872 // cycle to the next one
874 check = bound(1, check, svs.maxclients);
875 if (check == svs.maxclients)
883 pr_xfunction->builtinsprofile++;
885 if (i == svs.maxclients+1)
887 // look up the client's edict
889 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
890 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
892 // found a valid client (possibly the same one again)
896 // get the PVS for the entity
897 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
899 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
900 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
909 Returns a client (or object that has a client enemy) that would be a
912 If there is more than one valid option, they are cycled each frame
914 If (self.origin + self.viewofs) is not in the PVS of the current target,
915 it is not returned at all.
920 int c_invis, c_notvis;
921 void PF_checkclient (void)
926 // find a new check if on a new frame
927 if (sv.time - sv.lastchecktime >= 0.1)
929 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
930 sv.lastchecktime = sv.time;
933 // return check if it might be visible
934 ent = EDICT_NUM(sv.lastcheck);
935 if (ent->e->free || ent->v->health <= 0)
937 RETURN_EDICT(sv.edicts);
941 // if current entity can't possibly see the check entity, return 0
942 self = PROG_TO_EDICT(pr_global_struct->self);
943 VectorAdd(self->v->origin, self->v->view_ofs, view);
944 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
947 RETURN_EDICT(sv.edicts);
951 // might be able to see it
956 //============================================================================
963 Sends text over to the client's execution buffer
965 stuffcmd (clientent, value)
968 void PF_stuffcmd (void)
974 entnum = G_EDICTNUM(OFS_PARM0);
975 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
977 Con_Print("Can't stuffcmd to a non-client\n");
980 str = G_STRING(OFS_PARM1);
983 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
984 Host_ClientCommands ("%s", str);
992 Sends text to server console
997 void PF_localcmd (void)
999 Cbuf_AddText(G_STRING(OFS_PARM0));
1011 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1021 void PF_cvar_set (void)
1023 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1030 Returns a chain of entities that have origins within a spherical area
1032 findradius (origin, radius)
1035 void PF_findradius (void)
1037 edict_t *ent, *chain;
1044 chain = (edict_t *)sv.edicts;
1046 org = G_VECTOR(OFS_PARM0);
1047 radius = G_FLOAT(OFS_PARM1);
1048 radius2 = radius * radius;
1050 ent = NEXT_EDICT(sv.edicts);
1051 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1053 pr_xfunction->builtinsprofile++;
1056 if (ent->v->solid == SOLID_NOT)
1059 // LordHavoc: compare against bounding box rather than center,
1060 // and use DotProduct instead of Length, major speedup
1061 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1062 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1063 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1064 if (DotProduct(eorg, eorg) > radius2)
1067 ent->v->chain = EDICT_TO_PROG(chain);
1071 RETURN_EDICT(chain);
1080 void PF_dprint (void)
1082 char string[STRINGTEMP_LENGTH];
1083 if (developer.integer)
1085 PF_VarString(0, string, sizeof(string));
1094 v = G_FLOAT(OFS_PARM0);
1096 s = PR_GetTempString();
1097 if ((float)((int)v) == v)
1098 sprintf(s, "%i", (int)v);
1100 sprintf(s, "%f", v);
1101 G_INT(OFS_RETURN) = PR_SetString(s);
1107 v = G_FLOAT(OFS_PARM0);
1108 G_FLOAT(OFS_RETURN) = fabs(v);
1114 s = PR_GetTempString();
1115 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1116 G_INT(OFS_RETURN) = PR_SetString(s);
1122 s = PR_GetTempString();
1123 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1124 G_INT(OFS_RETURN) = PR_SetString(s);
1127 void PF_Spawn (void)
1130 pr_xfunction->builtinsprofile += 20;
1135 void PF_Remove (void)
1138 pr_xfunction->builtinsprofile += 20;
1140 ed = G_EDICT(OFS_PARM0);
1141 if (ed == sv.edicts)
1142 PF_WARNING("remove: tried to remove world\n");
1143 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1144 PF_WARNING("remove: tried to remove a client\n");
1145 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1146 if (ed->e->free && developer.integer)
1147 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1152 // entity (entity start, .string field, string match) find = #5;
1160 e = G_EDICTNUM(OFS_PARM0);
1161 f = G_INT(OFS_PARM1);
1162 s = G_STRING(OFS_PARM2);
1165 RETURN_EDICT(sv.edicts);
1169 for (e++ ; e < sv.num_edicts ; e++)
1171 pr_xfunction->builtinsprofile++;
1185 RETURN_EDICT(sv.edicts);
1188 // LordHavoc: added this for searching float, int, and entity reference fields
1189 void PF_FindFloat (void)
1196 e = G_EDICTNUM(OFS_PARM0);
1197 f = G_INT(OFS_PARM1);
1198 s = G_FLOAT(OFS_PARM2);
1200 for (e++ ; e < sv.num_edicts ; e++)
1202 pr_xfunction->builtinsprofile++;
1206 if (E_FLOAT(ed,f) == s)
1213 RETURN_EDICT(sv.edicts);
1216 // chained search for strings in entity fields
1217 // entity(.string field, string match) findchain = #402;
1218 void PF_findchain (void)
1223 edict_t *ent, *chain;
1225 chain = (edict_t *)sv.edicts;
1227 f = G_INT(OFS_PARM0);
1228 s = G_STRING(OFS_PARM1);
1231 RETURN_EDICT(sv.edicts);
1235 ent = NEXT_EDICT(sv.edicts);
1236 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1238 pr_xfunction->builtinsprofile++;
1241 t = E_STRING(ent,f);
1247 ent->v->chain = EDICT_TO_PROG(chain);
1251 RETURN_EDICT(chain);
1254 // LordHavoc: chained search for float, int, and entity reference fields
1255 // entity(.string field, float match) findchainfloat = #403;
1256 void PF_findchainfloat (void)
1261 edict_t *ent, *chain;
1263 chain = (edict_t *)sv.edicts;
1265 f = G_INT(OFS_PARM0);
1266 s = G_FLOAT(OFS_PARM1);
1268 ent = NEXT_EDICT(sv.edicts);
1269 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1271 pr_xfunction->builtinsprofile++;
1274 if (E_FLOAT(ent,f) != s)
1277 ent->v->chain = EDICT_TO_PROG(chain);
1281 RETURN_EDICT(chain);
1284 // LordHavoc: search for flags in float fields
1285 void PF_findflags (void)
1292 e = G_EDICTNUM(OFS_PARM0);
1293 f = G_INT(OFS_PARM1);
1294 s = (int)G_FLOAT(OFS_PARM2);
1296 for (e++ ; e < sv.num_edicts ; e++)
1298 pr_xfunction->builtinsprofile++;
1302 if ((int)E_FLOAT(ed,f) & s)
1309 RETURN_EDICT(sv.edicts);
1312 // LordHavoc: chained search for flags in float fields
1313 void PF_findchainflags (void)
1318 edict_t *ent, *chain;
1320 chain = (edict_t *)sv.edicts;
1322 f = G_INT(OFS_PARM0);
1323 s = (int)G_FLOAT(OFS_PARM1);
1325 ent = NEXT_EDICT(sv.edicts);
1326 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1328 pr_xfunction->builtinsprofile++;
1331 if (!((int)E_FLOAT(ent,f) & s))
1334 ent->v->chain = EDICT_TO_PROG(chain);
1338 RETURN_EDICT(chain);
1341 void PR_CheckEmptyString (char *s)
1344 PF_ERROR("Bad string");
1347 void PF_precache_file (void)
1348 { // precache_file is only used to copy files with qcc, it does nothing
1349 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1352 void PF_precache_sound (void)
1357 if (sv.state != ss_loading)
1358 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1360 s = G_STRING(OFS_PARM0);
1361 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1362 PR_CheckEmptyString (s);
1364 for (i=0 ; i<MAX_SOUNDS ; i++)
1366 if (!sv.sound_precache[i])
1368 sv.sound_precache[i] = s;
1371 if (!strcmp(sv.sound_precache[i], s))
1374 PF_ERROR("PF_precache_sound: overflow");
1377 void PF_precache_model (void)
1382 if (sv.state != ss_loading)
1383 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1385 s = G_STRING(OFS_PARM0);
1386 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1388 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1389 PR_CheckEmptyString (s);
1391 for (i=0 ; i<MAX_MODELS ; i++)
1393 if (!sv.model_precache[i])
1395 sv.model_precache[i] = s;
1396 sv.models[i] = Mod_ForName (s, true, false, false);
1399 if (!strcmp(sv.model_precache[i], s))
1402 PF_ERROR("PF_precache_model: overflow");
1406 void PF_coredump (void)
1411 void PF_traceon (void)
1416 void PF_traceoff (void)
1421 void PF_eprint (void)
1423 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1430 float(float yaw, float dist) walkmove
1433 void PF_walkmove (void)
1441 // assume failure if it returns early
1442 G_FLOAT(OFS_RETURN) = 0;
1444 ent = PROG_TO_EDICT(pr_global_struct->self);
1445 if (ent == sv.edicts)
1446 PF_WARNING("walkmove: can not modify world entity\n");
1448 PF_WARNING("walkmove: can not modify free entity\n");
1449 yaw = G_FLOAT(OFS_PARM0);
1450 dist = G_FLOAT(OFS_PARM1);
1452 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1455 yaw = yaw*M_PI*2 / 360;
1457 move[0] = cos(yaw)*dist;
1458 move[1] = sin(yaw)*dist;
1461 // save program state, because SV_movestep may call other progs
1462 oldf = pr_xfunction;
1463 oldself = pr_global_struct->self;
1465 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1468 // restore program state
1469 pr_xfunction = oldf;
1470 pr_global_struct->self = oldself;
1480 void PF_droptofloor (void)
1486 // assume failure if it returns early
1487 G_FLOAT(OFS_RETURN) = 0;
1489 ent = PROG_TO_EDICT(pr_global_struct->self);
1490 if (ent == sv.edicts)
1491 PF_WARNING("droptofloor: can not modify world entity\n");
1493 PF_WARNING("droptofloor: can not modify free entity\n");
1495 VectorCopy (ent->v->origin, end);
1498 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1500 if (trace.fraction != 1)
1502 VectorCopy (trace.endpos, ent->v->origin);
1503 SV_LinkEdict (ent, false);
1504 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1505 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1506 G_FLOAT(OFS_RETURN) = 1;
1507 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1508 ent->e->suspendedinairflag = true;
1516 void(float style, string value) lightstyle
1519 void PF_lightstyle (void)
1526 style = G_FLOAT(OFS_PARM0);
1527 val = G_STRING(OFS_PARM1);
1529 // change the string in sv
1530 sv.lightstyles[style] = val;
1532 // send message to all clients on this server
1533 if (sv.state != ss_active)
1536 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1538 if (client->netconnection)
1540 MSG_WriteChar (&client->message, svc_lightstyle);
1541 MSG_WriteChar (&client->message,style);
1542 MSG_WriteString (&client->message, val);
1550 f = G_FLOAT(OFS_PARM0);
1552 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1554 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1556 void PF_floor (void)
1558 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1562 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1571 void PF_checkbottom (void)
1573 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1581 void PF_pointcontents (void)
1583 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1590 entity nextent(entity)
1593 void PF_nextent (void)
1598 i = G_EDICTNUM(OFS_PARM0);
1601 pr_xfunction->builtinsprofile++;
1603 if (i == sv.num_edicts)
1605 RETURN_EDICT(sv.edicts);
1621 Pick a vector for the player to shoot along
1622 vector aim(entity, missilespeed)
1627 edict_t *ent, *check, *bestent;
1628 vec3_t start, dir, end, bestdir;
1631 float dist, bestdist;
1634 // assume failure if it returns early
1635 VectorClear(G_VECTOR(OFS_RETURN));
1637 ent = G_EDICT(OFS_PARM0);
1638 if (ent == sv.edicts)
1639 PF_WARNING("aim: can not use world entity\n");
1641 PF_WARNING("aim: can not use free entity\n");
1642 speed = G_FLOAT(OFS_PARM1);
1644 VectorCopy (ent->v->origin, start);
1647 // try sending a trace straight
1648 VectorCopy (pr_global_struct->v_forward, dir);
1649 VectorMA (start, 2048, dir, end);
1650 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1651 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1652 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1654 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1659 // try all possible entities
1660 VectorCopy (dir, bestdir);
1661 bestdist = sv_aim.value;
1664 check = NEXT_EDICT(sv.edicts);
1665 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1667 pr_xfunction->builtinsprofile++;
1668 if (check->v->takedamage != DAMAGE_AIM)
1672 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1673 continue; // don't aim at teammate
1674 for (j=0 ; j<3 ; j++)
1675 end[j] = check->v->origin[j]
1676 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1677 VectorSubtract (end, start, dir);
1678 VectorNormalize (dir);
1679 dist = DotProduct (dir, pr_global_struct->v_forward);
1680 if (dist < bestdist)
1681 continue; // to far to turn
1682 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1683 if (tr.ent == check)
1684 { // can shoot at this one
1692 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1693 dist = DotProduct (dir, pr_global_struct->v_forward);
1694 VectorScale (pr_global_struct->v_forward, dist, end);
1696 VectorNormalize (end);
1697 VectorCopy (end, G_VECTOR(OFS_RETURN));
1701 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1709 This was a major timewaster in progs, so it was converted to C
1712 void PF_changeyaw (void)
1715 float ideal, current, move, speed;
1717 ent = PROG_TO_EDICT(pr_global_struct->self);
1718 if (ent == sv.edicts)
1719 PF_WARNING("changeyaw: can not modify world entity\n");
1721 PF_WARNING("changeyaw: can not modify free entity\n");
1722 current = ANGLEMOD(ent->v->angles[1]);
1723 ideal = ent->v->ideal_yaw;
1724 speed = ent->v->yaw_speed;
1726 if (current == ideal)
1728 move = ideal - current;
1729 if (ideal > current)
1750 ent->v->angles[1] = ANGLEMOD (current + move);
1758 void PF_changepitch (void)
1761 float ideal, current, move, speed;
1764 ent = G_EDICT(OFS_PARM0);
1765 if (ent == sv.edicts)
1766 PF_WARNING("changepitch: can not modify world entity\n");
1768 PF_WARNING("changepitch: can not modify free entity\n");
1769 current = ANGLEMOD( ent->v->angles[0] );
1770 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1771 ideal = val->_float;
1774 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1777 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1778 speed = val->_float;
1781 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1785 if (current == ideal)
1787 move = ideal - current;
1788 if (ideal > current)
1809 ent->v->angles[0] = ANGLEMOD (current + move);
1813 ===============================================================================
1817 ===============================================================================
1820 #define MSG_BROADCAST 0 // unreliable to all
1821 #define MSG_ONE 1 // reliable to one (msg_entity)
1822 #define MSG_ALL 2 // reliable to all
1823 #define MSG_INIT 3 // write to the init string
1825 sizebuf_t *WriteDest (void)
1831 dest = G_FLOAT(OFS_PARM0);
1835 return &sv.datagram;
1838 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1839 entnum = NUM_FOR_EDICT(ent);
1840 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1841 Host_Error("WriteDest: tried to write to non-client\n");
1842 return &svs.clients[entnum-1].message;
1845 return &sv.reliable_datagram;
1851 Host_Error("WriteDest: bad destination");
1858 void PF_WriteByte (void)
1860 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1863 void PF_WriteChar (void)
1865 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1868 void PF_WriteShort (void)
1870 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1873 void PF_WriteLong (void)
1875 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1878 void PF_WriteAngle (void)
1880 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1883 void PF_WriteCoord (void)
1885 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1888 void PF_WriteString (void)
1890 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1894 void PF_WriteEntity (void)
1896 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1899 //=============================================================================
1901 void PF_makestatic (void)
1906 ent = G_EDICT(OFS_PARM0);
1907 if (ent == sv.edicts)
1908 PF_WARNING("makestatic: can not modify world entity\n");
1910 PF_WARNING("makestatic: can not modify free entity\n");
1913 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1918 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1919 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1920 MSG_WriteShort (&sv.signon, ent->v->frame);
1924 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1925 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1926 MSG_WriteByte (&sv.signon, ent->v->frame);
1929 MSG_WriteByte (&sv.signon, ent->v->colormap);
1930 MSG_WriteByte (&sv.signon, ent->v->skin);
1931 for (i=0 ; i<3 ; i++)
1933 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1934 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1937 // throw the entity away now
1941 //=============================================================================
1948 void PF_setspawnparms (void)
1954 ent = G_EDICT(OFS_PARM0);
1955 i = NUM_FOR_EDICT(ent);
1956 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1958 Con_Print("tried to setspawnparms on a non-client\n");
1962 // copy spawn parms out of the client_t
1963 client = svs.clients + i-1;
1964 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1965 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1973 void PF_changelevel (void)
1977 // make sure we don't issue two changelevels
1978 if (svs.changelevel_issued)
1980 svs.changelevel_issued = true;
1982 s = G_STRING(OFS_PARM0);
1983 Cbuf_AddText (va("changelevel %s\n",s));
1988 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1993 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1998 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2005 Returns a vector of length < 1
2010 void PF_randomvec (void)
2015 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2016 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2017 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2019 while (DotProduct(temp, temp) >= 1);
2020 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2027 Returns a color vector indicating the lighting at the requested point.
2029 (Internal Operation note: actually measures the light beneath the point, just like
2030 the model lighting on the client)
2035 void PF_GetLight (void)
2037 vec3_t ambientcolor, diffusecolor, diffusenormal;
2039 p = G_VECTOR(OFS_PARM0);
2040 VectorClear(ambientcolor);
2041 VectorClear(diffusecolor);
2042 VectorClear(diffusenormal);
2043 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2044 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2045 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2048 #define MAX_QC_CVARS 128
2049 cvar_t qc_cvar[MAX_QC_CVARS];
2052 void PF_registercvar (void)
2056 name = G_STRING(OFS_PARM0);
2057 value = G_STRING(OFS_PARM1);
2058 G_FLOAT(OFS_RETURN) = 0;
2059 // first check to see if it has already been defined
2060 if (Cvar_FindVar (name))
2063 // check for overlap with a command
2064 if (Cmd_Exists (name))
2066 Con_Printf("PF_registercvar: %s is a command\n", name);
2070 if (currentqc_cvar >= MAX_QC_CVARS)
2071 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2073 // copy the name and value
2074 variable = &qc_cvar[currentqc_cvar++];
2075 variable->name = Z_Malloc (strlen(name)+1);
2076 strcpy (variable->name, name);
2077 variable->string = Z_Malloc (strlen(value)+1);
2078 strcpy (variable->string, value);
2079 variable->value = atof (value);
2081 Cvar_RegisterVariable(variable);
2082 G_FLOAT(OFS_RETURN) = 1; // success
2089 returns the minimum of two supplied floats
2096 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2098 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2099 else if (pr_argc >= 3)
2102 float f = G_FLOAT(OFS_PARM0);
2103 for (i = 1;i < pr_argc;i++)
2104 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2105 f = G_FLOAT((OFS_PARM0+i*3));
2106 G_FLOAT(OFS_RETURN) = f;
2110 G_FLOAT(OFS_RETURN) = 0;
2111 PF_WARNING("min: must supply at least 2 floats\n");
2119 returns the maximum of two supplied floats
2126 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2128 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2129 else if (pr_argc >= 3)
2132 float f = G_FLOAT(OFS_PARM0);
2133 for (i = 1;i < pr_argc;i++)
2134 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2135 f = G_FLOAT((OFS_PARM0+i*3));
2136 G_FLOAT(OFS_RETURN) = f;
2140 G_FLOAT(OFS_RETURN) = 0;
2141 PF_WARNING("max: must supply at least 2 floats\n");
2149 returns number bounded by supplied range
2151 min(min, value, max)
2154 void PF_bound (void)
2156 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2163 returns a raised to power b
2170 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2177 copies data from one entity to another
2179 copyentity(src, dst)
2182 void PF_copyentity (void)
2185 in = G_EDICT(OFS_PARM0);
2186 if (in == sv.edicts)
2187 PF_WARNING("copyentity: can not read world entity\n");
2189 PF_WARNING("copyentity: can not read free entity\n");
2190 out = G_EDICT(OFS_PARM1);
2191 if (out == sv.edicts)
2192 PF_WARNING("copyentity: can not modify world entity\n");
2194 PF_WARNING("copyentity: can not modify free entity\n");
2195 memcpy(out->v, in->v, progs->entityfields * 4);
2202 sets the color of a client and broadcasts the update to all connected clients
2204 setcolor(clientent, value)
2207 void PF_setcolor (void)
2213 entnum = G_EDICTNUM(OFS_PARM0);
2214 i = G_FLOAT(OFS_PARM1);
2216 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2218 Con_Print("tried to setcolor a non-client\n");
2222 client = svs.clients + entnum-1;
2223 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2226 client->old_colors = i;
2227 client->edict->v->team = (i & 15) + 1;
2229 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2230 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2231 MSG_WriteByte (&sv.reliable_datagram, i);
2238 effect(origin, modelname, startframe, framecount, framerate)
2241 void PF_effect (void)
2244 s = G_STRING(OFS_PARM1);
2246 PF_WARNING("effect: no model specified\n");
2248 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2251 void PF_te_blood (void)
2253 if (G_FLOAT(OFS_PARM2) < 1)
2255 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2256 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2258 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2259 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2260 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2262 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2263 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2264 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2266 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2269 void PF_te_bloodshower (void)
2271 if (G_FLOAT(OFS_PARM3) < 1)
2273 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2274 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2277 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2284 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2286 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2289 void PF_te_explosionrgb (void)
2291 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2292 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2294 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2295 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2296 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2298 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2299 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2300 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2303 void PF_te_particlecube (void)
2305 if (G_FLOAT(OFS_PARM3) < 1)
2307 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2308 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2310 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2311 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2312 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2314 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2315 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2316 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2318 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2319 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2320 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2322 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2324 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2325 // gravity true/false
2326 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2328 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2331 void PF_te_particlerain (void)
2333 if (G_FLOAT(OFS_PARM3) < 1)
2335 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2336 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2338 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2339 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2340 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2342 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2343 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2344 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2346 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2347 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2348 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2350 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2352 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2355 void PF_te_particlesnow (void)
2357 if (G_FLOAT(OFS_PARM3) < 1)
2359 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2360 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2362 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2364 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2366 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2367 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2368 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2370 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2371 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2372 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2374 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2376 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2379 void PF_te_spark (void)
2381 if (G_FLOAT(OFS_PARM2) < 1)
2383 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2384 MSG_WriteByte(&sv.datagram, TE_SPARK);
2386 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2387 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2388 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2390 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2391 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2392 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2394 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2397 void PF_te_gunshotquad (void)
2399 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2400 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2402 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2403 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2404 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2407 void PF_te_spikequad (void)
2409 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2410 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2412 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2414 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2417 void PF_te_superspikequad (void)
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2424 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2427 void PF_te_explosionquad (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2432 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2434 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2437 void PF_te_smallflash (void)
2439 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2440 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2442 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2444 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2447 void PF_te_customflash (void)
2449 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2451 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2452 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2454 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2456 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2458 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2460 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2462 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2463 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2464 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2467 void PF_te_gunshot (void)
2469 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2470 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2474 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2477 void PF_te_spike (void)
2479 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2480 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2482 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2483 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2484 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2487 void PF_te_superspike (void)
2489 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2490 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2494 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2497 void PF_te_explosion (void)
2499 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2500 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2502 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2504 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2507 void PF_te_tarexplosion (void)
2509 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2510 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2517 void PF_te_wizspike (void)
2519 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2520 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2522 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2523 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2524 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2527 void PF_te_knightspike (void)
2529 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2530 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2534 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2537 void PF_te_lavasplash (void)
2539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2540 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2542 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2543 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2544 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2547 void PF_te_teleport (void)
2549 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2550 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2552 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2553 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2554 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2557 void PF_te_explosion2 (void)
2559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2560 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2562 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2563 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2564 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2566 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2567 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2570 void PF_te_lightning1 (void)
2572 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2573 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2575 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2577 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2578 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2579 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2581 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2582 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2583 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2586 void PF_te_lightning2 (void)
2588 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2589 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2591 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2593 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2594 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2595 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2597 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2598 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2599 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2602 void PF_te_lightning3 (void)
2604 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2605 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2607 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2609 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2610 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2611 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2613 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2614 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2615 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2618 void PF_te_beam (void)
2620 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2621 MSG_WriteByte(&sv.datagram, TE_BEAM);
2623 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2625 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2626 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2627 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2629 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2630 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2631 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2634 void PF_te_plasmaburn (void)
2636 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2637 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2638 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2639 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2640 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2643 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2646 vec3_t v1, clipplanenormal, normal;
2647 vec_t clipplanedist, clipdist;
2649 if (surf->flags & SURF_PLANEBACK)
2650 VectorNegate(surf->plane->normal, normal);
2652 VectorCopy(surf->plane->normal, normal);
2653 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2655 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2656 VectorNormalizeFast(v1);
2657 CrossProduct(v1, normal, clipplanenormal);
2658 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2659 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2662 clipdist = -clipdist;
2663 VectorMA(out, clipdist, clipplanenormal, out);
2668 static msurface_t *getsurface(edict_t *ed, int surfnum)
2672 if (!ed || ed->e->free)
2674 modelindex = ed->v->modelindex;
2675 if (modelindex < 1 || modelindex >= MAX_MODELS)
2677 model = sv.models[modelindex];
2678 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2680 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2684 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2685 void PF_getsurfacenumpoints(void)
2688 // return 0 if no such surface
2689 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2691 G_FLOAT(OFS_RETURN) = 0;
2695 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2697 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2698 void PF_getsurfacepoint(void)
2703 VectorClear(G_VECTOR(OFS_RETURN));
2704 ed = G_EDICT(OFS_PARM0);
2705 if (!ed || ed->e->free)
2707 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2709 pointnum = G_FLOAT(OFS_PARM2);
2710 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2712 // FIXME: implement rotation/scaling
2713 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2715 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2716 void PF_getsurfacenormal(void)
2719 VectorClear(G_VECTOR(OFS_RETURN));
2720 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2722 // FIXME: implement rotation/scaling
2723 if (surf->flags & SURF_PLANEBACK)
2724 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2726 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2728 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2729 void PF_getsurfacetexture(void)
2732 G_INT(OFS_RETURN) = 0;
2733 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2735 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2737 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2738 void PF_getsurfacenearpoint(void)
2740 int surfnum, best, modelindex;
2742 vec_t dist, bestdist;
2747 G_FLOAT(OFS_RETURN) = -1;
2748 ed = G_EDICT(OFS_PARM0);
2749 point = G_VECTOR(OFS_PARM1);
2751 if (!ed || ed->e->free)
2753 modelindex = ed->v->modelindex;
2754 if (modelindex < 1 || modelindex >= MAX_MODELS)
2756 model = sv.models[modelindex];
2757 if (!model->brushq1.numsurfaces)
2760 // FIXME: implement rotation/scaling
2761 VectorSubtract(point, ed->v->origin, p);
2763 bestdist = 1000000000;
2764 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2766 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2767 dist = PlaneDiff(p, surf->plane);
2769 if (dist < bestdist)
2771 clippointtosurface(surf, p, clipped);
2772 VectorSubtract(clipped, p, clipped);
2773 dist += DotProduct(clipped, clipped);
2774 if (dist < bestdist)
2781 G_FLOAT(OFS_RETURN) = best;
2783 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2784 void PF_getsurfaceclippedpoint(void)
2789 VectorClear(G_VECTOR(OFS_RETURN));
2790 ed = G_EDICT(OFS_PARM0);
2791 if (!ed || ed->e->free)
2793 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2795 // FIXME: implement rotation/scaling
2796 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2797 clippointtosurface(surf, p, out);
2798 // FIXME: implement rotation/scaling
2799 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2802 #define MAX_PRFILES 256
2804 qfile_t *pr_files[MAX_PRFILES];
2806 void PR_Files_Init(void)
2808 memset(pr_files, 0, sizeof(pr_files));
2811 void PR_Files_CloseAll(void)
2814 for (i = 0;i < MAX_PRFILES;i++)
2817 FS_Close(pr_files[i]);
2822 //float(string s) stof = #81; // get numerical value from a string
2825 char string[STRINGTEMP_LENGTH];
2826 PF_VarString(0, string, sizeof(string));
2827 G_FLOAT(OFS_RETURN) = atof(string);
2830 //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
2833 int filenum, mode, i;
2834 char *modestring, *filename;
2835 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2836 if (pr_files[filenum] == NULL)
2838 if (filenum >= MAX_PRFILES)
2840 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2841 G_FLOAT(OFS_RETURN) = -2;
2844 mode = G_FLOAT(OFS_PARM1);
2847 case 0: // FILE_READ
2850 case 1: // FILE_APPEND
2853 case 2: // FILE_WRITE
2857 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2858 G_FLOAT(OFS_RETURN) = -3;
2861 filename = G_STRING(OFS_PARM0);
2862 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2863 // ../ is parent directory on many platforms
2864 // // is parent directory on Amiga
2865 // / at the beginning of a path is root on unix, and parent directory on Amiga
2866 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2867 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2868 for (i = 0;filename[i];i++)
2870 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2872 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);
2873 G_FLOAT(OFS_RETURN) = -4;
2877 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2879 if (pr_files[filenum] == NULL && modestring == "rb")
2880 pr_files[filenum] = FS_Open(filename, modestring, false);
2882 if (pr_files[filenum] == NULL)
2883 G_FLOAT(OFS_RETURN) = -1;
2885 G_FLOAT(OFS_RETURN) = filenum;
2888 //void(float fhandle) fclose = #111; // closes a file
2889 void PF_fclose(void)
2891 int filenum = G_FLOAT(OFS_PARM0);
2892 if (filenum < 0 || filenum >= MAX_PRFILES)
2894 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2897 if (pr_files[filenum] == NULL)
2899 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2902 FS_Close(pr_files[filenum]);
2903 pr_files[filenum] = NULL;
2906 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2910 static char string[STRINGTEMP_LENGTH];
2911 int filenum = G_FLOAT(OFS_PARM0);
2912 if (filenum < 0 || filenum >= MAX_PRFILES)
2914 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2917 if (pr_files[filenum] == NULL)
2919 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2925 c = FS_Getc(pr_files[filenum]);
2926 if (c == '\r' || c == '\n' || c < 0)
2928 if (end < STRINGTEMP_LENGTH - 1)
2932 // remove \n following \r
2934 c = FS_Getc(pr_files[filenum]);
2935 if (developer.integer)
2936 Con_Printf("fgets: %s\n", string);
2938 G_INT(OFS_RETURN) = PR_SetString(string);
2940 G_INT(OFS_RETURN) = 0;
2943 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2947 char string[STRINGTEMP_LENGTH];
2948 int filenum = G_FLOAT(OFS_PARM0);
2949 if (filenum < 0 || filenum >= MAX_PRFILES)
2951 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2954 if (pr_files[filenum] == NULL)
2956 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2959 PF_VarString(1, string, sizeof(string));
2960 if ((stringlength = strlen(string)))
2961 FS_Write(pr_files[filenum], string, stringlength);
2962 if (developer.integer)
2963 Con_Printf("fputs: %s\n", string);
2966 //float(string s) strlen = #114; // returns how many characters are in a string
2967 void PF_strlen(void)
2970 s = G_STRING(OFS_PARM0);
2972 G_FLOAT(OFS_RETURN) = strlen(s);
2974 G_FLOAT(OFS_RETURN) = 0;
2977 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2978 void PF_strcat(void)
2980 char *s = PR_GetTempString();
2981 PF_VarString(0, s, STRINGTEMP_LENGTH);
2982 G_INT(OFS_RETURN) = PR_SetString(s);
2985 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2986 void PF_substring(void)
2988 int i, start, length;
2989 char *s, *string = PR_GetTempString();
2990 s = G_STRING(OFS_PARM0);
2991 start = G_FLOAT(OFS_PARM1);
2992 length = G_FLOAT(OFS_PARM2);
2995 for (i = 0;i < start && *s;i++, s++);
2996 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2999 G_INT(OFS_RETURN) = PR_SetString(string);
3002 //vector(string s) stov = #117; // returns vector value from a string
3005 char string[STRINGTEMP_LENGTH];
3006 PF_VarString(0, string, sizeof(string));
3007 Math_atov(string, G_VECTOR(OFS_RETURN));
3010 //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)
3011 void PF_strzone(void)
3014 in = G_STRING(OFS_PARM0);
3015 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3017 G_INT(OFS_RETURN) = PR_SetString(out);
3020 //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!!!)
3021 void PF_strunzone(void)
3023 Mem_Free(G_STRING(OFS_PARM0));
3026 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3027 //this function originally written by KrimZon, made shorter by LordHavoc
3028 void PF_clientcommand (void)
3030 client_t *temp_client;
3033 //find client for this entity
3034 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3035 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3037 Con_Print("PF_clientcommand: entity is not a client\n");
3041 temp_client = host_client;
3042 host_client = svs.clients + i;
3043 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3044 host_client = temp_client;
3047 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3048 //this function originally written by KrimZon, made shorter by LordHavoc
3049 //20040203: rewritten by LordHavoc (no longer uses allocations)
3051 char *tokens[256], tokenbuf[4096];
3052 void PF_tokenize (void)
3056 p = G_STRING(OFS_PARM0);
3060 while(COM_ParseToken(&p, false))
3062 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3064 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3066 tokens[num_tokens++] = tokenbuf + pos;
3067 strcpy(tokenbuf + pos, com_token);
3068 pos += strlen(com_token) + 1;
3071 G_FLOAT(OFS_RETURN) = num_tokens;
3074 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3075 //this function originally written by KrimZon, made shorter by LordHavoc
3078 int token_num = G_FLOAT(OFS_PARM0);
3079 if (token_num >= 0 && token_num < num_tokens)
3080 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3082 G_INT(OFS_RETURN) = PR_SetString("");
3085 //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)
3086 void PF_setattachment (void)
3088 edict_t *e = G_EDICT(OFS_PARM0);
3089 edict_t *tagentity = G_EDICT(OFS_PARM1);
3090 char *tagname = G_STRING(OFS_PARM2);
3096 PF_WARNING("setattachment: can not modify world entity\n");
3098 PF_WARNING("setattachment: can not modify free entity\n");
3100 if (tagentity == NULL)
3101 tagentity = sv.edicts;
3103 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3105 v->edict = EDICT_TO_PROG(tagentity);
3107 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3110 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3112 modelindex = (int)tagentity->v->modelindex;
3113 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3115 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3116 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3117 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3119 // FIXME: use a model function to get tag info (need to handle skeletal)
3120 if (v->_float == 0 && model->alias.aliasnum_tags)
3121 for (i = 0;i < model->alias.aliasnum_tags;i++)
3122 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3125 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);
3128 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));
3133 /////////////////////////////////////////
3134 // DP_QC_FS_SEARCH extension
3136 // qc fs search handling
3137 #define MAX_SEARCHES 128
3139 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3141 void PR_Search_Init(void)
3143 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3146 void PR_Search_Reset(void)
3149 // reset the fssearch list
3150 for(i = 0; i < MAX_SEARCHES; i++)
3151 if(pr_fssearchlist[i])
3152 FS_FreeSearch(pr_fssearchlist[i]);
3153 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3160 float search_begin(string pattern, float caseinsensitive, float quiet)
3163 void PF_search_begin(void)
3167 int caseinsens, quiet;
3169 pattern = G_STRING(OFS_PARM0);
3171 PR_CheckEmptyString(pattern);
3173 caseinsens = G_FLOAT(OFS_PARM1);
3174 quiet = G_FLOAT(OFS_PARM2);
3176 for(handle = 0; handle < MAX_SEARCHES; handle++)
3177 if(!pr_fssearchlist[handle])
3180 if(handle >= MAX_SEARCHES)
3182 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3183 G_FLOAT(OFS_RETURN) = -2;
3187 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3188 G_FLOAT(OFS_RETURN) = -1;
3190 G_FLOAT(OFS_RETURN) = handle;
3197 void search_end(float handle)
3200 void PF_search_end(void)
3204 handle = G_FLOAT(OFS_PARM0);
3206 if(handle < 0 || handle >= MAX_SEARCHES)
3208 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3211 if(pr_fssearchlist[handle] == NULL)
3213 Con_Printf("PF_search_end: no such handle %i\n", handle);
3217 FS_FreeSearch(pr_fssearchlist[handle]);
3218 pr_fssearchlist[handle] = NULL;
3225 float search_getsize(float handle)
3228 void PF_search_getsize(void)
3232 handle = G_FLOAT(OFS_PARM0);
3234 if(handle < 0 || handle >= MAX_SEARCHES)
3236 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3239 if(pr_fssearchlist[handle] == NULL)
3241 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3245 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3250 VM_search_getfilename
3252 string search_getfilename(float handle, float num)
3255 void PF_search_getfilename(void)
3257 int handle, filenum;
3260 handle = G_FLOAT(OFS_PARM0);
3261 filenum = G_FLOAT(OFS_PARM1);
3263 if(handle < 0 || handle >= MAX_SEARCHES)
3265 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3268 if(pr_fssearchlist[handle] == NULL)
3270 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3273 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3275 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3279 tmp = PR_GetTempString();
3280 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3282 G_INT(OFS_RETURN) = PR_SetString(tmp);
3285 void PF_cvar_string (void)
3291 str = G_STRING(OFS_PARM0);
3292 var = Cvar_FindVar (str);
3294 tmp = PR_GetTempString();
3295 strcpy(tmp, var->string);
3297 G_INT(OFS_RETURN) = PR_SetString(tmp);
3302 builtin_t pr_builtin[] =
3305 PF_makevectors, // #1 void(entity e) makevectors
3306 PF_setorigin, // #2 void(entity e, vector o) setorigin
3307 PF_setmodel, // #3 void(entity e, string m) setmodel
3308 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3309 NULL, // #5 void(entity e, vector min, vector max) setabssize
3310 PF_break, // #6 void() break
3311 PF_random, // #7 float() random
3312 PF_sound, // #8 void(entity e, float chan, string samp) sound
3313 PF_normalize, // #9 vector(vector v) normalize
3314 PF_error, // #10 void(string e) error
3315 PF_objerror, // #11 void(string e) objerror
3316 PF_vlen, // #12 float(vector v) vlen
3317 PF_vectoyaw, // #13 float(vector v) vectoyaw
3318 PF_Spawn, // #14 entity() spawn
3319 PF_Remove, // #15 void(entity e) remove
3320 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3321 PF_checkclient, // #17 entity() clientlist
3322 PF_Find, // #18 entity(entity start, .string fld, string match) find
3323 PF_precache_sound, // #19 void(string s) precache_sound
3324 PF_precache_model, // #20 void(string s) precache_model
3325 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3326 PF_findradius, // #22 entity(vector org, float rad) findradius
3327 PF_bprint, // #23 void(string s) bprint
3328 PF_sprint, // #24 void(entity client, string s) sprint
3329 PF_dprint, // #25 void(string s) dprint
3330 PF_ftos, // #26 void(string s) ftos
3331 PF_vtos, // #27 void(string s) vtos
3332 PF_coredump, // #28 void() coredump
3333 PF_traceon, // #29 void() traceon
3334 PF_traceoff, // #30 void() traceoff
3335 PF_eprint, // #31 void(entity e) eprint
3336 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3338 PF_droptofloor, // #34 float() droptofloor
3339 PF_lightstyle, // #35 void(float style, string value) lightstyle
3340 PF_rint, // #36 float(float v) rint
3341 PF_floor, // #37 float(float v) floor
3342 PF_ceil, // #38 float(float v) ceil
3344 PF_checkbottom, // #40 float(entity e) checkbottom
3345 PF_pointcontents , // #41 float(vector v) pointcontents
3347 PF_fabs, // #43 float(float f) fabs
3348 PF_aim, // #44 vector(entity e, float speed) aim
3349 PF_cvar, // #45 float(string s) cvar
3350 PF_localcmd, // #46 void(string s) localcmd
3351 PF_nextent, // #47 entity(entity e) nextent
3352 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3353 PF_changeyaw, // #49 void() ChangeYaw
3355 PF_vectoangles, // #51 vector(vector v) vectoangles
3356 PF_WriteByte, // #52 void(float to, float f) WriteByte
3357 PF_WriteChar, // #53 void(float to, float f) WriteChar
3358 PF_WriteShort, // #54 void(float to, float f) WriteShort
3359 PF_WriteLong, // #55 void(float to, float f) WriteLong
3360 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3361 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3362 PF_WriteString, // #58 void(float to, string s) WriteString
3363 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3364 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3365 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3366 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3367 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3368 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3369 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3371 SV_MoveToGoal, // #67 void(float step) movetogoal
3372 PF_precache_file, // #68 string(string s) precache_file
3373 PF_makestatic, // #69 void(entity e) makestatic
3374 PF_changelevel, // #70 void(string s) changelevel
3376 PF_cvar_set, // #72 void(string var, string val) cvar_set
3377 PF_centerprint, // #73 void(entity client, strings) centerprint
3378 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3379 PF_precache_model, // #75 string(string s) precache_model2
3380 PF_precache_sound, // #76 string(string s) precache_sound2
3381 PF_precache_file, // #77 string(string s) precache_file2
3382 PF_setspawnparms, // #78 void(entity e) setspawnparms
3385 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3394 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3395 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3396 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3397 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3398 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3399 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3400 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3401 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3402 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3403 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3414 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3415 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3416 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3417 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3418 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3419 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3420 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3421 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3422 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3423 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3424 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3425 a a a a a a a a // #120-199
3426 a a a a a a a a a a // #200-299
3427 a a a a a a a a a a // #300-399
3428 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3429 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3430 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3431 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3432 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3433 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3434 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3435 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3436 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3437 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3438 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3439 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3440 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3441 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3442 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3443 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3444 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3445 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3446 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3448 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3449 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3450 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3451 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3452 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3453 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3454 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3455 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3456 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3457 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3458 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3459 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3460 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3461 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3462 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3463 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3464 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3465 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3466 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3467 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3468 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3469 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3470 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3471 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3472 PF_search_begin, // #444
3473 PF_search_end, // #445
3474 PF_search_getsize, // #446
3475 PF_search_getfilename, // #447
3476 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3477 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3478 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3488 a a a a // #460-499 (LordHavoc)
3491 builtin_t *pr_builtins = pr_builtin;
3492 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3494 void PR_Cmd_Init(void)
3496 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3501 void PR_Cmd_Reset(void)
3503 Mem_EmptyPool(pr_strings_mempool);
3505 PR_Files_CloseAll();