2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
24 cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
26 mempool_t *pr_strings_mempool;
28 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
29 #define STRINGTEMP_BUFFERS 16
30 #define STRINGTEMP_LENGTH 4096
31 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
32 static int pr_string_tempindex = 0;
34 static char *PR_GetTempString(void)
37 s = pr_string_temp[pr_string_tempindex];
38 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
42 #define RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
43 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
44 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
48 ===============================================================================
52 ===============================================================================
56 void PF_VarString(int first, char *out, int outlength)
62 outend = out + outlength - 1;
63 for (i = first;i < pr_argc && out < outend;i++)
65 s = G_STRING((OFS_PARM0+i*3));
66 while (out < outend && *s)
72 char *ENGINE_EXTENSIONS =
83 "DP_ENT_CUSTOMCOLORMAP "
84 "DP_ENT_EXTERIORMODELTOCLIENT "
86 "DP_ENT_LOWPRECISION "
89 "DP_GFX_EXTERNALTEXTURES "
91 "DP_GFX_QUAKE3MODELTAGS "
95 "DP_HALFLIFE_MAP_CVAR "
99 "DP_MOVETYPEBOUNCEMISSILE "
106 "DP_QC_FINDCHAINFLAGS "
107 "DP_QC_FINDCHAINFLOAT "
110 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
114 "DP_QC_MULTIPLETEMPSTRINGS "
116 "DP_QC_SINCOSSQRTPOW "
119 "DP_QC_TRACE_MOVETYPE_HITMODEL "
120 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
121 "DP_QC_VECTORVECTORS "
125 "DP_SND_DIRECTIONLESSATTNNONE "
130 "DP_SV_DRAWONLYTOCLIENT "
132 "DP_SV_EXTERIORMODELTOCLIENT "
133 "DP_SV_NODRAWTOCLIENT "
134 "DP_SV_PLAYERPHYSICS "
135 "DP_SV_ROTATINGBMODEL "
141 "DP_TE_EXPLOSIONRGB "
143 "DP_TE_PARTICLECUBE "
144 "DP_TE_PARTICLERAIN "
145 "DP_TE_PARTICLESNOW "
147 "DP_TE_QUADEFFECTS1 "
150 "DP_TE_STANDARDEFFECTBUILTINS "
153 "KRIMZON_SV_PARSECLIENTCOMMAND "
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 = (atan2(value1[1], value1[0]) * 180 / M_PI);
531 G_FLOAT(OFS_RETURN) = yaw;
539 vector vectoangles(vector)
542 void PF_vectoangles (void)
544 double value1[3], forward, yaw, pitch;
546 VectorCopy(G_VECTOR(OFS_PARM0), value1);
548 if (value1[1] == 0 && value1[0] == 0)
558 // LordHavoc: optimized a bit
561 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
565 else if (value1[1] > 0)
570 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
571 pitch = (atan2(value1[2], forward) * 180 / M_PI);
576 VectorSet(G_VECTOR(OFS_RETURN), pitch, yaw, 0);
583 Returns a number from 0<= num < 1
588 void PF_random (void)
592 num = (rand ()&0x7fff) / ((float)0x7fff);
594 G_FLOAT(OFS_RETURN) = num;
601 particle(origin, color, count)
604 void PF_particle (void)
610 org = G_VECTOR(OFS_PARM0);
611 dir = G_VECTOR(OFS_PARM1);
612 color = G_FLOAT(OFS_PARM2);
613 count = G_FLOAT(OFS_PARM3);
614 SV_StartParticle (org, dir, color, count);
624 void PF_ambientsound (void)
629 float vol, attenuation;
632 pos = G_VECTOR (OFS_PARM0);
633 samp = G_STRING(OFS_PARM1);
634 vol = G_FLOAT(OFS_PARM2);
635 attenuation = G_FLOAT(OFS_PARM3);
637 // check to see if samp was properly precached
638 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
639 if (!strcmp(*check,samp))
644 Con_Printf("no precache: %s\n", samp);
652 // add an svc_spawnambient command to the level signon packet
655 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
657 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
659 MSG_WriteVector(&sv.signon, pos, sv.protocol);
662 MSG_WriteShort (&sv.signon, soundnum);
664 MSG_WriteByte (&sv.signon, soundnum);
666 MSG_WriteByte (&sv.signon, vol*255);
667 MSG_WriteByte (&sv.signon, attenuation*64);
675 Each entity can have eight independant sound sources, like voice,
678 Channel 0 is an auto-allocate channel, the others override anything
679 already running on that entity/channel pair.
681 An attenuation of 0 will play full volume everywhere in the level.
682 Larger attenuations will drop off.
694 entity = G_EDICT(OFS_PARM0);
695 channel = G_FLOAT(OFS_PARM1);
696 sample = G_STRING(OFS_PARM2);
697 volume = G_FLOAT(OFS_PARM3) * 255;
698 attenuation = G_FLOAT(OFS_PARM4);
700 if (volume < 0 || volume > 255)
701 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
703 if (attenuation < 0 || attenuation > 4)
704 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
706 if (channel < 0 || channel > 7)
707 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
709 SV_StartSound (entity, channel, sample, volume, attenuation);
721 PF_ERROR("break: break statement\n");
728 Used for use tracing and shot targeting
729 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
730 if the tryents flag is set.
732 traceline (vector1, vector2, tryents)
735 void PF_traceline (void)
742 pr_xfunction->builtinsprofile += 30;
744 v1 = G_VECTOR(OFS_PARM0);
745 v2 = G_VECTOR(OFS_PARM1);
746 move = G_FLOAT(OFS_PARM2);
747 ent = G_EDICT(OFS_PARM3);
749 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
751 pr_global_struct->trace_allsolid = trace.allsolid;
752 pr_global_struct->trace_startsolid = trace.startsolid;
753 pr_global_struct->trace_fraction = trace.fraction;
754 pr_global_struct->trace_inwater = trace.inwater;
755 pr_global_struct->trace_inopen = trace.inopen;
756 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
757 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
758 pr_global_struct->trace_plane_dist = trace.plane.dist;
760 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
762 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
763 // FIXME: add trace_endcontents
771 Used for use tracing and shot targeting
772 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
773 if the tryents flag is set.
775 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
778 // LordHavoc: added this for my own use, VERY useful, similar to traceline
779 void PF_tracebox (void)
781 float *v1, *v2, *m1, *m2;
786 pr_xfunction->builtinsprofile += 30;
788 v1 = G_VECTOR(OFS_PARM0);
789 m1 = G_VECTOR(OFS_PARM1);
790 m2 = G_VECTOR(OFS_PARM2);
791 v2 = G_VECTOR(OFS_PARM3);
792 move = G_FLOAT(OFS_PARM4);
793 ent = G_EDICT(OFS_PARM5);
795 trace = SV_Move (v1, m1, m2, v2, move, ent);
797 pr_global_struct->trace_allsolid = trace.allsolid;
798 pr_global_struct->trace_startsolid = trace.startsolid;
799 pr_global_struct->trace_fraction = trace.fraction;
800 pr_global_struct->trace_inwater = trace.inwater;
801 pr_global_struct->trace_inopen = trace.inopen;
802 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
803 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
804 pr_global_struct->trace_plane_dist = trace.plane.dist;
806 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
808 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
811 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
812 void PF_TraceToss (void)
818 pr_xfunction->builtinsprofile += 600;
820 ent = G_EDICT(OFS_PARM0);
821 if (ent == sv.edicts)
822 PF_WARNING("tracetoss: can not use world entity\n");
823 ignore = G_EDICT(OFS_PARM1);
825 trace = SV_Trace_Toss (ent, ignore);
827 pr_global_struct->trace_allsolid = trace.allsolid;
828 pr_global_struct->trace_startsolid = trace.startsolid;
829 pr_global_struct->trace_fraction = trace.fraction;
830 pr_global_struct->trace_inwater = trace.inwater;
831 pr_global_struct->trace_inopen = trace.inopen;
832 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
833 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
834 pr_global_struct->trace_plane_dist = trace.plane.dist;
836 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
838 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
846 Returns true if the given entity can move to the given position from it's
847 current position by walking or rolling.
849 scalar checkpos (entity, vector)
852 void PF_checkpos (void)
856 //============================================================================
859 qbyte checkpvs[MAX_MAP_LEAFS/8];
861 int PF_newcheckclient (int check)
867 // cycle to the next one
869 check = bound(1, check, svs.maxclients);
870 if (check == svs.maxclients)
878 pr_xfunction->builtinsprofile++;
880 if (i == svs.maxclients+1)
882 // look up the client's edict
884 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
885 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
887 // found a valid client (possibly the same one again)
891 // get the PVS for the entity
892 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
894 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
895 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
904 Returns a client (or object that has a client enemy) that would be a
907 If there is more than one valid option, they are cycled each frame
909 If (self.origin + self.viewofs) is not in the PVS of the current target,
910 it is not returned at all.
915 int c_invis, c_notvis;
916 void PF_checkclient (void)
921 // find a new check if on a new frame
922 if (sv.time - sv.lastchecktime >= 0.1)
924 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
925 sv.lastchecktime = sv.time;
928 // return check if it might be visible
929 ent = EDICT_NUM(sv.lastcheck);
930 if (ent->e->free || ent->v->health <= 0)
932 RETURN_EDICT(sv.edicts);
936 // if current entity can't possibly see the check entity, return 0
937 self = PROG_TO_EDICT(pr_global_struct->self);
938 VectorAdd(self->v->origin, self->v->view_ofs, view);
939 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
942 RETURN_EDICT(sv.edicts);
946 // might be able to see it
951 //============================================================================
958 Sends text over to the client's execution buffer
960 stuffcmd (clientent, value)
963 void PF_stuffcmd (void)
969 entnum = G_EDICTNUM(OFS_PARM0);
970 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
972 Con_Print("Can't stuffcmd to a non-client\n");
975 str = G_STRING(OFS_PARM1);
978 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
979 Host_ClientCommands ("%s", str);
987 Sends text to server console
992 void PF_localcmd (void)
994 Cbuf_AddText(G_STRING(OFS_PARM0));
1006 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1016 void PF_cvar_set (void)
1018 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1025 Returns a chain of entities that have origins within a spherical area
1027 findradius (origin, radius)
1030 void PF_findradius (void)
1032 edict_t *ent, *chain;
1039 chain = (edict_t *)sv.edicts;
1041 org = G_VECTOR(OFS_PARM0);
1042 radius = G_FLOAT(OFS_PARM1);
1043 radius2 = radius * radius;
1045 ent = NEXT_EDICT(sv.edicts);
1046 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1048 pr_xfunction->builtinsprofile++;
1051 if (ent->v->solid == SOLID_NOT)
1054 // LordHavoc: compare against bounding box rather than center,
1055 // and use DotProduct instead of Length, major speedup
1056 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1057 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1058 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1059 if (DotProduct(eorg, eorg) > radius2)
1062 ent->v->chain = EDICT_TO_PROG(chain);
1066 RETURN_EDICT(chain);
1075 void PF_dprint (void)
1077 char string[STRINGTEMP_LENGTH];
1078 if (developer.integer)
1080 PF_VarString(0, string, sizeof(string));
1089 v = G_FLOAT(OFS_PARM0);
1091 s = PR_GetTempString();
1092 if ((float)((int)v) == v)
1093 sprintf(s, "%i", (int)v);
1095 sprintf(s, "%f", v);
1096 G_INT(OFS_RETURN) = PR_SetString(s);
1102 v = G_FLOAT(OFS_PARM0);
1103 G_FLOAT(OFS_RETURN) = fabs(v);
1109 s = PR_GetTempString();
1110 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1111 G_INT(OFS_RETURN) = PR_SetString(s);
1117 s = PR_GetTempString();
1118 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1119 G_INT(OFS_RETURN) = PR_SetString(s);
1122 void PF_Spawn (void)
1125 pr_xfunction->builtinsprofile += 20;
1130 void PF_Remove (void)
1133 pr_xfunction->builtinsprofile += 20;
1135 ed = G_EDICT(OFS_PARM0);
1136 if (ed == sv.edicts)
1137 PF_WARNING("remove: tried to remove world\n");
1138 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1139 PF_WARNING("remove: tried to remove a client\n");
1140 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1141 if (ed->e->free && developer.integer)
1142 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1147 // entity (entity start, .string field, string match) find = #5;
1155 e = G_EDICTNUM(OFS_PARM0);
1156 f = G_INT(OFS_PARM1);
1157 s = G_STRING(OFS_PARM2);
1160 RETURN_EDICT(sv.edicts);
1164 for (e++ ; e < sv.num_edicts ; e++)
1166 pr_xfunction->builtinsprofile++;
1180 RETURN_EDICT(sv.edicts);
1183 // LordHavoc: added this for searching float, int, and entity reference fields
1184 void PF_FindFloat (void)
1191 e = G_EDICTNUM(OFS_PARM0);
1192 f = G_INT(OFS_PARM1);
1193 s = G_FLOAT(OFS_PARM2);
1195 for (e++ ; e < sv.num_edicts ; e++)
1197 pr_xfunction->builtinsprofile++;
1201 if (E_FLOAT(ed,f) == s)
1208 RETURN_EDICT(sv.edicts);
1211 // chained search for strings in entity fields
1212 // entity(.string field, string match) findchain = #402;
1213 void PF_findchain (void)
1218 edict_t *ent, *chain;
1220 chain = (edict_t *)sv.edicts;
1222 f = G_INT(OFS_PARM0);
1223 s = G_STRING(OFS_PARM1);
1226 RETURN_EDICT(sv.edicts);
1230 ent = NEXT_EDICT(sv.edicts);
1231 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1233 pr_xfunction->builtinsprofile++;
1236 t = E_STRING(ent,f);
1242 ent->v->chain = EDICT_TO_PROG(chain);
1246 RETURN_EDICT(chain);
1249 // LordHavoc: chained search for float, int, and entity reference fields
1250 // entity(.string field, float match) findchainfloat = #403;
1251 void PF_findchainfloat (void)
1256 edict_t *ent, *chain;
1258 chain = (edict_t *)sv.edicts;
1260 f = G_INT(OFS_PARM0);
1261 s = G_FLOAT(OFS_PARM1);
1263 ent = NEXT_EDICT(sv.edicts);
1264 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1266 pr_xfunction->builtinsprofile++;
1269 if (E_FLOAT(ent,f) != s)
1272 ent->v->chain = EDICT_TO_PROG(chain);
1276 RETURN_EDICT(chain);
1279 // LordHavoc: search for flags in float fields
1280 void PF_findflags (void)
1287 e = G_EDICTNUM(OFS_PARM0);
1288 f = G_INT(OFS_PARM1);
1289 s = (int)G_FLOAT(OFS_PARM2);
1291 for (e++ ; e < sv.num_edicts ; e++)
1293 pr_xfunction->builtinsprofile++;
1297 if ((int)E_FLOAT(ed,f) & s)
1304 RETURN_EDICT(sv.edicts);
1307 // LordHavoc: chained search for flags in float fields
1308 void PF_findchainflags (void)
1313 edict_t *ent, *chain;
1315 chain = (edict_t *)sv.edicts;
1317 f = G_INT(OFS_PARM0);
1318 s = (int)G_FLOAT(OFS_PARM1);
1320 ent = NEXT_EDICT(sv.edicts);
1321 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1323 pr_xfunction->builtinsprofile++;
1326 if (!((int)E_FLOAT(ent,f) & s))
1329 ent->v->chain = EDICT_TO_PROG(chain);
1333 RETURN_EDICT(chain);
1336 void PR_CheckEmptyString (char *s)
1339 PF_ERROR("Bad string");
1342 void PF_precache_file (void)
1343 { // precache_file is only used to copy files with qcc, it does nothing
1344 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1347 void PF_precache_sound (void)
1351 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1353 if (sv.state != ss_loading)
1354 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1356 s = G_STRING(OFS_PARM0);
1357 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1358 PR_CheckEmptyString (s);
1360 for (i=0 ; i<limit ; i++)
1362 if (!sv.sound_precache[i])
1364 sv.sound_precache[i] = s;
1367 if (!strcmp(sv.sound_precache[i], s))
1370 PF_ERROR("PF_precache_sound: overflow");
1373 void PF_precache_model (void)
1377 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1379 if (sv.state != ss_loading)
1380 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1382 s = G_STRING(OFS_PARM0);
1383 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1385 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1386 PR_CheckEmptyString (s);
1388 for (i = 0;i < limit;i++)
1390 if (!sv.model_precache[i])
1392 sv.model_precache[i] = s;
1393 sv.models[i] = Mod_ForName (s, true, false, false);
1396 if (!strcmp(sv.model_precache[i], s))
1399 PF_ERROR("PF_precache_model: overflow");
1403 void PF_coredump (void)
1408 void PF_traceon (void)
1413 void PF_traceoff (void)
1418 void PF_eprint (void)
1420 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1427 float(float yaw, float dist) walkmove
1430 void PF_walkmove (void)
1438 // assume failure if it returns early
1439 G_FLOAT(OFS_RETURN) = 0;
1441 ent = PROG_TO_EDICT(pr_global_struct->self);
1442 if (ent == sv.edicts)
1443 PF_WARNING("walkmove: can not modify world entity\n");
1445 PF_WARNING("walkmove: can not modify free entity\n");
1446 yaw = G_FLOAT(OFS_PARM0);
1447 dist = G_FLOAT(OFS_PARM1);
1449 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1452 yaw = yaw*M_PI*2 / 360;
1454 move[0] = cos(yaw)*dist;
1455 move[1] = sin(yaw)*dist;
1458 // save program state, because SV_movestep may call other progs
1459 oldf = pr_xfunction;
1460 oldself = pr_global_struct->self;
1462 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1465 // restore program state
1466 pr_xfunction = oldf;
1467 pr_global_struct->self = oldself;
1477 void PF_droptofloor (void)
1483 // assume failure if it returns early
1484 G_FLOAT(OFS_RETURN) = 0;
1486 ent = PROG_TO_EDICT(pr_global_struct->self);
1487 if (ent == sv.edicts)
1488 PF_WARNING("droptofloor: can not modify world entity\n");
1490 PF_WARNING("droptofloor: can not modify free entity\n");
1492 VectorCopy (ent->v->origin, end);
1495 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1497 if (trace.fraction != 1)
1499 VectorCopy (trace.endpos, ent->v->origin);
1500 SV_LinkEdict (ent, false);
1501 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1502 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1503 G_FLOAT(OFS_RETURN) = 1;
1504 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1505 ent->e->suspendedinairflag = true;
1513 void(float style, string value) lightstyle
1516 void PF_lightstyle (void)
1523 style = G_FLOAT(OFS_PARM0);
1524 val = G_STRING(OFS_PARM1);
1526 // change the string in sv
1527 sv.lightstyles[style] = val;
1529 // send message to all clients on this server
1530 if (sv.state != ss_active)
1533 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1535 if (client->netconnection)
1537 MSG_WriteChar (&client->message, svc_lightstyle);
1538 MSG_WriteChar (&client->message,style);
1539 MSG_WriteString (&client->message, val);
1547 f = G_FLOAT(OFS_PARM0);
1549 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1551 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1553 void PF_floor (void)
1555 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1559 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1568 void PF_checkbottom (void)
1570 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1578 void PF_pointcontents (void)
1580 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1587 entity nextent(entity)
1590 void PF_nextent (void)
1595 i = G_EDICTNUM(OFS_PARM0);
1598 pr_xfunction->builtinsprofile++;
1600 if (i == sv.num_edicts)
1602 RETURN_EDICT(sv.edicts);
1618 Pick a vector for the player to shoot along
1619 vector aim(entity, missilespeed)
1624 edict_t *ent, *check, *bestent;
1625 vec3_t start, dir, end, bestdir;
1628 float dist, bestdist;
1631 // assume failure if it returns early
1632 VectorClear(G_VECTOR(OFS_RETURN));
1634 ent = G_EDICT(OFS_PARM0);
1635 if (ent == sv.edicts)
1636 PF_WARNING("aim: can not use world entity\n");
1638 PF_WARNING("aim: can not use free entity\n");
1639 speed = G_FLOAT(OFS_PARM1);
1641 VectorCopy (ent->v->origin, start);
1644 // try sending a trace straight
1645 VectorCopy (pr_global_struct->v_forward, dir);
1646 VectorMA (start, 2048, dir, end);
1647 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1648 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1649 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1651 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1656 // try all possible entities
1657 VectorCopy (dir, bestdir);
1658 bestdist = sv_aim.value;
1661 check = NEXT_EDICT(sv.edicts);
1662 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1664 pr_xfunction->builtinsprofile++;
1665 if (check->v->takedamage != DAMAGE_AIM)
1669 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1670 continue; // don't aim at teammate
1671 for (j=0 ; j<3 ; j++)
1672 end[j] = check->v->origin[j]
1673 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1674 VectorSubtract (end, start, dir);
1675 VectorNormalize (dir);
1676 dist = DotProduct (dir, pr_global_struct->v_forward);
1677 if (dist < bestdist)
1678 continue; // to far to turn
1679 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1680 if (tr.ent == check)
1681 { // can shoot at this one
1689 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1690 dist = DotProduct (dir, pr_global_struct->v_forward);
1691 VectorScale (pr_global_struct->v_forward, dist, end);
1693 VectorNormalize (end);
1694 VectorCopy (end, G_VECTOR(OFS_RETURN));
1698 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1706 This was a major timewaster in progs, so it was converted to C
1709 void PF_changeyaw (void)
1712 float ideal, current, move, speed;
1714 ent = PROG_TO_EDICT(pr_global_struct->self);
1715 if (ent == sv.edicts)
1716 PF_WARNING("changeyaw: can not modify world entity\n");
1718 PF_WARNING("changeyaw: can not modify free entity\n");
1719 current = ANGLEMOD(ent->v->angles[1]);
1720 ideal = ent->v->ideal_yaw;
1721 speed = ent->v->yaw_speed;
1723 if (current == ideal)
1725 move = ideal - current;
1726 if (ideal > current)
1747 ent->v->angles[1] = ANGLEMOD (current + move);
1755 void PF_changepitch (void)
1758 float ideal, current, move, speed;
1761 ent = G_EDICT(OFS_PARM0);
1762 if (ent == sv.edicts)
1763 PF_WARNING("changepitch: can not modify world entity\n");
1765 PF_WARNING("changepitch: can not modify free entity\n");
1766 current = ANGLEMOD( ent->v->angles[0] );
1767 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1768 ideal = val->_float;
1771 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1774 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1775 speed = val->_float;
1778 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1782 if (current == ideal)
1784 move = ideal - current;
1785 if (ideal > current)
1806 ent->v->angles[0] = ANGLEMOD (current + move);
1810 ===============================================================================
1814 ===============================================================================
1817 #define MSG_BROADCAST 0 // unreliable to all
1818 #define MSG_ONE 1 // reliable to one (msg_entity)
1819 #define MSG_ALL 2 // reliable to all
1820 #define MSG_INIT 3 // write to the init string
1822 sizebuf_t *WriteDest (void)
1828 dest = G_FLOAT(OFS_PARM0);
1832 return &sv.datagram;
1835 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1836 entnum = NUM_FOR_EDICT(ent);
1837 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1838 Host_Error("WriteDest: tried to write to non-client\n");
1839 return &svs.clients[entnum-1].message;
1842 return &sv.reliable_datagram;
1848 Host_Error("WriteDest: bad destination");
1855 void PF_WriteByte (void)
1857 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1860 void PF_WriteChar (void)
1862 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1865 void PF_WriteShort (void)
1867 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1870 void PF_WriteLong (void)
1872 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1875 void PF_WriteAngle (void)
1877 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1880 void PF_WriteCoord (void)
1882 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1885 void PF_WriteString (void)
1887 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1891 void PF_WriteEntity (void)
1893 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1896 //=============================================================================
1898 void PF_makestatic (void)
1903 ent = G_EDICT(OFS_PARM0);
1904 if (ent == sv.edicts)
1905 PF_WARNING("makestatic: can not modify world entity\n");
1907 PF_WARNING("makestatic: can not modify free entity\n");
1910 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1915 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1916 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1917 MSG_WriteShort (&sv.signon, ent->v->frame);
1921 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1922 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1923 MSG_WriteByte (&sv.signon, ent->v->frame);
1926 MSG_WriteByte (&sv.signon, ent->v->colormap);
1927 MSG_WriteByte (&sv.signon, ent->v->skin);
1928 for (i=0 ; i<3 ; i++)
1930 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1931 MSG_WriteAngle(&sv.signon, ent->v->angles[i], sv.protocol);
1934 // throw the entity away now
1938 //=============================================================================
1945 void PF_setspawnparms (void)
1951 ent = G_EDICT(OFS_PARM0);
1952 i = NUM_FOR_EDICT(ent);
1953 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1955 Con_Print("tried to setspawnparms on a non-client\n");
1959 // copy spawn parms out of the client_t
1960 client = svs.clients + i-1;
1961 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1962 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1970 void PF_changelevel (void)
1974 // make sure we don't issue two changelevels
1975 if (svs.changelevel_issued)
1977 svs.changelevel_issued = true;
1979 s = G_STRING(OFS_PARM0);
1980 Cbuf_AddText (va("changelevel %s\n",s));
1985 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1990 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1995 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2002 Returns a vector of length < 1
2007 void PF_randomvec (void)
2012 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2013 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2014 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2016 while (DotProduct(temp, temp) >= 1);
2017 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2024 Returns a color vector indicating the lighting at the requested point.
2026 (Internal Operation note: actually measures the light beneath the point, just like
2027 the model lighting on the client)
2032 void PF_GetLight (void)
2034 vec3_t ambientcolor, diffusecolor, diffusenormal;
2036 p = G_VECTOR(OFS_PARM0);
2037 VectorClear(ambientcolor);
2038 VectorClear(diffusecolor);
2039 VectorClear(diffusenormal);
2040 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2041 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2042 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2045 void PF_registercvar (void)
2048 name = G_STRING(OFS_PARM0);
2049 value = G_STRING(OFS_PARM1);
2050 G_FLOAT(OFS_RETURN) = 0;
2052 // first check to see if it has already been defined
2053 if (Cvar_FindVar (name))
2056 // check for overlap with a command
2057 if (Cmd_Exists (name))
2059 Con_Printf("PF_registercvar: %s is a command\n", name);
2063 Cvar_Get(name, value, 0);
2065 G_FLOAT(OFS_RETURN) = 1; // success
2072 returns the minimum of two supplied floats
2079 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2081 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2082 else if (pr_argc >= 3)
2085 float f = G_FLOAT(OFS_PARM0);
2086 for (i = 1;i < pr_argc;i++)
2087 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2088 f = G_FLOAT((OFS_PARM0+i*3));
2089 G_FLOAT(OFS_RETURN) = f;
2093 G_FLOAT(OFS_RETURN) = 0;
2094 PF_WARNING("min: must supply at least 2 floats\n");
2102 returns the maximum of two supplied floats
2109 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2111 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2112 else if (pr_argc >= 3)
2115 float f = G_FLOAT(OFS_PARM0);
2116 for (i = 1;i < pr_argc;i++)
2117 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2118 f = G_FLOAT((OFS_PARM0+i*3));
2119 G_FLOAT(OFS_RETURN) = f;
2123 G_FLOAT(OFS_RETURN) = 0;
2124 PF_WARNING("max: must supply at least 2 floats\n");
2132 returns number bounded by supplied range
2134 min(min, value, max)
2137 void PF_bound (void)
2139 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2146 returns a raised to power b
2153 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2160 copies data from one entity to another
2162 copyentity(src, dst)
2165 void PF_copyentity (void)
2168 in = G_EDICT(OFS_PARM0);
2169 if (in == sv.edicts)
2170 PF_WARNING("copyentity: can not read world entity\n");
2172 PF_WARNING("copyentity: can not read free entity\n");
2173 out = G_EDICT(OFS_PARM1);
2174 if (out == sv.edicts)
2175 PF_WARNING("copyentity: can not modify world entity\n");
2177 PF_WARNING("copyentity: can not modify free entity\n");
2178 memcpy(out->v, in->v, progs->entityfields * 4);
2185 sets the color of a client and broadcasts the update to all connected clients
2187 setcolor(clientent, value)
2190 void PF_setcolor (void)
2196 entnum = G_EDICTNUM(OFS_PARM0);
2197 i = G_FLOAT(OFS_PARM1);
2199 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2201 Con_Print("tried to setcolor a non-client\n");
2205 client = svs.clients + entnum-1;
2206 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2209 client->old_colors = i;
2210 client->edict->v->team = (i & 15) + 1;
2212 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2213 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2214 MSG_WriteByte (&sv.reliable_datagram, i);
2221 effect(origin, modelname, startframe, framecount, framerate)
2224 void PF_effect (void)
2228 s = G_STRING(OFS_PARM1);
2230 PF_WARNING("effect: no model specified\n");
2232 i = SV_ModelIndex(s);
2234 PF_WARNING("effect: model not precached\n");
2235 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2238 void PF_te_blood (void)
2240 if (G_FLOAT(OFS_PARM2) < 1)
2242 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2243 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2245 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2249 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2250 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2251 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2253 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2256 void PF_te_bloodshower (void)
2258 if (G_FLOAT(OFS_PARM3) < 1)
2260 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2261 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2263 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2267 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2271 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2273 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2276 void PF_te_explosionrgb (void)
2278 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2281 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2285 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2286 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2287 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2290 void PF_te_particlecube (void)
2292 if (G_FLOAT(OFS_PARM3) < 1)
2294 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2295 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2297 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2298 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2301 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2309 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2311 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2312 // gravity true/false
2313 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2315 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2318 void PF_te_particlerain (void)
2320 if (G_FLOAT(OFS_PARM3) < 1)
2322 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2323 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2325 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2326 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2333 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2334 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2337 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2339 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2342 void PF_te_particlesnow (void)
2344 if (G_FLOAT(OFS_PARM3) < 1)
2346 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2347 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2349 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2350 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2351 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2354 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2357 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2358 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2359 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2361 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2363 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2366 void PF_te_spark (void)
2368 if (G_FLOAT(OFS_PARM2) < 1)
2370 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2371 MSG_WriteByte(&sv.datagram, TE_SPARK);
2373 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2374 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2375 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2377 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2378 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2379 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2381 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2384 void PF_te_gunshotquad (void)
2386 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2387 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2389 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2390 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2391 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2394 void PF_te_spikequad (void)
2396 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2397 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2399 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2400 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2401 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2404 void PF_te_superspikequad (void)
2406 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2407 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2409 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2410 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2414 void PF_te_explosionquad (void)
2416 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2417 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2419 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2420 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2421 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2424 void PF_te_smallflash (void)
2426 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2427 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2429 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2430 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2431 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2434 void PF_te_customflash (void)
2436 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2438 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2439 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2441 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2442 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2443 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2445 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2447 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2449 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2450 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2451 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2454 void PF_te_gunshot (void)
2456 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2457 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2459 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2460 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2461 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2464 void PF_te_spike (void)
2466 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2467 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2469 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2470 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2471 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2474 void PF_te_superspike (void)
2476 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2477 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2479 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2480 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2481 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2484 void PF_te_explosion (void)
2486 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2487 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2489 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2490 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2491 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2494 void PF_te_tarexplosion (void)
2496 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2497 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2499 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2500 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2501 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2504 void PF_te_wizspike (void)
2506 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2507 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2509 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2510 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2511 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2514 void PF_te_knightspike (void)
2516 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2517 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2519 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2520 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2521 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2524 void PF_te_lavasplash (void)
2526 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2527 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2529 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2530 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2531 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2534 void PF_te_teleport (void)
2536 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2537 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2539 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2540 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2541 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2544 void PF_te_explosion2 (void)
2546 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2547 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2549 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2550 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2551 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2553 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2554 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2557 void PF_te_lightning1 (void)
2559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2560 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2562 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2564 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2565 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2566 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2568 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2569 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2570 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2573 void PF_te_lightning2 (void)
2575 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2576 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2578 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2580 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2581 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2582 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2584 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2585 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2586 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2589 void PF_te_lightning3 (void)
2591 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2592 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2594 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2596 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2597 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2598 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2600 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2601 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2602 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2605 void PF_te_beam (void)
2607 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2608 MSG_WriteByte(&sv.datagram, TE_BEAM);
2610 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2612 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2613 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2614 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2616 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2617 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2618 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2621 void PF_te_plasmaburn (void)
2623 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2624 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2625 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2626 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2627 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2630 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2633 vec3_t v1, clipplanenormal, normal;
2634 vec_t clipplanedist, clipdist;
2636 if (surf->flags & SURF_PLANEBACK)
2637 VectorNegate(surf->plane->normal, normal);
2639 VectorCopy(surf->plane->normal, normal);
2640 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2642 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2643 VectorNormalizeFast(v1);
2644 CrossProduct(v1, normal, clipplanenormal);
2645 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2646 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2649 clipdist = -clipdist;
2650 VectorMA(out, clipdist, clipplanenormal, out);
2655 static msurface_t *getsurface(edict_t *ed, int surfnum)
2659 if (!ed || ed->e->free)
2661 modelindex = ed->v->modelindex;
2662 if (modelindex < 1 || modelindex >= MAX_MODELS)
2664 model = sv.models[modelindex];
2665 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2667 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2671 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2672 void PF_getsurfacenumpoints(void)
2675 // return 0 if no such surface
2676 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2678 G_FLOAT(OFS_RETURN) = 0;
2682 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2684 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2685 void PF_getsurfacepoint(void)
2690 VectorClear(G_VECTOR(OFS_RETURN));
2691 ed = G_EDICT(OFS_PARM0);
2692 if (!ed || ed->e->free)
2694 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2696 pointnum = G_FLOAT(OFS_PARM2);
2697 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2699 // FIXME: implement rotation/scaling
2700 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2702 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2703 void PF_getsurfacenormal(void)
2706 VectorClear(G_VECTOR(OFS_RETURN));
2707 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2709 // FIXME: implement rotation/scaling
2710 if (surf->flags & SURF_PLANEBACK)
2711 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2713 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2715 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2716 void PF_getsurfacetexture(void)
2719 G_INT(OFS_RETURN) = 0;
2720 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2722 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2724 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2725 void PF_getsurfacenearpoint(void)
2727 int surfnum, best, modelindex;
2729 vec_t dist, bestdist;
2734 G_FLOAT(OFS_RETURN) = -1;
2735 ed = G_EDICT(OFS_PARM0);
2736 point = G_VECTOR(OFS_PARM1);
2738 if (!ed || ed->e->free)
2740 modelindex = ed->v->modelindex;
2741 if (modelindex < 1 || modelindex >= MAX_MODELS)
2743 model = sv.models[modelindex];
2744 if (!model->brushq1.numsurfaces)
2747 // FIXME: implement rotation/scaling
2748 VectorSubtract(point, ed->v->origin, p);
2750 bestdist = 1000000000;
2751 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2753 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2754 dist = PlaneDiff(p, surf->plane);
2756 if (dist < bestdist)
2758 clippointtosurface(surf, p, clipped);
2759 VectorSubtract(clipped, p, clipped);
2760 dist += DotProduct(clipped, clipped);
2761 if (dist < bestdist)
2768 G_FLOAT(OFS_RETURN) = best;
2770 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2771 void PF_getsurfaceclippedpoint(void)
2776 VectorClear(G_VECTOR(OFS_RETURN));
2777 ed = G_EDICT(OFS_PARM0);
2778 if (!ed || ed->e->free)
2780 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2782 // FIXME: implement rotation/scaling
2783 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2784 clippointtosurface(surf, p, out);
2785 // FIXME: implement rotation/scaling
2786 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2789 #define MAX_PRFILES 256
2791 qfile_t *pr_files[MAX_PRFILES];
2793 void PR_Files_Init(void)
2795 memset(pr_files, 0, sizeof(pr_files));
2798 void PR_Files_CloseAll(void)
2801 for (i = 0;i < MAX_PRFILES;i++)
2804 FS_Close(pr_files[i]);
2809 //float(string s) stof = #81; // get numerical value from a string
2812 char string[STRINGTEMP_LENGTH];
2813 PF_VarString(0, string, sizeof(string));
2814 G_FLOAT(OFS_RETURN) = atof(string);
2817 //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
2820 int filenum, mode, i;
2821 char *modestring, *filename;
2822 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2823 if (pr_files[filenum] == NULL)
2825 if (filenum >= MAX_PRFILES)
2827 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2828 G_FLOAT(OFS_RETURN) = -2;
2831 mode = G_FLOAT(OFS_PARM1);
2834 case 0: // FILE_READ
2837 case 1: // FILE_APPEND
2840 case 2: // FILE_WRITE
2844 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2845 G_FLOAT(OFS_RETURN) = -3;
2848 filename = G_STRING(OFS_PARM0);
2849 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2850 // ../ is parent directory on many platforms
2851 // // is parent directory on Amiga
2852 // / at the beginning of a path is root on unix, and parent directory on Amiga
2853 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2854 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2855 for (i = 0;filename[i];i++)
2857 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2859 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);
2860 G_FLOAT(OFS_RETURN) = -4;
2864 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2866 if (pr_files[filenum] == NULL && modestring == "rb")
2867 pr_files[filenum] = FS_Open(filename, modestring, false);
2869 if (pr_files[filenum] == NULL)
2870 G_FLOAT(OFS_RETURN) = -1;
2872 G_FLOAT(OFS_RETURN) = filenum;
2875 //void(float fhandle) fclose = #111; // closes a file
2876 void PF_fclose(void)
2878 int filenum = G_FLOAT(OFS_PARM0);
2879 if (filenum < 0 || filenum >= MAX_PRFILES)
2881 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2884 if (pr_files[filenum] == NULL)
2886 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2889 FS_Close(pr_files[filenum]);
2890 pr_files[filenum] = NULL;
2893 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2897 static char string[STRINGTEMP_LENGTH];
2898 int filenum = G_FLOAT(OFS_PARM0);
2899 if (filenum < 0 || filenum >= MAX_PRFILES)
2901 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2904 if (pr_files[filenum] == NULL)
2906 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2912 c = FS_Getc(pr_files[filenum]);
2913 if (c == '\r' || c == '\n' || c < 0)
2915 if (end < STRINGTEMP_LENGTH - 1)
2919 // remove \n following \r
2921 c = FS_Getc(pr_files[filenum]);
2922 if (developer.integer)
2923 Con_Printf("fgets: %s\n", string);
2925 G_INT(OFS_RETURN) = PR_SetString(string);
2927 G_INT(OFS_RETURN) = 0;
2930 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2934 char string[STRINGTEMP_LENGTH];
2935 int filenum = G_FLOAT(OFS_PARM0);
2936 if (filenum < 0 || filenum >= MAX_PRFILES)
2938 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2941 if (pr_files[filenum] == NULL)
2943 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2946 PF_VarString(1, string, sizeof(string));
2947 if ((stringlength = strlen(string)))
2948 FS_Write(pr_files[filenum], string, stringlength);
2949 if (developer.integer)
2950 Con_Printf("fputs: %s\n", string);
2953 //float(string s) strlen = #114; // returns how many characters are in a string
2954 void PF_strlen(void)
2957 s = G_STRING(OFS_PARM0);
2959 G_FLOAT(OFS_RETURN) = strlen(s);
2961 G_FLOAT(OFS_RETURN) = 0;
2964 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2965 void PF_strcat(void)
2967 char *s = PR_GetTempString();
2968 PF_VarString(0, s, STRINGTEMP_LENGTH);
2969 G_INT(OFS_RETURN) = PR_SetString(s);
2972 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2973 void PF_substring(void)
2975 int i, start, length;
2976 char *s, *string = PR_GetTempString();
2977 s = G_STRING(OFS_PARM0);
2978 start = G_FLOAT(OFS_PARM1);
2979 length = G_FLOAT(OFS_PARM2);
2982 for (i = 0;i < start && *s;i++, s++);
2983 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2986 G_INT(OFS_RETURN) = PR_SetString(string);
2989 //vector(string s) stov = #117; // returns vector value from a string
2992 char string[STRINGTEMP_LENGTH];
2993 PF_VarString(0, string, sizeof(string));
2994 Math_atov(string, G_VECTOR(OFS_RETURN));
2997 //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)
2998 void PF_strzone(void)
3001 in = G_STRING(OFS_PARM0);
3002 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3004 G_INT(OFS_RETURN) = PR_SetString(out);
3007 //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!!!)
3008 void PF_strunzone(void)
3010 Mem_Free(G_STRING(OFS_PARM0));
3013 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3014 //this function originally written by KrimZon, made shorter by LordHavoc
3015 void PF_clientcommand (void)
3017 client_t *temp_client;
3020 //find client for this entity
3021 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3022 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3024 Con_Print("PF_clientcommand: entity is not a client\n");
3028 temp_client = host_client;
3029 host_client = svs.clients + i;
3030 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3031 host_client = temp_client;
3034 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3035 //this function originally written by KrimZon, made shorter by LordHavoc
3036 //20040203: rewritten by LordHavoc (no longer uses allocations)
3038 char *tokens[256], tokenbuf[4096];
3039 void PF_tokenize (void)
3043 p = G_STRING(OFS_PARM0);
3047 while(COM_ParseToken(&p, false))
3049 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3051 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3053 tokens[num_tokens++] = tokenbuf + pos;
3054 strcpy(tokenbuf + pos, com_token);
3055 pos += strlen(com_token) + 1;
3058 G_FLOAT(OFS_RETURN) = num_tokens;
3061 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3062 //this function originally written by KrimZon, made shorter by LordHavoc
3065 int token_num = G_FLOAT(OFS_PARM0);
3066 if (token_num >= 0 && token_num < num_tokens)
3067 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3069 G_INT(OFS_RETURN) = PR_SetString("");
3072 //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)
3073 void PF_setattachment (void)
3075 edict_t *e = G_EDICT(OFS_PARM0);
3076 edict_t *tagentity = G_EDICT(OFS_PARM1);
3077 char *tagname = G_STRING(OFS_PARM2);
3083 PF_WARNING("setattachment: can not modify world entity\n");
3085 PF_WARNING("setattachment: can not modify free entity\n");
3087 if (tagentity == NULL)
3088 tagentity = sv.edicts;
3090 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3092 v->edict = EDICT_TO_PROG(tagentity);
3094 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3097 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3099 modelindex = (int)tagentity->v->modelindex;
3100 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3102 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3103 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3104 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3106 // FIXME: use a model function to get tag info (need to handle skeletal)
3107 if (v->_float == 0 && model->alias.aliasnum_tags)
3108 for (i = 0;i < model->alias.aliasnum_tags;i++)
3109 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3112 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);
3115 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));
3120 /////////////////////////////////////////
3121 // DP_QC_FS_SEARCH extension
3123 // qc fs search handling
3124 #define MAX_SEARCHES 128
3126 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3128 void PR_Search_Init(void)
3130 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3133 void PR_Search_Reset(void)
3136 // reset the fssearch list
3137 for(i = 0; i < MAX_SEARCHES; i++)
3138 if(pr_fssearchlist[i])
3139 FS_FreeSearch(pr_fssearchlist[i]);
3140 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3147 float search_begin(string pattern, float caseinsensitive, float quiet)
3150 void PF_search_begin(void)
3154 int caseinsens, quiet;
3156 pattern = G_STRING(OFS_PARM0);
3158 PR_CheckEmptyString(pattern);
3160 caseinsens = G_FLOAT(OFS_PARM1);
3161 quiet = G_FLOAT(OFS_PARM2);
3163 for(handle = 0; handle < MAX_SEARCHES; handle++)
3164 if(!pr_fssearchlist[handle])
3167 if(handle >= MAX_SEARCHES)
3169 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3170 G_FLOAT(OFS_RETURN) = -2;
3174 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3175 G_FLOAT(OFS_RETURN) = -1;
3177 G_FLOAT(OFS_RETURN) = handle;
3184 void search_end(float handle)
3187 void PF_search_end(void)
3191 handle = G_FLOAT(OFS_PARM0);
3193 if(handle < 0 || handle >= MAX_SEARCHES)
3195 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3198 if(pr_fssearchlist[handle] == NULL)
3200 Con_Printf("PF_search_end: no such handle %i\n", handle);
3204 FS_FreeSearch(pr_fssearchlist[handle]);
3205 pr_fssearchlist[handle] = NULL;
3212 float search_getsize(float handle)
3215 void PF_search_getsize(void)
3219 handle = G_FLOAT(OFS_PARM0);
3221 if(handle < 0 || handle >= MAX_SEARCHES)
3223 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3226 if(pr_fssearchlist[handle] == NULL)
3228 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3232 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3237 VM_search_getfilename
3239 string search_getfilename(float handle, float num)
3242 void PF_search_getfilename(void)
3244 int handle, filenum;
3247 handle = G_FLOAT(OFS_PARM0);
3248 filenum = G_FLOAT(OFS_PARM1);
3250 if(handle < 0 || handle >= MAX_SEARCHES)
3252 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3255 if(pr_fssearchlist[handle] == NULL)
3257 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3260 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3262 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3266 tmp = PR_GetTempString();
3267 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3269 G_INT(OFS_RETURN) = PR_SetString(tmp);
3272 void PF_cvar_string (void)
3278 str = G_STRING(OFS_PARM0);
3279 var = Cvar_FindVar (str);
3281 tmp = PR_GetTempString();
3282 strcpy(tmp, var->string);
3284 G_INT(OFS_RETURN) = PR_SetString(tmp);
3289 builtin_t pr_builtin[] =
3292 PF_makevectors, // #1 void(entity e) makevectors
3293 PF_setorigin, // #2 void(entity e, vector o) setorigin
3294 PF_setmodel, // #3 void(entity e, string m) setmodel
3295 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3296 NULL, // #5 void(entity e, vector min, vector max) setabssize
3297 PF_break, // #6 void() break
3298 PF_random, // #7 float() random
3299 PF_sound, // #8 void(entity e, float chan, string samp) sound
3300 PF_normalize, // #9 vector(vector v) normalize
3301 PF_error, // #10 void(string e) error
3302 PF_objerror, // #11 void(string e) objerror
3303 PF_vlen, // #12 float(vector v) vlen
3304 PF_vectoyaw, // #13 float(vector v) vectoyaw
3305 PF_Spawn, // #14 entity() spawn
3306 PF_Remove, // #15 void(entity e) remove
3307 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3308 PF_checkclient, // #17 entity() clientlist
3309 PF_Find, // #18 entity(entity start, .string fld, string match) find
3310 PF_precache_sound, // #19 void(string s) precache_sound
3311 PF_precache_model, // #20 void(string s) precache_model
3312 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3313 PF_findradius, // #22 entity(vector org, float rad) findradius
3314 PF_bprint, // #23 void(string s) bprint
3315 PF_sprint, // #24 void(entity client, string s) sprint
3316 PF_dprint, // #25 void(string s) dprint
3317 PF_ftos, // #26 void(string s) ftos
3318 PF_vtos, // #27 void(string s) vtos
3319 PF_coredump, // #28 void() coredump
3320 PF_traceon, // #29 void() traceon
3321 PF_traceoff, // #30 void() traceoff
3322 PF_eprint, // #31 void(entity e) eprint
3323 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3325 PF_droptofloor, // #34 float() droptofloor
3326 PF_lightstyle, // #35 void(float style, string value) lightstyle
3327 PF_rint, // #36 float(float v) rint
3328 PF_floor, // #37 float(float v) floor
3329 PF_ceil, // #38 float(float v) ceil
3331 PF_checkbottom, // #40 float(entity e) checkbottom
3332 PF_pointcontents , // #41 float(vector v) pointcontents
3334 PF_fabs, // #43 float(float f) fabs
3335 PF_aim, // #44 vector(entity e, float speed) aim
3336 PF_cvar, // #45 float(string s) cvar
3337 PF_localcmd, // #46 void(string s) localcmd
3338 PF_nextent, // #47 entity(entity e) nextent
3339 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3340 PF_changeyaw, // #49 void() ChangeYaw
3342 PF_vectoangles, // #51 vector(vector v) vectoangles
3343 PF_WriteByte, // #52 void(float to, float f) WriteByte
3344 PF_WriteChar, // #53 void(float to, float f) WriteChar
3345 PF_WriteShort, // #54 void(float to, float f) WriteShort
3346 PF_WriteLong, // #55 void(float to, float f) WriteLong
3347 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3348 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3349 PF_WriteString, // #58 void(float to, string s) WriteString
3350 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3351 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3352 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3353 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3354 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3355 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3356 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3358 SV_MoveToGoal, // #67 void(float step) movetogoal
3359 PF_precache_file, // #68 string(string s) precache_file
3360 PF_makestatic, // #69 void(entity e) makestatic
3361 PF_changelevel, // #70 void(string s) changelevel
3363 PF_cvar_set, // #72 void(string var, string val) cvar_set
3364 PF_centerprint, // #73 void(entity client, strings) centerprint
3365 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3366 PF_precache_model, // #75 string(string s) precache_model2
3367 PF_precache_sound, // #76 string(string s) precache_sound2
3368 PF_precache_file, // #77 string(string s) precache_file2
3369 PF_setspawnparms, // #78 void(entity e) setspawnparms
3372 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3381 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3382 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3383 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3384 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3385 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3386 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3387 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3388 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3389 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3390 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3401 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3402 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3403 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3404 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3405 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3406 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3407 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3408 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3409 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3410 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3411 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3412 a a a a a a a a // #120-199
3413 a a a a a a a a a a // #200-299
3414 a a a a a a a a a a // #300-399
3415 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3416 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3417 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3418 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3419 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3420 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3421 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3422 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3423 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3424 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3425 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3426 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3427 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3428 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3429 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3430 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3431 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3432 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3433 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3434 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3435 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3436 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3437 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3438 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3439 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3440 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3441 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3442 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3443 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3444 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3445 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3446 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3448 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3449 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3450 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3451 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3452 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3453 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3454 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3455 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3456 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3457 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3458 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3459 PF_search_begin, // #444
3460 PF_search_end, // #445
3461 PF_search_getsize, // #446
3462 PF_search_getfilename, // #447
3463 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3464 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3465 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3475 a a a a // #460-499 (LordHavoc)
3478 builtin_t *pr_builtins = pr_builtin;
3479 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3481 void PR_Cmd_Init(void)
3483 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3488 void PR_Cmd_Reset(void)
3490 Mem_EmptyPool(pr_strings_mempool);
3492 PR_Files_CloseAll();