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 =
84 "DP_ENT_CUSTOMCOLORMAP "
85 "DP_ENT_EXTERIORMODELTOCLIENT "
87 "DP_ENT_LOWPRECISION "
90 "DP_GFX_EXTERNALTEXTURES "
92 "DP_GFX_QUAKE3MODELTAGS "
96 "DP_HALFLIFE_MAP_CVAR "
100 "DP_MOVETYPEBOUNCEMISSILE "
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 "
158 "TENEBRAE_GFX_DLIGHTS "
162 qboolean checkextension(char *name)
167 for (e = ENGINE_EXTENSIONS;*e;e++)
174 while (*e && *e != ' ')
176 if (e - start == len)
177 if (!strncasecmp(start, name, len))
187 returns true if the extension is supported by the server
189 checkextension(extensionname)
192 void PF_checkextension (void)
194 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
201 This is a TERMINAL error, which will kill off the entire server.
210 char string[STRINGTEMP_LENGTH];
212 PF_VarString(0, string, sizeof(string));
213 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
214 ed = PROG_TO_EDICT(pr_global_struct->self);
217 PF_ERROR("Program error");
224 Dumps out self, then an error message. The program is aborted and self is
225 removed, but the level can continue.
230 void PF_objerror (void)
233 char string[STRINGTEMP_LENGTH];
235 PF_VarString(0, string, sizeof(string));
236 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
237 ed = PROG_TO_EDICT(pr_global_struct->self);
247 Writes new values for v_forward, v_up, and v_right based on angles
251 void PF_makevectors (void)
253 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
260 Writes new values for v_forward, v_up, and v_right based on the given forward vector
261 vectorvectors(vector, vector)
264 void PF_vectorvectors (void)
266 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
267 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
274 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.
276 setorigin (entity, origin)
279 void PF_setorigin (void)
284 e = G_EDICT(OFS_PARM0);
286 PF_WARNING("setorigin: can not modify world entity\n");
288 PF_WARNING("setorigin: can not modify free entity\n");
289 org = G_VECTOR(OFS_PARM1);
290 VectorCopy (org, e->v->origin);
291 SV_LinkEdict (e, false);
295 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
299 for (i=0 ; i<3 ; i++)
301 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
303 // set derived values
304 VectorCopy (min, e->v->mins);
305 VectorCopy (max, e->v->maxs);
306 VectorSubtract (max, min, e->v->size);
308 SV_LinkEdict (e, false);
315 the size box is rotated by the current angle
316 LordHavoc: no it isn't...
318 setsize (entity, minvector, maxvector)
321 void PF_setsize (void)
326 e = G_EDICT(OFS_PARM0);
328 PF_WARNING("setsize: can not modify world entity\n");
330 PF_WARNING("setsize: can not modify free entity\n");
331 min = G_VECTOR(OFS_PARM1);
332 max = G_VECTOR(OFS_PARM2);
333 SetMinMaxSize (e, min, max, false);
341 setmodel(entity, model)
344 void PF_setmodel (void)
351 e = G_EDICT(OFS_PARM0);
353 PF_WARNING("setmodel: can not modify world entity\n");
355 PF_WARNING("setmodel: can not modify free entity\n");
356 m = G_STRING(OFS_PARM1);
358 // check to see if model was properly precached
359 for (i=0, check = sv.model_precache ; *check ; i++, check++)
360 if (!strcmp(*check, m))
364 PF_WARNING("setmodel: no precache\n");
367 e->v->model = PR_SetString(*check);
368 e->v->modelindex = i;
370 mod = sv.models[ (int)e->v->modelindex];
373 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
375 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
382 broadcast print to everyone on server
387 void PF_bprint (void)
389 char string[STRINGTEMP_LENGTH];
390 PF_VarString(0, string, sizeof(string));
391 SV_BroadcastPrint(string);
398 single print to a specific client
400 sprint(clientent, value)
403 void PF_sprint (void)
407 char string[STRINGTEMP_LENGTH];
409 entnum = G_EDICTNUM(OFS_PARM0);
411 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
413 Con_Print("tried to sprint to a non-client\n");
417 client = svs.clients + entnum-1;
418 if (!client->netconnection)
420 PF_VarString(1, string, sizeof(string));
421 MSG_WriteChar(&client->message,svc_print);
422 MSG_WriteString(&client->message, string);
430 single print to a specific client
432 centerprint(clientent, value)
435 void PF_centerprint (void)
439 char string[STRINGTEMP_LENGTH];
441 entnum = G_EDICTNUM(OFS_PARM0);
443 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
445 Con_Print("tried to sprint to a non-client\n");
449 client = svs.clients + entnum-1;
450 if (!client->netconnection)
452 PF_VarString(1, string, sizeof(string));
453 MSG_WriteChar(&client->message,svc_centerprint);
454 MSG_WriteString(&client->message, string);
462 vector normalize(vector)
465 void PF_normalize (void)
471 value1 = G_VECTOR(OFS_PARM0);
473 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
477 newvalue[0] = newvalue[1] = newvalue[2] = 0;
481 newvalue[0] = value1[0] * new;
482 newvalue[1] = value1[1] * new;
483 newvalue[2] = value1[2] * new;
486 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
501 value1 = G_VECTOR(OFS_PARM0);
503 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
506 G_FLOAT(OFS_RETURN) = new;
513 float vectoyaw(vector)
516 void PF_vectoyaw (void)
521 value1 = G_VECTOR(OFS_PARM0);
523 if (value1[1] == 0 && value1[0] == 0)
527 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
532 G_FLOAT(OFS_RETURN) = yaw;
540 vector vectoangles(vector)
543 void PF_vectoangles (void)
545 double value1[3], forward, yaw, pitch;
547 VectorCopy(G_VECTOR(OFS_PARM0), value1);
549 if (value1[1] == 0 && value1[0] == 0)
559 // LordHavoc: optimized a bit
562 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
566 else if (value1[1] > 0)
571 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
572 pitch = (atan2(value1[2], forward) * 180 / M_PI);
577 VectorSet(G_VECTOR(OFS_RETURN), pitch, yaw, 0);
584 Returns a number from 0<= num < 1
589 void PF_random (void)
593 num = (rand ()&0x7fff) / ((float)0x7fff);
595 G_FLOAT(OFS_RETURN) = num;
602 particle(origin, color, count)
605 void PF_particle (void)
611 org = G_VECTOR(OFS_PARM0);
612 dir = G_VECTOR(OFS_PARM1);
613 color = G_FLOAT(OFS_PARM2);
614 count = G_FLOAT(OFS_PARM3);
615 SV_StartParticle (org, dir, color, count);
625 void PF_ambientsound (void)
630 float vol, attenuation;
633 pos = G_VECTOR (OFS_PARM0);
634 samp = G_STRING(OFS_PARM1);
635 vol = G_FLOAT(OFS_PARM2);
636 attenuation = G_FLOAT(OFS_PARM3);
638 // check to see if samp was properly precached
639 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
640 if (!strcmp(*check,samp))
645 Con_Printf("no precache: %s\n", samp);
653 // add an svc_spawnambient command to the level signon packet
656 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
658 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
660 MSG_WriteVector(&sv.signon, pos, sv.protocol);
663 MSG_WriteShort (&sv.signon, soundnum);
665 MSG_WriteByte (&sv.signon, soundnum);
667 MSG_WriteByte (&sv.signon, vol*255);
668 MSG_WriteByte (&sv.signon, attenuation*64);
676 Each entity can have eight independant sound sources, like voice,
679 Channel 0 is an auto-allocate channel, the others override anything
680 already running on that entity/channel pair.
682 An attenuation of 0 will play full volume everywhere in the level.
683 Larger attenuations will drop off.
695 entity = G_EDICT(OFS_PARM0);
696 channel = G_FLOAT(OFS_PARM1);
697 sample = G_STRING(OFS_PARM2);
698 volume = G_FLOAT(OFS_PARM3) * 255;
699 attenuation = G_FLOAT(OFS_PARM4);
701 if (volume < 0 || volume > 255)
702 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
704 if (attenuation < 0 || attenuation > 4)
705 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
707 if (channel < 0 || channel > 7)
708 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
710 SV_StartSound (entity, channel, sample, volume, attenuation);
722 PF_ERROR("break: break statement\n");
729 Used for use tracing and shot targeting
730 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
731 if the tryents flag is set.
733 traceline (vector1, vector2, tryents)
736 void PF_traceline (void)
743 pr_xfunction->builtinsprofile += 30;
745 v1 = G_VECTOR(OFS_PARM0);
746 v2 = G_VECTOR(OFS_PARM1);
747 move = G_FLOAT(OFS_PARM2);
748 ent = G_EDICT(OFS_PARM3);
750 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
752 pr_global_struct->trace_allsolid = trace.allsolid;
753 pr_global_struct->trace_startsolid = trace.startsolid;
754 pr_global_struct->trace_fraction = trace.fraction;
755 pr_global_struct->trace_inwater = trace.inwater;
756 pr_global_struct->trace_inopen = trace.inopen;
757 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
758 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
759 pr_global_struct->trace_plane_dist = trace.plane.dist;
761 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
763 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
764 // FIXME: add trace_endcontents
772 Used for use tracing and shot targeting
773 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
774 if the tryents flag is set.
776 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
779 // LordHavoc: added this for my own use, VERY useful, similar to traceline
780 void PF_tracebox (void)
782 float *v1, *v2, *m1, *m2;
787 pr_xfunction->builtinsprofile += 30;
789 v1 = G_VECTOR(OFS_PARM0);
790 m1 = G_VECTOR(OFS_PARM1);
791 m2 = G_VECTOR(OFS_PARM2);
792 v2 = G_VECTOR(OFS_PARM3);
793 move = G_FLOAT(OFS_PARM4);
794 ent = G_EDICT(OFS_PARM5);
796 trace = SV_Move (v1, m1, m2, v2, move, ent);
798 pr_global_struct->trace_allsolid = trace.allsolid;
799 pr_global_struct->trace_startsolid = trace.startsolid;
800 pr_global_struct->trace_fraction = trace.fraction;
801 pr_global_struct->trace_inwater = trace.inwater;
802 pr_global_struct->trace_inopen = trace.inopen;
803 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
804 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
805 pr_global_struct->trace_plane_dist = trace.plane.dist;
807 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
809 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
812 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
813 void PF_TraceToss (void)
819 pr_xfunction->builtinsprofile += 600;
821 ent = G_EDICT(OFS_PARM0);
822 if (ent == sv.edicts)
823 PF_WARNING("tracetoss: can not use world entity\n");
824 ignore = G_EDICT(OFS_PARM1);
826 trace = SV_Trace_Toss (ent, ignore);
828 pr_global_struct->trace_allsolid = trace.allsolid;
829 pr_global_struct->trace_startsolid = trace.startsolid;
830 pr_global_struct->trace_fraction = trace.fraction;
831 pr_global_struct->trace_inwater = trace.inwater;
832 pr_global_struct->trace_inopen = trace.inopen;
833 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
834 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
835 pr_global_struct->trace_plane_dist = trace.plane.dist;
837 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
839 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
847 Returns true if the given entity can move to the given position from it's
848 current position by walking or rolling.
850 scalar checkpos (entity, vector)
853 void PF_checkpos (void)
857 //============================================================================
860 qbyte checkpvs[MAX_MAP_LEAFS/8];
862 int PF_newcheckclient (int check)
868 // cycle to the next one
870 check = bound(1, check, svs.maxclients);
871 if (check == svs.maxclients)
879 pr_xfunction->builtinsprofile++;
881 if (i == svs.maxclients+1)
883 // look up the client's edict
885 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
886 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
888 // found a valid client (possibly the same one again)
892 // get the PVS for the entity
893 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
895 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
896 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
905 Returns a client (or object that has a client enemy) that would be a
908 If there is more than one valid option, they are cycled each frame
910 If (self.origin + self.viewofs) is not in the PVS of the current target,
911 it is not returned at all.
916 int c_invis, c_notvis;
917 void PF_checkclient (void)
922 // find a new check if on a new frame
923 if (sv.time - sv.lastchecktime >= 0.1)
925 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
926 sv.lastchecktime = sv.time;
929 // return check if it might be visible
930 ent = EDICT_NUM(sv.lastcheck);
931 if (ent->e->free || ent->v->health <= 0)
933 RETURN_EDICT(sv.edicts);
937 // if current entity can't possibly see the check entity, return 0
938 self = PROG_TO_EDICT(pr_global_struct->self);
939 VectorAdd(self->v->origin, self->v->view_ofs, view);
940 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
943 RETURN_EDICT(sv.edicts);
947 // might be able to see it
952 //============================================================================
959 Sends text over to the client's execution buffer
961 stuffcmd (clientent, value)
964 void PF_stuffcmd (void)
970 entnum = G_EDICTNUM(OFS_PARM0);
971 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
973 Con_Print("Can't stuffcmd to a non-client\n");
976 str = G_STRING(OFS_PARM1);
979 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
980 Host_ClientCommands ("%s", str);
988 Sends text to server console
993 void PF_localcmd (void)
995 Cbuf_AddText(G_STRING(OFS_PARM0));
1007 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1017 void PF_cvar_set (void)
1019 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1026 Returns a chain of entities that have origins within a spherical area
1028 findradius (origin, radius)
1031 void PF_findradius (void)
1033 edict_t *ent, *chain;
1034 vec_t radius, radius2;
1035 vec3_t org, eorg, mins, maxs;
1038 edict_t *touchedicts[MAX_EDICTS];
1040 chain = (edict_t *)sv.edicts;
1042 VectorCopy(G_VECTOR(OFS_PARM0), org);
1043 radius = G_FLOAT(OFS_PARM1);
1044 radius2 = radius * radius;
1046 mins[0] = org[0] - radius;
1047 mins[1] = org[1] - radius;
1048 mins[2] = org[2] - radius;
1049 maxs[0] = org[0] + radius;
1050 maxs[1] = org[1] + radius;
1051 maxs[2] = org[2] + radius;
1052 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1053 if (numtouchedicts > MAX_EDICTS)
1055 // this never happens
1056 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1057 numtouchedicts = MAX_EDICTS;
1059 for (i = 0;i < numtouchedicts;i++)
1061 ent = touchedicts[i];
1062 pr_xfunction->builtinsprofile++;
1063 // LordHavoc: compare against bounding box rather than center so it
1064 // doesn't miss large objects, and use DotProduct instead of Length
1065 // for a major speedup
1066 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1067 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1068 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1069 if (DotProduct(eorg, eorg) < radius2)
1071 ent->v->chain = EDICT_TO_PROG(chain);
1076 RETURN_EDICT(chain);
1085 void PF_dprint (void)
1087 char string[STRINGTEMP_LENGTH];
1088 if (developer.integer)
1090 PF_VarString(0, string, sizeof(string));
1099 v = G_FLOAT(OFS_PARM0);
1101 s = PR_GetTempString();
1102 if ((float)((int)v) == v)
1103 sprintf(s, "%i", (int)v);
1105 sprintf(s, "%f", v);
1106 G_INT(OFS_RETURN) = PR_SetString(s);
1112 v = G_FLOAT(OFS_PARM0);
1113 G_FLOAT(OFS_RETURN) = fabs(v);
1119 s = PR_GetTempString();
1120 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1121 G_INT(OFS_RETURN) = PR_SetString(s);
1127 s = PR_GetTempString();
1128 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1129 G_INT(OFS_RETURN) = PR_SetString(s);
1132 void PF_Spawn (void)
1135 pr_xfunction->builtinsprofile += 20;
1140 void PF_Remove (void)
1143 pr_xfunction->builtinsprofile += 20;
1145 ed = G_EDICT(OFS_PARM0);
1146 if (ed == sv.edicts)
1147 PF_WARNING("remove: tried to remove world\n");
1148 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1149 PF_WARNING("remove: tried to remove a client\n");
1150 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1151 if (ed->e->free && developer.integer)
1152 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1157 // entity (entity start, .string field, string match) find = #5;
1165 e = G_EDICTNUM(OFS_PARM0);
1166 f = G_INT(OFS_PARM1);
1167 s = G_STRING(OFS_PARM2);
1170 RETURN_EDICT(sv.edicts);
1174 for (e++ ; e < sv.num_edicts ; e++)
1176 pr_xfunction->builtinsprofile++;
1190 RETURN_EDICT(sv.edicts);
1193 // LordHavoc: added this for searching float, int, and entity reference fields
1194 void PF_FindFloat (void)
1201 e = G_EDICTNUM(OFS_PARM0);
1202 f = G_INT(OFS_PARM1);
1203 s = G_FLOAT(OFS_PARM2);
1205 for (e++ ; e < sv.num_edicts ; e++)
1207 pr_xfunction->builtinsprofile++;
1211 if (E_FLOAT(ed,f) == s)
1218 RETURN_EDICT(sv.edicts);
1221 // chained search for strings in entity fields
1222 // entity(.string field, string match) findchain = #402;
1223 void PF_findchain (void)
1228 edict_t *ent, *chain;
1230 chain = (edict_t *)sv.edicts;
1232 f = G_INT(OFS_PARM0);
1233 s = G_STRING(OFS_PARM1);
1236 RETURN_EDICT(sv.edicts);
1240 ent = NEXT_EDICT(sv.edicts);
1241 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1243 pr_xfunction->builtinsprofile++;
1246 t = E_STRING(ent,f);
1252 ent->v->chain = EDICT_TO_PROG(chain);
1256 RETURN_EDICT(chain);
1259 // LordHavoc: chained search for float, int, and entity reference fields
1260 // entity(.string field, float match) findchainfloat = #403;
1261 void PF_findchainfloat (void)
1266 edict_t *ent, *chain;
1268 chain = (edict_t *)sv.edicts;
1270 f = G_INT(OFS_PARM0);
1271 s = G_FLOAT(OFS_PARM1);
1273 ent = NEXT_EDICT(sv.edicts);
1274 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1276 pr_xfunction->builtinsprofile++;
1279 if (E_FLOAT(ent,f) != s)
1282 ent->v->chain = EDICT_TO_PROG(chain);
1286 RETURN_EDICT(chain);
1289 // LordHavoc: search for flags in float fields
1290 void PF_findflags (void)
1297 e = G_EDICTNUM(OFS_PARM0);
1298 f = G_INT(OFS_PARM1);
1299 s = (int)G_FLOAT(OFS_PARM2);
1301 for (e++ ; e < sv.num_edicts ; e++)
1303 pr_xfunction->builtinsprofile++;
1307 if ((int)E_FLOAT(ed,f) & s)
1314 RETURN_EDICT(sv.edicts);
1317 // LordHavoc: chained search for flags in float fields
1318 void PF_findchainflags (void)
1323 edict_t *ent, *chain;
1325 chain = (edict_t *)sv.edicts;
1327 f = G_INT(OFS_PARM0);
1328 s = (int)G_FLOAT(OFS_PARM1);
1330 ent = NEXT_EDICT(sv.edicts);
1331 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1333 pr_xfunction->builtinsprofile++;
1336 if (!((int)E_FLOAT(ent,f) & s))
1339 ent->v->chain = EDICT_TO_PROG(chain);
1343 RETURN_EDICT(chain);
1346 void PR_CheckEmptyString (char *s)
1349 PF_ERROR("Bad string");
1352 void PF_precache_file (void)
1353 { // precache_file is only used to copy files with qcc, it does nothing
1354 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1357 void PF_precache_sound (void)
1361 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1363 if (sv.state != ss_loading)
1364 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1366 s = G_STRING(OFS_PARM0);
1367 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1368 PR_CheckEmptyString (s);
1370 for (i=0 ; i<limit ; i++)
1372 if (!sv.sound_precache[i])
1374 sv.sound_precache[i] = s;
1377 if (!strcmp(sv.sound_precache[i], s))
1380 PF_ERROR("PF_precache_sound: overflow");
1383 void PF_precache_model (void)
1387 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1389 if (sv.state != ss_loading)
1390 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1392 s = G_STRING(OFS_PARM0);
1393 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1395 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1396 PR_CheckEmptyString (s);
1398 for (i = 0;i < limit;i++)
1400 if (!sv.model_precache[i])
1402 sv.model_precache[i] = s;
1403 sv.models[i] = Mod_ForName (s, true, false, false);
1406 if (!strcmp(sv.model_precache[i], s))
1409 PF_ERROR("PF_precache_model: overflow");
1413 void PF_coredump (void)
1418 void PF_traceon (void)
1423 void PF_traceoff (void)
1428 void PF_eprint (void)
1430 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1437 float(float yaw, float dist) walkmove
1440 void PF_walkmove (void)
1448 // assume failure if it returns early
1449 G_FLOAT(OFS_RETURN) = 0;
1451 ent = PROG_TO_EDICT(pr_global_struct->self);
1452 if (ent == sv.edicts)
1453 PF_WARNING("walkmove: can not modify world entity\n");
1455 PF_WARNING("walkmove: can not modify free entity\n");
1456 yaw = G_FLOAT(OFS_PARM0);
1457 dist = G_FLOAT(OFS_PARM1);
1459 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1462 yaw = yaw*M_PI*2 / 360;
1464 move[0] = cos(yaw)*dist;
1465 move[1] = sin(yaw)*dist;
1468 // save program state, because SV_movestep may call other progs
1469 oldf = pr_xfunction;
1470 oldself = pr_global_struct->self;
1472 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1475 // restore program state
1476 pr_xfunction = oldf;
1477 pr_global_struct->self = oldself;
1487 void PF_droptofloor (void)
1493 // assume failure if it returns early
1494 G_FLOAT(OFS_RETURN) = 0;
1496 ent = PROG_TO_EDICT(pr_global_struct->self);
1497 if (ent == sv.edicts)
1498 PF_WARNING("droptofloor: can not modify world entity\n");
1500 PF_WARNING("droptofloor: can not modify free entity\n");
1502 VectorCopy (ent->v->origin, end);
1505 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1507 if (trace.fraction != 1)
1509 VectorCopy (trace.endpos, ent->v->origin);
1510 SV_LinkEdict (ent, false);
1511 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1512 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1513 G_FLOAT(OFS_RETURN) = 1;
1514 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1515 ent->e->suspendedinairflag = true;
1523 void(float style, string value) lightstyle
1526 void PF_lightstyle (void)
1533 style = G_FLOAT(OFS_PARM0);
1534 val = G_STRING(OFS_PARM1);
1536 // change the string in sv
1537 sv.lightstyles[style] = val;
1539 // send message to all clients on this server
1540 if (sv.state != ss_active)
1543 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1545 if (client->netconnection)
1547 MSG_WriteChar (&client->message, svc_lightstyle);
1548 MSG_WriteChar (&client->message,style);
1549 MSG_WriteString (&client->message, val);
1557 f = G_FLOAT(OFS_PARM0);
1559 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1561 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1563 void PF_floor (void)
1565 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1569 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1578 void PF_checkbottom (void)
1580 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1588 void PF_pointcontents (void)
1590 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1597 entity nextent(entity)
1600 void PF_nextent (void)
1605 i = G_EDICTNUM(OFS_PARM0);
1608 pr_xfunction->builtinsprofile++;
1610 if (i == sv.num_edicts)
1612 RETURN_EDICT(sv.edicts);
1628 Pick a vector for the player to shoot along
1629 vector aim(entity, missilespeed)
1634 edict_t *ent, *check, *bestent;
1635 vec3_t start, dir, end, bestdir;
1638 float dist, bestdist;
1641 // assume failure if it returns early
1642 VectorCopy(pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1643 // if sv_aim is so high it can't possibly accept anything, skip out early
1644 if (sv_aim.value >= 1)
1647 ent = G_EDICT(OFS_PARM0);
1648 if (ent == sv.edicts)
1649 PF_WARNING("aim: can not use world entity\n");
1651 PF_WARNING("aim: can not use free entity\n");
1652 speed = G_FLOAT(OFS_PARM1);
1654 VectorCopy (ent->v->origin, start);
1657 // try sending a trace straight
1658 VectorCopy (pr_global_struct->v_forward, dir);
1659 VectorMA (start, 2048, dir, end);
1660 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1661 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1662 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1664 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1669 // try all possible entities
1670 VectorCopy (dir, bestdir);
1671 bestdist = sv_aim.value;
1674 check = NEXT_EDICT(sv.edicts);
1675 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1677 pr_xfunction->builtinsprofile++;
1678 if (check->v->takedamage != DAMAGE_AIM)
1682 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1683 continue; // don't aim at teammate
1684 for (j=0 ; j<3 ; j++)
1685 end[j] = check->v->origin[j]
1686 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1687 VectorSubtract (end, start, dir);
1688 VectorNormalize (dir);
1689 dist = DotProduct (dir, pr_global_struct->v_forward);
1690 if (dist < bestdist)
1691 continue; // to far to turn
1692 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1693 if (tr.ent == check)
1694 { // can shoot at this one
1702 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1703 dist = DotProduct (dir, pr_global_struct->v_forward);
1704 VectorScale (pr_global_struct->v_forward, dist, end);
1706 VectorNormalize (end);
1707 VectorCopy (end, G_VECTOR(OFS_RETURN));
1711 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1719 This was a major timewaster in progs, so it was converted to C
1722 void PF_changeyaw (void)
1725 float ideal, current, move, speed;
1727 ent = PROG_TO_EDICT(pr_global_struct->self);
1728 if (ent == sv.edicts)
1729 PF_WARNING("changeyaw: can not modify world entity\n");
1731 PF_WARNING("changeyaw: can not modify free entity\n");
1732 current = ANGLEMOD(ent->v->angles[1]);
1733 ideal = ent->v->ideal_yaw;
1734 speed = ent->v->yaw_speed;
1736 if (current == ideal)
1738 move = ideal - current;
1739 if (ideal > current)
1760 ent->v->angles[1] = ANGLEMOD (current + move);
1768 void PF_changepitch (void)
1771 float ideal, current, move, speed;
1774 ent = G_EDICT(OFS_PARM0);
1775 if (ent == sv.edicts)
1776 PF_WARNING("changepitch: can not modify world entity\n");
1778 PF_WARNING("changepitch: can not modify free entity\n");
1779 current = ANGLEMOD( ent->v->angles[0] );
1780 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1781 ideal = val->_float;
1784 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1787 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1788 speed = val->_float;
1791 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1795 if (current == ideal)
1797 move = ideal - current;
1798 if (ideal > current)
1819 ent->v->angles[0] = ANGLEMOD (current + move);
1823 ===============================================================================
1827 ===============================================================================
1830 #define MSG_BROADCAST 0 // unreliable to all
1831 #define MSG_ONE 1 // reliable to one (msg_entity)
1832 #define MSG_ALL 2 // reliable to all
1833 #define MSG_INIT 3 // write to the init string
1835 sizebuf_t *WriteDest (void)
1841 dest = G_FLOAT(OFS_PARM0);
1845 return &sv.datagram;
1848 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1849 entnum = NUM_FOR_EDICT(ent);
1850 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1851 Host_Error("WriteDest: tried to write to non-client\n");
1852 return &svs.clients[entnum-1].message;
1855 return &sv.reliable_datagram;
1861 Host_Error("WriteDest: bad destination");
1868 void PF_WriteByte (void)
1870 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1873 void PF_WriteChar (void)
1875 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1878 void PF_WriteShort (void)
1880 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1883 void PF_WriteLong (void)
1885 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1888 void PF_WriteAngle (void)
1890 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1893 void PF_WriteCoord (void)
1895 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1898 void PF_WriteString (void)
1900 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1904 void PF_WriteEntity (void)
1906 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1909 //=============================================================================
1911 void PF_makestatic (void)
1916 ent = G_EDICT(OFS_PARM0);
1917 if (ent == sv.edicts)
1918 PF_WARNING("makestatic: can not modify world entity\n");
1920 PF_WARNING("makestatic: can not modify free entity\n");
1923 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1928 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1929 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1930 MSG_WriteShort (&sv.signon, ent->v->frame);
1934 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1935 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1936 MSG_WriteByte (&sv.signon, ent->v->frame);
1939 MSG_WriteByte (&sv.signon, ent->v->colormap);
1940 MSG_WriteByte (&sv.signon, ent->v->skin);
1941 for (i=0 ; i<3 ; i++)
1943 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1944 MSG_WriteAngle(&sv.signon, ent->v->angles[i], sv.protocol);
1947 // throw the entity away now
1951 //=============================================================================
1958 void PF_setspawnparms (void)
1964 ent = G_EDICT(OFS_PARM0);
1965 i = NUM_FOR_EDICT(ent);
1966 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1968 Con_Print("tried to setspawnparms on a non-client\n");
1972 // copy spawn parms out of the client_t
1973 client = svs.clients + i-1;
1974 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1975 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1983 void PF_changelevel (void)
1987 // make sure we don't issue two changelevels
1988 if (svs.changelevel_issued)
1990 svs.changelevel_issued = true;
1992 s = G_STRING(OFS_PARM0);
1993 Cbuf_AddText (va("changelevel %s\n",s));
1998 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
2003 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
2008 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2015 Returns a vector of length < 1
2020 void PF_randomvec (void)
2025 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2026 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2027 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2029 while (DotProduct(temp, temp) >= 1);
2030 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2037 Returns a color vector indicating the lighting at the requested point.
2039 (Internal Operation note: actually measures the light beneath the point, just like
2040 the model lighting on the client)
2045 void PF_GetLight (void)
2047 vec3_t ambientcolor, diffusecolor, diffusenormal;
2049 p = G_VECTOR(OFS_PARM0);
2050 VectorClear(ambientcolor);
2051 VectorClear(diffusecolor);
2052 VectorClear(diffusenormal);
2053 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2054 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2055 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2058 void PF_registercvar (void)
2061 name = G_STRING(OFS_PARM0);
2062 value = G_STRING(OFS_PARM1);
2063 G_FLOAT(OFS_RETURN) = 0;
2065 // first check to see if it has already been defined
2066 if (Cvar_FindVar (name))
2069 // check for overlap with a command
2070 if (Cmd_Exists (name))
2072 Con_Printf("PF_registercvar: %s is a command\n", name);
2076 Cvar_Get(name, value, 0);
2078 G_FLOAT(OFS_RETURN) = 1; // success
2085 returns the minimum of two supplied floats
2092 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2094 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2095 else if (pr_argc >= 3)
2098 float f = G_FLOAT(OFS_PARM0);
2099 for (i = 1;i < pr_argc;i++)
2100 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2101 f = G_FLOAT((OFS_PARM0+i*3));
2102 G_FLOAT(OFS_RETURN) = f;
2106 G_FLOAT(OFS_RETURN) = 0;
2107 PF_WARNING("min: must supply at least 2 floats\n");
2115 returns the maximum of two supplied floats
2122 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2124 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2125 else if (pr_argc >= 3)
2128 float f = G_FLOAT(OFS_PARM0);
2129 for (i = 1;i < pr_argc;i++)
2130 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2131 f = G_FLOAT((OFS_PARM0+i*3));
2132 G_FLOAT(OFS_RETURN) = f;
2136 G_FLOAT(OFS_RETURN) = 0;
2137 PF_WARNING("max: must supply at least 2 floats\n");
2145 returns number bounded by supplied range
2147 min(min, value, max)
2150 void PF_bound (void)
2152 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2159 returns a raised to power b
2166 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2173 copies data from one entity to another
2175 copyentity(src, dst)
2178 void PF_copyentity (void)
2181 in = G_EDICT(OFS_PARM0);
2182 if (in == sv.edicts)
2183 PF_WARNING("copyentity: can not read world entity\n");
2185 PF_WARNING("copyentity: can not read free entity\n");
2186 out = G_EDICT(OFS_PARM1);
2187 if (out == sv.edicts)
2188 PF_WARNING("copyentity: can not modify world entity\n");
2190 PF_WARNING("copyentity: can not modify free entity\n");
2191 memcpy(out->v, in->v, progs->entityfields * 4);
2198 sets the color of a client and broadcasts the update to all connected clients
2200 setcolor(clientent, value)
2203 void PF_setcolor (void)
2209 entnum = G_EDICTNUM(OFS_PARM0);
2210 i = G_FLOAT(OFS_PARM1);
2212 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2214 Con_Print("tried to setcolor a non-client\n");
2218 client = svs.clients + entnum-1;
2219 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2222 client->old_colors = i;
2223 client->edict->v->team = (i & 15) + 1;
2225 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2226 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2227 MSG_WriteByte (&sv.reliable_datagram, i);
2234 effect(origin, modelname, startframe, framecount, framerate)
2237 void PF_effect (void)
2241 s = G_STRING(OFS_PARM1);
2243 PF_WARNING("effect: no model specified\n");
2245 i = SV_ModelIndex(s);
2247 PF_WARNING("effect: model not precached\n");
2248 SV_StartEffect(G_VECTOR(OFS_PARM0), i, 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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2259 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2295 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2318 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2319 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2320 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2339 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2342 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2343 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2344 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2346 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2347 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2348 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2363 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2364 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2366 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2367 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2368 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2370 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2372 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2387 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2388 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2403 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2404 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2407 void PF_te_spikequad (void)
2409 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2410 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2412 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2413 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2414 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2417 void PF_te_superspikequad (void)
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2422 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2423 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2424 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2427 void PF_te_explosionquad (void)
2429 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2430 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2432 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2433 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2434 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2437 void PF_te_smallflash (void)
2439 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2440 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2442 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2443 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2444 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2455 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2456 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2473 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2474 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2477 void PF_te_spike (void)
2479 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2480 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2482 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2483 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2484 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2487 void PF_te_superspike (void)
2489 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2490 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2492 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2493 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2494 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2497 void PF_te_explosion (void)
2499 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2500 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2502 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2503 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2504 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2507 void PF_te_tarexplosion (void)
2509 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2510 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2512 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2513 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2514 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2517 void PF_te_wizspike (void)
2519 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2520 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2522 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2523 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2524 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2527 void PF_te_knightspike (void)
2529 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2530 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2532 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2533 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2534 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2537 void PF_te_lavasplash (void)
2539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2540 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2542 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2543 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2544 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2547 void PF_te_teleport (void)
2549 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2550 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2552 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2553 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2554 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2557 void PF_te_explosion2 (void)
2559 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2560 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2562 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2563 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2564 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2578 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2579 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2581 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2582 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2583 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2594 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2595 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2597 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2598 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2599 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2610 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2611 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2613 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2614 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2615 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
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_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2626 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2627 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2629 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2630 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2631 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2634 void PF_te_plasmaburn (void)
2636 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2637 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2638 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2639 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2640 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
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);
3295 tmp = PR_GetTempString();
3296 strcpy(tmp, var->string);
3300 G_INT(OFS_RETURN) = PR_SetString(tmp);
3305 builtin_t pr_builtin[] =
3308 PF_makevectors, // #1 void(entity e) makevectors
3309 PF_setorigin, // #2 void(entity e, vector o) setorigin
3310 PF_setmodel, // #3 void(entity e, string m) setmodel
3311 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3312 NULL, // #5 void(entity e, vector min, vector max) setabssize
3313 PF_break, // #6 void() break
3314 PF_random, // #7 float() random
3315 PF_sound, // #8 void(entity e, float chan, string samp) sound
3316 PF_normalize, // #9 vector(vector v) normalize
3317 PF_error, // #10 void(string e) error
3318 PF_objerror, // #11 void(string e) objerror
3319 PF_vlen, // #12 float(vector v) vlen
3320 PF_vectoyaw, // #13 float(vector v) vectoyaw
3321 PF_Spawn, // #14 entity() spawn
3322 PF_Remove, // #15 void(entity e) remove
3323 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3324 PF_checkclient, // #17 entity() clientlist
3325 PF_Find, // #18 entity(entity start, .string fld, string match) find
3326 PF_precache_sound, // #19 void(string s) precache_sound
3327 PF_precache_model, // #20 void(string s) precache_model
3328 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3329 PF_findradius, // #22 entity(vector org, float rad) findradius
3330 PF_bprint, // #23 void(string s) bprint
3331 PF_sprint, // #24 void(entity client, string s) sprint
3332 PF_dprint, // #25 void(string s) dprint
3333 PF_ftos, // #26 void(string s) ftos
3334 PF_vtos, // #27 void(string s) vtos
3335 PF_coredump, // #28 void() coredump
3336 PF_traceon, // #29 void() traceon
3337 PF_traceoff, // #30 void() traceoff
3338 PF_eprint, // #31 void(entity e) eprint
3339 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3341 PF_droptofloor, // #34 float() droptofloor
3342 PF_lightstyle, // #35 void(float style, string value) lightstyle
3343 PF_rint, // #36 float(float v) rint
3344 PF_floor, // #37 float(float v) floor
3345 PF_ceil, // #38 float(float v) ceil
3347 PF_checkbottom, // #40 float(entity e) checkbottom
3348 PF_pointcontents , // #41 float(vector v) pointcontents
3350 PF_fabs, // #43 float(float f) fabs
3351 PF_aim, // #44 vector(entity e, float speed) aim
3352 PF_cvar, // #45 float(string s) cvar
3353 PF_localcmd, // #46 void(string s) localcmd
3354 PF_nextent, // #47 entity(entity e) nextent
3355 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3356 PF_changeyaw, // #49 void() ChangeYaw
3358 PF_vectoangles, // #51 vector(vector v) vectoangles
3359 PF_WriteByte, // #52 void(float to, float f) WriteByte
3360 PF_WriteChar, // #53 void(float to, float f) WriteChar
3361 PF_WriteShort, // #54 void(float to, float f) WriteShort
3362 PF_WriteLong, // #55 void(float to, float f) WriteLong
3363 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3364 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3365 PF_WriteString, // #58 void(float to, string s) WriteString
3366 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3367 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3368 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3369 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3370 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3371 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3372 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3374 SV_MoveToGoal, // #67 void(float step) movetogoal
3375 PF_precache_file, // #68 string(string s) precache_file
3376 PF_makestatic, // #69 void(entity e) makestatic
3377 PF_changelevel, // #70 void(string s) changelevel
3379 PF_cvar_set, // #72 void(string var, string val) cvar_set
3380 PF_centerprint, // #73 void(entity client, strings) centerprint
3381 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3382 PF_precache_model, // #75 string(string s) precache_model2
3383 PF_precache_sound, // #76 string(string s) precache_sound2
3384 PF_precache_file, // #77 string(string s) precache_file2
3385 PF_setspawnparms, // #78 void(entity e) setspawnparms
3388 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3397 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3398 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3399 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3400 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3401 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3402 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3403 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3404 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3405 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3406 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3417 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3418 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3419 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3420 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3421 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3422 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3423 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3424 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3425 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3426 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3427 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3428 a a a a a a a a // #120-199
3429 a a a a a a a a a a // #200-299
3430 a a a a a a a a a a // #300-399
3431 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3432 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3433 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3434 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3435 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3436 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3437 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3438 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3439 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3440 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3441 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3442 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3443 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3444 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3445 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3446 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3447 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3448 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3449 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3450 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3451 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3452 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3453 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3454 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3455 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3456 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3457 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3458 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3459 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3460 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3461 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3462 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3463 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3464 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3465 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3466 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3467 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3468 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3469 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3470 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3471 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3472 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3473 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3474 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3475 PF_search_begin, // #444
3476 PF_search_end, // #445
3477 PF_search_getsize, // #446
3478 PF_search_getfilename, // #447
3479 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3480 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3481 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3491 a a a a // #460-499 (LordHavoc)
3494 builtin_t *pr_builtins = pr_builtin;
3495 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3497 void PR_Cmd_Init(void)
3499 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3504 void PR_Cmd_Reset(void)
3506 Mem_EmptyPool(pr_strings_mempool);
3508 PR_Files_CloseAll();