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;
1040 chain = (edict_t *)sv.edicts;
1042 org = G_VECTOR(OFS_PARM0);
1043 radius = G_FLOAT(OFS_PARM1);
1044 radius2 = radius * radius;
1046 ent = NEXT_EDICT(sv.edicts);
1047 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1049 pr_xfunction->builtinsprofile++;
1052 if (ent->v->solid == SOLID_NOT)
1055 // LordHavoc: compare against bounding box rather than center,
1056 // and use DotProduct instead of Length, major speedup
1057 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1058 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1059 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1060 if (DotProduct(eorg, eorg) > radius2)
1063 ent->v->chain = EDICT_TO_PROG(chain);
1067 RETURN_EDICT(chain);
1076 void PF_dprint (void)
1078 char string[STRINGTEMP_LENGTH];
1079 if (developer.integer)
1081 PF_VarString(0, string, sizeof(string));
1090 v = G_FLOAT(OFS_PARM0);
1092 s = PR_GetTempString();
1093 if ((float)((int)v) == v)
1094 sprintf(s, "%i", (int)v);
1096 sprintf(s, "%f", v);
1097 G_INT(OFS_RETURN) = PR_SetString(s);
1103 v = G_FLOAT(OFS_PARM0);
1104 G_FLOAT(OFS_RETURN) = fabs(v);
1110 s = PR_GetTempString();
1111 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1112 G_INT(OFS_RETURN) = PR_SetString(s);
1118 s = PR_GetTempString();
1119 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1120 G_INT(OFS_RETURN) = PR_SetString(s);
1123 void PF_Spawn (void)
1126 pr_xfunction->builtinsprofile += 20;
1131 void PF_Remove (void)
1134 pr_xfunction->builtinsprofile += 20;
1136 ed = G_EDICT(OFS_PARM0);
1137 if (ed == sv.edicts)
1138 PF_WARNING("remove: tried to remove world\n");
1139 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1140 PF_WARNING("remove: tried to remove a client\n");
1141 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1142 if (ed->e->free && developer.integer)
1143 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1148 // entity (entity start, .string field, string match) find = #5;
1156 e = G_EDICTNUM(OFS_PARM0);
1157 f = G_INT(OFS_PARM1);
1158 s = G_STRING(OFS_PARM2);
1161 RETURN_EDICT(sv.edicts);
1165 for (e++ ; e < sv.num_edicts ; e++)
1167 pr_xfunction->builtinsprofile++;
1181 RETURN_EDICT(sv.edicts);
1184 // LordHavoc: added this for searching float, int, and entity reference fields
1185 void PF_FindFloat (void)
1192 e = G_EDICTNUM(OFS_PARM0);
1193 f = G_INT(OFS_PARM1);
1194 s = G_FLOAT(OFS_PARM2);
1196 for (e++ ; e < sv.num_edicts ; e++)
1198 pr_xfunction->builtinsprofile++;
1202 if (E_FLOAT(ed,f) == s)
1209 RETURN_EDICT(sv.edicts);
1212 // chained search for strings in entity fields
1213 // entity(.string field, string match) findchain = #402;
1214 void PF_findchain (void)
1219 edict_t *ent, *chain;
1221 chain = (edict_t *)sv.edicts;
1223 f = G_INT(OFS_PARM0);
1224 s = G_STRING(OFS_PARM1);
1227 RETURN_EDICT(sv.edicts);
1231 ent = NEXT_EDICT(sv.edicts);
1232 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1234 pr_xfunction->builtinsprofile++;
1237 t = E_STRING(ent,f);
1243 ent->v->chain = EDICT_TO_PROG(chain);
1247 RETURN_EDICT(chain);
1250 // LordHavoc: chained search for float, int, and entity reference fields
1251 // entity(.string field, float match) findchainfloat = #403;
1252 void PF_findchainfloat (void)
1257 edict_t *ent, *chain;
1259 chain = (edict_t *)sv.edicts;
1261 f = G_INT(OFS_PARM0);
1262 s = G_FLOAT(OFS_PARM1);
1264 ent = NEXT_EDICT(sv.edicts);
1265 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1267 pr_xfunction->builtinsprofile++;
1270 if (E_FLOAT(ent,f) != s)
1273 ent->v->chain = EDICT_TO_PROG(chain);
1277 RETURN_EDICT(chain);
1280 // LordHavoc: search for flags in float fields
1281 void PF_findflags (void)
1288 e = G_EDICTNUM(OFS_PARM0);
1289 f = G_INT(OFS_PARM1);
1290 s = (int)G_FLOAT(OFS_PARM2);
1292 for (e++ ; e < sv.num_edicts ; e++)
1294 pr_xfunction->builtinsprofile++;
1298 if ((int)E_FLOAT(ed,f) & s)
1305 RETURN_EDICT(sv.edicts);
1308 // LordHavoc: chained search for flags in float fields
1309 void PF_findchainflags (void)
1314 edict_t *ent, *chain;
1316 chain = (edict_t *)sv.edicts;
1318 f = G_INT(OFS_PARM0);
1319 s = (int)G_FLOAT(OFS_PARM1);
1321 ent = NEXT_EDICT(sv.edicts);
1322 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1324 pr_xfunction->builtinsprofile++;
1327 if (!((int)E_FLOAT(ent,f) & s))
1330 ent->v->chain = EDICT_TO_PROG(chain);
1334 RETURN_EDICT(chain);
1337 void PR_CheckEmptyString (char *s)
1340 PF_ERROR("Bad string");
1343 void PF_precache_file (void)
1344 { // precache_file is only used to copy files with qcc, it does nothing
1345 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1348 void PF_precache_sound (void)
1352 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1354 if (sv.state != ss_loading)
1355 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1357 s = G_STRING(OFS_PARM0);
1358 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1359 PR_CheckEmptyString (s);
1361 for (i=0 ; i<limit ; i++)
1363 if (!sv.sound_precache[i])
1365 sv.sound_precache[i] = s;
1368 if (!strcmp(sv.sound_precache[i], s))
1371 PF_ERROR("PF_precache_sound: overflow");
1374 void PF_precache_model (void)
1378 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1380 if (sv.state != ss_loading)
1381 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1383 s = G_STRING(OFS_PARM0);
1384 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1386 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1387 PR_CheckEmptyString (s);
1389 for (i = 0;i < limit;i++)
1391 if (!sv.model_precache[i])
1393 sv.model_precache[i] = s;
1394 sv.models[i] = Mod_ForName (s, true, false, false);
1397 if (!strcmp(sv.model_precache[i], s))
1400 PF_ERROR("PF_precache_model: overflow");
1404 void PF_coredump (void)
1409 void PF_traceon (void)
1414 void PF_traceoff (void)
1419 void PF_eprint (void)
1421 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1428 float(float yaw, float dist) walkmove
1431 void PF_walkmove (void)
1439 // assume failure if it returns early
1440 G_FLOAT(OFS_RETURN) = 0;
1442 ent = PROG_TO_EDICT(pr_global_struct->self);
1443 if (ent == sv.edicts)
1444 PF_WARNING("walkmove: can not modify world entity\n");
1446 PF_WARNING("walkmove: can not modify free entity\n");
1447 yaw = G_FLOAT(OFS_PARM0);
1448 dist = G_FLOAT(OFS_PARM1);
1450 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1453 yaw = yaw*M_PI*2 / 360;
1455 move[0] = cos(yaw)*dist;
1456 move[1] = sin(yaw)*dist;
1459 // save program state, because SV_movestep may call other progs
1460 oldf = pr_xfunction;
1461 oldself = pr_global_struct->self;
1463 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1466 // restore program state
1467 pr_xfunction = oldf;
1468 pr_global_struct->self = oldself;
1478 void PF_droptofloor (void)
1484 // assume failure if it returns early
1485 G_FLOAT(OFS_RETURN) = 0;
1487 ent = PROG_TO_EDICT(pr_global_struct->self);
1488 if (ent == sv.edicts)
1489 PF_WARNING("droptofloor: can not modify world entity\n");
1491 PF_WARNING("droptofloor: can not modify free entity\n");
1493 VectorCopy (ent->v->origin, end);
1496 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1498 if (trace.fraction != 1)
1500 VectorCopy (trace.endpos, ent->v->origin);
1501 SV_LinkEdict (ent, false);
1502 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1503 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1504 G_FLOAT(OFS_RETURN) = 1;
1505 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1506 ent->e->suspendedinairflag = true;
1514 void(float style, string value) lightstyle
1517 void PF_lightstyle (void)
1524 style = G_FLOAT(OFS_PARM0);
1525 val = G_STRING(OFS_PARM1);
1527 // change the string in sv
1528 sv.lightstyles[style] = val;
1530 // send message to all clients on this server
1531 if (sv.state != ss_active)
1534 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1536 if (client->netconnection)
1538 MSG_WriteChar (&client->message, svc_lightstyle);
1539 MSG_WriteChar (&client->message,style);
1540 MSG_WriteString (&client->message, val);
1548 f = G_FLOAT(OFS_PARM0);
1550 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1552 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1554 void PF_floor (void)
1556 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1560 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1569 void PF_checkbottom (void)
1571 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1579 void PF_pointcontents (void)
1581 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1588 entity nextent(entity)
1591 void PF_nextent (void)
1596 i = G_EDICTNUM(OFS_PARM0);
1599 pr_xfunction->builtinsprofile++;
1601 if (i == sv.num_edicts)
1603 RETURN_EDICT(sv.edicts);
1619 Pick a vector for the player to shoot along
1620 vector aim(entity, missilespeed)
1625 edict_t *ent, *check, *bestent;
1626 vec3_t start, dir, end, bestdir;
1629 float dist, bestdist;
1632 // assume failure if it returns early
1633 VectorClear(G_VECTOR(OFS_RETURN));
1635 ent = G_EDICT(OFS_PARM0);
1636 if (ent == sv.edicts)
1637 PF_WARNING("aim: can not use world entity\n");
1639 PF_WARNING("aim: can not use free entity\n");
1640 speed = G_FLOAT(OFS_PARM1);
1642 VectorCopy (ent->v->origin, start);
1645 // try sending a trace straight
1646 VectorCopy (pr_global_struct->v_forward, dir);
1647 VectorMA (start, 2048, dir, end);
1648 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1649 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1650 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1652 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1657 // try all possible entities
1658 VectorCopy (dir, bestdir);
1659 bestdist = sv_aim.value;
1662 check = NEXT_EDICT(sv.edicts);
1663 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1665 pr_xfunction->builtinsprofile++;
1666 if (check->v->takedamage != DAMAGE_AIM)
1670 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1671 continue; // don't aim at teammate
1672 for (j=0 ; j<3 ; j++)
1673 end[j] = check->v->origin[j]
1674 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1675 VectorSubtract (end, start, dir);
1676 VectorNormalize (dir);
1677 dist = DotProduct (dir, pr_global_struct->v_forward);
1678 if (dist < bestdist)
1679 continue; // to far to turn
1680 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1681 if (tr.ent == check)
1682 { // can shoot at this one
1690 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1691 dist = DotProduct (dir, pr_global_struct->v_forward);
1692 VectorScale (pr_global_struct->v_forward, dist, end);
1694 VectorNormalize (end);
1695 VectorCopy (end, G_VECTOR(OFS_RETURN));
1699 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1707 This was a major timewaster in progs, so it was converted to C
1710 void PF_changeyaw (void)
1713 float ideal, current, move, speed;
1715 ent = PROG_TO_EDICT(pr_global_struct->self);
1716 if (ent == sv.edicts)
1717 PF_WARNING("changeyaw: can not modify world entity\n");
1719 PF_WARNING("changeyaw: can not modify free entity\n");
1720 current = ANGLEMOD(ent->v->angles[1]);
1721 ideal = ent->v->ideal_yaw;
1722 speed = ent->v->yaw_speed;
1724 if (current == ideal)
1726 move = ideal - current;
1727 if (ideal > current)
1748 ent->v->angles[1] = ANGLEMOD (current + move);
1756 void PF_changepitch (void)
1759 float ideal, current, move, speed;
1762 ent = G_EDICT(OFS_PARM0);
1763 if (ent == sv.edicts)
1764 PF_WARNING("changepitch: can not modify world entity\n");
1766 PF_WARNING("changepitch: can not modify free entity\n");
1767 current = ANGLEMOD( ent->v->angles[0] );
1768 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1769 ideal = val->_float;
1772 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1775 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1776 speed = val->_float;
1779 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1783 if (current == ideal)
1785 move = ideal - current;
1786 if (ideal > current)
1807 ent->v->angles[0] = ANGLEMOD (current + move);
1811 ===============================================================================
1815 ===============================================================================
1818 #define MSG_BROADCAST 0 // unreliable to all
1819 #define MSG_ONE 1 // reliable to one (msg_entity)
1820 #define MSG_ALL 2 // reliable to all
1821 #define MSG_INIT 3 // write to the init string
1823 sizebuf_t *WriteDest (void)
1829 dest = G_FLOAT(OFS_PARM0);
1833 return &sv.datagram;
1836 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1837 entnum = NUM_FOR_EDICT(ent);
1838 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1839 Host_Error("WriteDest: tried to write to non-client\n");
1840 return &svs.clients[entnum-1].message;
1843 return &sv.reliable_datagram;
1849 Host_Error("WriteDest: bad destination");
1856 void PF_WriteByte (void)
1858 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1861 void PF_WriteChar (void)
1863 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1866 void PF_WriteShort (void)
1868 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1871 void PF_WriteLong (void)
1873 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1876 void PF_WriteAngle (void)
1878 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1881 void PF_WriteCoord (void)
1883 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1886 void PF_WriteString (void)
1888 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1892 void PF_WriteEntity (void)
1894 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1897 //=============================================================================
1899 void PF_makestatic (void)
1904 ent = G_EDICT(OFS_PARM0);
1905 if (ent == sv.edicts)
1906 PF_WARNING("makestatic: can not modify world entity\n");
1908 PF_WARNING("makestatic: can not modify free entity\n");
1911 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1916 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1917 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1918 MSG_WriteShort (&sv.signon, ent->v->frame);
1922 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1923 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1924 MSG_WriteByte (&sv.signon, ent->v->frame);
1927 MSG_WriteByte (&sv.signon, ent->v->colormap);
1928 MSG_WriteByte (&sv.signon, ent->v->skin);
1929 for (i=0 ; i<3 ; i++)
1931 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1932 MSG_WriteAngle(&sv.signon, ent->v->angles[i], sv.protocol);
1935 // throw the entity away now
1939 //=============================================================================
1946 void PF_setspawnparms (void)
1952 ent = G_EDICT(OFS_PARM0);
1953 i = NUM_FOR_EDICT(ent);
1954 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1956 Con_Print("tried to setspawnparms on a non-client\n");
1960 // copy spawn parms out of the client_t
1961 client = svs.clients + i-1;
1962 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1963 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1971 void PF_changelevel (void)
1975 // make sure we don't issue two changelevels
1976 if (svs.changelevel_issued)
1978 svs.changelevel_issued = true;
1980 s = G_STRING(OFS_PARM0);
1981 Cbuf_AddText (va("changelevel %s\n",s));
1986 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1991 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1996 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2003 Returns a vector of length < 1
2008 void PF_randomvec (void)
2013 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2014 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2015 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2017 while (DotProduct(temp, temp) >= 1);
2018 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2025 Returns a color vector indicating the lighting at the requested point.
2027 (Internal Operation note: actually measures the light beneath the point, just like
2028 the model lighting on the client)
2033 void PF_GetLight (void)
2035 vec3_t ambientcolor, diffusecolor, diffusenormal;
2037 p = G_VECTOR(OFS_PARM0);
2038 VectorClear(ambientcolor);
2039 VectorClear(diffusecolor);
2040 VectorClear(diffusenormal);
2041 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2042 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2043 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2046 void PF_registercvar (void)
2049 name = G_STRING(OFS_PARM0);
2050 value = G_STRING(OFS_PARM1);
2051 G_FLOAT(OFS_RETURN) = 0;
2053 // first check to see if it has already been defined
2054 if (Cvar_FindVar (name))
2057 // check for overlap with a command
2058 if (Cmd_Exists (name))
2060 Con_Printf("PF_registercvar: %s is a command\n", name);
2064 Cvar_Get(name, value, 0);
2066 G_FLOAT(OFS_RETURN) = 1; // success
2073 returns the minimum of two supplied floats
2080 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2082 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2083 else if (pr_argc >= 3)
2086 float f = G_FLOAT(OFS_PARM0);
2087 for (i = 1;i < pr_argc;i++)
2088 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2089 f = G_FLOAT((OFS_PARM0+i*3));
2090 G_FLOAT(OFS_RETURN) = f;
2094 G_FLOAT(OFS_RETURN) = 0;
2095 PF_WARNING("min: must supply at least 2 floats\n");
2103 returns the maximum of two supplied floats
2110 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2112 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2113 else if (pr_argc >= 3)
2116 float f = G_FLOAT(OFS_PARM0);
2117 for (i = 1;i < pr_argc;i++)
2118 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2119 f = G_FLOAT((OFS_PARM0+i*3));
2120 G_FLOAT(OFS_RETURN) = f;
2124 G_FLOAT(OFS_RETURN) = 0;
2125 PF_WARNING("max: must supply at least 2 floats\n");
2133 returns number bounded by supplied range
2135 min(min, value, max)
2138 void PF_bound (void)
2140 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2147 returns a raised to power b
2154 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2161 copies data from one entity to another
2163 copyentity(src, dst)
2166 void PF_copyentity (void)
2169 in = G_EDICT(OFS_PARM0);
2170 if (in == sv.edicts)
2171 PF_WARNING("copyentity: can not read world entity\n");
2173 PF_WARNING("copyentity: can not read free entity\n");
2174 out = G_EDICT(OFS_PARM1);
2175 if (out == sv.edicts)
2176 PF_WARNING("copyentity: can not modify world entity\n");
2178 PF_WARNING("copyentity: can not modify free entity\n");
2179 memcpy(out->v, in->v, progs->entityfields * 4);
2186 sets the color of a client and broadcasts the update to all connected clients
2188 setcolor(clientent, value)
2191 void PF_setcolor (void)
2197 entnum = G_EDICTNUM(OFS_PARM0);
2198 i = G_FLOAT(OFS_PARM1);
2200 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2202 Con_Print("tried to setcolor a non-client\n");
2206 client = svs.clients + entnum-1;
2207 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2210 client->old_colors = i;
2211 client->edict->v->team = (i & 15) + 1;
2213 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2214 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2215 MSG_WriteByte (&sv.reliable_datagram, i);
2222 effect(origin, modelname, startframe, framecount, framerate)
2225 void PF_effect (void)
2229 s = G_STRING(OFS_PARM1);
2231 PF_WARNING("effect: no model specified\n");
2233 i = SV_ModelIndex(s);
2235 PF_WARNING("effect: model not precached\n");
2236 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2239 void PF_te_blood (void)
2241 if (G_FLOAT(OFS_PARM2) < 1)
2243 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2244 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2246 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2250 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2251 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2252 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2254 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2257 void PF_te_bloodshower (void)
2259 if (G_FLOAT(OFS_PARM3) < 1)
2261 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2262 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2264 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2265 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2266 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2268 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2269 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2270 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2272 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2274 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2277 void PF_te_explosionrgb (void)
2279 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2280 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2282 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2286 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2287 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2288 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2291 void PF_te_particlecube (void)
2293 if (G_FLOAT(OFS_PARM3) < 1)
2295 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2296 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2298 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2299 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2300 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2302 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2303 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2306 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2310 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2312 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2313 // gravity true/false
2314 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2316 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2319 void PF_te_particlerain (void)
2321 if (G_FLOAT(OFS_PARM3) < 1)
2323 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2324 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2326 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2327 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2328 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2330 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2334 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2338 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2340 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2343 void PF_te_particlesnow (void)
2345 if (G_FLOAT(OFS_PARM3) < 1)
2347 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2348 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2350 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2351 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2352 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2354 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2358 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2359 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2360 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2362 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2364 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2367 void PF_te_spark (void)
2369 if (G_FLOAT(OFS_PARM2) < 1)
2371 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2372 MSG_WriteByte(&sv.datagram, TE_SPARK);
2374 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2375 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2376 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2378 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2379 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2380 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2382 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2385 void PF_te_gunshotquad (void)
2387 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2388 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2390 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2391 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2392 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2395 void PF_te_spikequad (void)
2397 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2398 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2400 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2401 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2402 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2405 void PF_te_superspikequad (void)
2407 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2408 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2410 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2412 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2415 void PF_te_explosionquad (void)
2417 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2418 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2420 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2421 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2422 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2425 void PF_te_smallflash (void)
2427 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2428 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2430 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2431 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2432 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2435 void PF_te_customflash (void)
2437 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2439 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2440 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
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);
2446 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2448 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2450 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2451 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2452 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2455 void PF_te_gunshot (void)
2457 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2458 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2460 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2461 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2462 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2465 void PF_te_spike (void)
2467 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2468 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2470 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2471 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2472 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2475 void PF_te_superspike (void)
2477 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2478 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2480 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2481 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2482 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2485 void PF_te_explosion (void)
2487 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2488 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2490 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2491 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2492 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2495 void PF_te_tarexplosion (void)
2497 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2498 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2500 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2501 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2502 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2505 void PF_te_wizspike (void)
2507 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2508 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2510 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2511 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2512 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2515 void PF_te_knightspike (void)
2517 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2518 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2520 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2521 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2522 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2525 void PF_te_lavasplash (void)
2527 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2528 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2530 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2531 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2532 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2535 void PF_te_teleport (void)
2537 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2538 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2540 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2541 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2542 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2545 void PF_te_explosion2 (void)
2547 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2548 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2550 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2551 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2552 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2554 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2555 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2558 void PF_te_lightning1 (void)
2560 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2561 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2563 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2565 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2566 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2567 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2569 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2570 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2571 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2574 void PF_te_lightning2 (void)
2576 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2577 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2579 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2581 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2582 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2583 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2585 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2586 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2587 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2590 void PF_te_lightning3 (void)
2592 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2593 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2595 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2597 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2598 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2599 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2601 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2602 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2603 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2606 void PF_te_beam (void)
2608 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2609 MSG_WriteByte(&sv.datagram, TE_BEAM);
2611 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2613 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2614 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2615 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2617 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2618 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2619 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2622 void PF_te_plasmaburn (void)
2624 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2625 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2626 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2627 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2628 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2631 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2634 vec3_t v1, clipplanenormal, normal;
2635 vec_t clipplanedist, clipdist;
2637 if (surf->flags & SURF_PLANEBACK)
2638 VectorNegate(surf->plane->normal, normal);
2640 VectorCopy(surf->plane->normal, normal);
2641 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2643 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2644 VectorNormalizeFast(v1);
2645 CrossProduct(v1, normal, clipplanenormal);
2646 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2647 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2650 clipdist = -clipdist;
2651 VectorMA(out, clipdist, clipplanenormal, out);
2656 static msurface_t *getsurface(edict_t *ed, int surfnum)
2660 if (!ed || ed->e->free)
2662 modelindex = ed->v->modelindex;
2663 if (modelindex < 1 || modelindex >= MAX_MODELS)
2665 model = sv.models[modelindex];
2666 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2668 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2672 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2673 void PF_getsurfacenumpoints(void)
2676 // return 0 if no such surface
2677 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2679 G_FLOAT(OFS_RETURN) = 0;
2683 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2685 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2686 void PF_getsurfacepoint(void)
2691 VectorClear(G_VECTOR(OFS_RETURN));
2692 ed = G_EDICT(OFS_PARM0);
2693 if (!ed || ed->e->free)
2695 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2697 pointnum = G_FLOAT(OFS_PARM2);
2698 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2700 // FIXME: implement rotation/scaling
2701 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2703 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2704 void PF_getsurfacenormal(void)
2707 VectorClear(G_VECTOR(OFS_RETURN));
2708 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2710 // FIXME: implement rotation/scaling
2711 if (surf->flags & SURF_PLANEBACK)
2712 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2714 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2716 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2717 void PF_getsurfacetexture(void)
2720 G_INT(OFS_RETURN) = 0;
2721 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2723 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2725 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2726 void PF_getsurfacenearpoint(void)
2728 int surfnum, best, modelindex;
2730 vec_t dist, bestdist;
2735 G_FLOAT(OFS_RETURN) = -1;
2736 ed = G_EDICT(OFS_PARM0);
2737 point = G_VECTOR(OFS_PARM1);
2739 if (!ed || ed->e->free)
2741 modelindex = ed->v->modelindex;
2742 if (modelindex < 1 || modelindex >= MAX_MODELS)
2744 model = sv.models[modelindex];
2745 if (!model->brushq1.numsurfaces)
2748 // FIXME: implement rotation/scaling
2749 VectorSubtract(point, ed->v->origin, p);
2751 bestdist = 1000000000;
2752 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2754 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2755 dist = PlaneDiff(p, surf->plane);
2757 if (dist < bestdist)
2759 clippointtosurface(surf, p, clipped);
2760 VectorSubtract(clipped, p, clipped);
2761 dist += DotProduct(clipped, clipped);
2762 if (dist < bestdist)
2769 G_FLOAT(OFS_RETURN) = best;
2771 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2772 void PF_getsurfaceclippedpoint(void)
2777 VectorClear(G_VECTOR(OFS_RETURN));
2778 ed = G_EDICT(OFS_PARM0);
2779 if (!ed || ed->e->free)
2781 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2783 // FIXME: implement rotation/scaling
2784 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2785 clippointtosurface(surf, p, out);
2786 // FIXME: implement rotation/scaling
2787 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2790 #define MAX_PRFILES 256
2792 qfile_t *pr_files[MAX_PRFILES];
2794 void PR_Files_Init(void)
2796 memset(pr_files, 0, sizeof(pr_files));
2799 void PR_Files_CloseAll(void)
2802 for (i = 0;i < MAX_PRFILES;i++)
2805 FS_Close(pr_files[i]);
2810 //float(string s) stof = #81; // get numerical value from a string
2813 char string[STRINGTEMP_LENGTH];
2814 PF_VarString(0, string, sizeof(string));
2815 G_FLOAT(OFS_RETURN) = atof(string);
2818 //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
2821 int filenum, mode, i;
2822 char *modestring, *filename;
2823 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2824 if (pr_files[filenum] == NULL)
2826 if (filenum >= MAX_PRFILES)
2828 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2829 G_FLOAT(OFS_RETURN) = -2;
2832 mode = G_FLOAT(OFS_PARM1);
2835 case 0: // FILE_READ
2838 case 1: // FILE_APPEND
2841 case 2: // FILE_WRITE
2845 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2846 G_FLOAT(OFS_RETURN) = -3;
2849 filename = G_STRING(OFS_PARM0);
2850 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2851 // ../ is parent directory on many platforms
2852 // // is parent directory on Amiga
2853 // / at the beginning of a path is root on unix, and parent directory on Amiga
2854 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2855 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2856 for (i = 0;filename[i];i++)
2858 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2860 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);
2861 G_FLOAT(OFS_RETURN) = -4;
2865 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2867 if (pr_files[filenum] == NULL && modestring == "rb")
2868 pr_files[filenum] = FS_Open(filename, modestring, false);
2870 if (pr_files[filenum] == NULL)
2871 G_FLOAT(OFS_RETURN) = -1;
2873 G_FLOAT(OFS_RETURN) = filenum;
2876 //void(float fhandle) fclose = #111; // closes a file
2877 void PF_fclose(void)
2879 int filenum = G_FLOAT(OFS_PARM0);
2880 if (filenum < 0 || filenum >= MAX_PRFILES)
2882 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2885 if (pr_files[filenum] == NULL)
2887 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2890 FS_Close(pr_files[filenum]);
2891 pr_files[filenum] = NULL;
2894 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2898 static char string[STRINGTEMP_LENGTH];
2899 int filenum = G_FLOAT(OFS_PARM0);
2900 if (filenum < 0 || filenum >= MAX_PRFILES)
2902 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2905 if (pr_files[filenum] == NULL)
2907 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2913 c = FS_Getc(pr_files[filenum]);
2914 if (c == '\r' || c == '\n' || c < 0)
2916 if (end < STRINGTEMP_LENGTH - 1)
2920 // remove \n following \r
2922 c = FS_Getc(pr_files[filenum]);
2923 if (developer.integer)
2924 Con_Printf("fgets: %s\n", string);
2926 G_INT(OFS_RETURN) = PR_SetString(string);
2928 G_INT(OFS_RETURN) = 0;
2931 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2935 char string[STRINGTEMP_LENGTH];
2936 int filenum = G_FLOAT(OFS_PARM0);
2937 if (filenum < 0 || filenum >= MAX_PRFILES)
2939 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2942 if (pr_files[filenum] == NULL)
2944 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2947 PF_VarString(1, string, sizeof(string));
2948 if ((stringlength = strlen(string)))
2949 FS_Write(pr_files[filenum], string, stringlength);
2950 if (developer.integer)
2951 Con_Printf("fputs: %s\n", string);
2954 //float(string s) strlen = #114; // returns how many characters are in a string
2955 void PF_strlen(void)
2958 s = G_STRING(OFS_PARM0);
2960 G_FLOAT(OFS_RETURN) = strlen(s);
2962 G_FLOAT(OFS_RETURN) = 0;
2965 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2966 void PF_strcat(void)
2968 char *s = PR_GetTempString();
2969 PF_VarString(0, s, STRINGTEMP_LENGTH);
2970 G_INT(OFS_RETURN) = PR_SetString(s);
2973 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2974 void PF_substring(void)
2976 int i, start, length;
2977 char *s, *string = PR_GetTempString();
2978 s = G_STRING(OFS_PARM0);
2979 start = G_FLOAT(OFS_PARM1);
2980 length = G_FLOAT(OFS_PARM2);
2983 for (i = 0;i < start && *s;i++, s++);
2984 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2987 G_INT(OFS_RETURN) = PR_SetString(string);
2990 //vector(string s) stov = #117; // returns vector value from a string
2993 char string[STRINGTEMP_LENGTH];
2994 PF_VarString(0, string, sizeof(string));
2995 Math_atov(string, G_VECTOR(OFS_RETURN));
2998 //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)
2999 void PF_strzone(void)
3002 in = G_STRING(OFS_PARM0);
3003 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3005 G_INT(OFS_RETURN) = PR_SetString(out);
3008 //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!!!)
3009 void PF_strunzone(void)
3011 Mem_Free(G_STRING(OFS_PARM0));
3014 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3015 //this function originally written by KrimZon, made shorter by LordHavoc
3016 void PF_clientcommand (void)
3018 client_t *temp_client;
3021 //find client for this entity
3022 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3023 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3025 Con_Print("PF_clientcommand: entity is not a client\n");
3029 temp_client = host_client;
3030 host_client = svs.clients + i;
3031 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3032 host_client = temp_client;
3035 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3036 //this function originally written by KrimZon, made shorter by LordHavoc
3037 //20040203: rewritten by LordHavoc (no longer uses allocations)
3039 char *tokens[256], tokenbuf[4096];
3040 void PF_tokenize (void)
3044 p = G_STRING(OFS_PARM0);
3048 while(COM_ParseToken(&p, false))
3050 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3052 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3054 tokens[num_tokens++] = tokenbuf + pos;
3055 strcpy(tokenbuf + pos, com_token);
3056 pos += strlen(com_token) + 1;
3059 G_FLOAT(OFS_RETURN) = num_tokens;
3062 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3063 //this function originally written by KrimZon, made shorter by LordHavoc
3066 int token_num = G_FLOAT(OFS_PARM0);
3067 if (token_num >= 0 && token_num < num_tokens)
3068 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3070 G_INT(OFS_RETURN) = PR_SetString("");
3073 //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)
3074 void PF_setattachment (void)
3076 edict_t *e = G_EDICT(OFS_PARM0);
3077 edict_t *tagentity = G_EDICT(OFS_PARM1);
3078 char *tagname = G_STRING(OFS_PARM2);
3084 PF_WARNING("setattachment: can not modify world entity\n");
3086 PF_WARNING("setattachment: can not modify free entity\n");
3088 if (tagentity == NULL)
3089 tagentity = sv.edicts;
3091 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3093 v->edict = EDICT_TO_PROG(tagentity);
3095 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3098 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3100 modelindex = (int)tagentity->v->modelindex;
3101 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3103 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3104 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3105 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3107 // FIXME: use a model function to get tag info (need to handle skeletal)
3108 if (v->_float == 0 && model->alias.aliasnum_tags)
3109 for (i = 0;i < model->alias.aliasnum_tags;i++)
3110 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3113 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);
3116 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));
3121 /////////////////////////////////////////
3122 // DP_QC_FS_SEARCH extension
3124 // qc fs search handling
3125 #define MAX_SEARCHES 128
3127 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3129 void PR_Search_Init(void)
3131 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3134 void PR_Search_Reset(void)
3137 // reset the fssearch list
3138 for(i = 0; i < MAX_SEARCHES; i++)
3139 if(pr_fssearchlist[i])
3140 FS_FreeSearch(pr_fssearchlist[i]);
3141 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3148 float search_begin(string pattern, float caseinsensitive, float quiet)
3151 void PF_search_begin(void)
3155 int caseinsens, quiet;
3157 pattern = G_STRING(OFS_PARM0);
3159 PR_CheckEmptyString(pattern);
3161 caseinsens = G_FLOAT(OFS_PARM1);
3162 quiet = G_FLOAT(OFS_PARM2);
3164 for(handle = 0; handle < MAX_SEARCHES; handle++)
3165 if(!pr_fssearchlist[handle])
3168 if(handle >= MAX_SEARCHES)
3170 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3171 G_FLOAT(OFS_RETURN) = -2;
3175 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3176 G_FLOAT(OFS_RETURN) = -1;
3178 G_FLOAT(OFS_RETURN) = handle;
3185 void search_end(float handle)
3188 void PF_search_end(void)
3192 handle = G_FLOAT(OFS_PARM0);
3194 if(handle < 0 || handle >= MAX_SEARCHES)
3196 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3199 if(pr_fssearchlist[handle] == NULL)
3201 Con_Printf("PF_search_end: no such handle %i\n", handle);
3205 FS_FreeSearch(pr_fssearchlist[handle]);
3206 pr_fssearchlist[handle] = NULL;
3213 float search_getsize(float handle)
3216 void PF_search_getsize(void)
3220 handle = G_FLOAT(OFS_PARM0);
3222 if(handle < 0 || handle >= MAX_SEARCHES)
3224 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3227 if(pr_fssearchlist[handle] == NULL)
3229 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3233 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3238 VM_search_getfilename
3240 string search_getfilename(float handle, float num)
3243 void PF_search_getfilename(void)
3245 int handle, filenum;
3248 handle = G_FLOAT(OFS_PARM0);
3249 filenum = G_FLOAT(OFS_PARM1);
3251 if(handle < 0 || handle >= MAX_SEARCHES)
3253 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3256 if(pr_fssearchlist[handle] == NULL)
3258 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3261 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3263 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3267 tmp = PR_GetTempString();
3268 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3270 G_INT(OFS_RETURN) = PR_SetString(tmp);
3273 void PF_cvar_string (void)
3279 str = G_STRING(OFS_PARM0);
3280 var = Cvar_FindVar (str);
3283 tmp = PR_GetTempString();
3284 strcpy(tmp, var->string);
3288 G_INT(OFS_RETURN) = PR_SetString(tmp);
3293 builtin_t pr_builtin[] =
3296 PF_makevectors, // #1 void(entity e) makevectors
3297 PF_setorigin, // #2 void(entity e, vector o) setorigin
3298 PF_setmodel, // #3 void(entity e, string m) setmodel
3299 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3300 NULL, // #5 void(entity e, vector min, vector max) setabssize
3301 PF_break, // #6 void() break
3302 PF_random, // #7 float() random
3303 PF_sound, // #8 void(entity e, float chan, string samp) sound
3304 PF_normalize, // #9 vector(vector v) normalize
3305 PF_error, // #10 void(string e) error
3306 PF_objerror, // #11 void(string e) objerror
3307 PF_vlen, // #12 float(vector v) vlen
3308 PF_vectoyaw, // #13 float(vector v) vectoyaw
3309 PF_Spawn, // #14 entity() spawn
3310 PF_Remove, // #15 void(entity e) remove
3311 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3312 PF_checkclient, // #17 entity() clientlist
3313 PF_Find, // #18 entity(entity start, .string fld, string match) find
3314 PF_precache_sound, // #19 void(string s) precache_sound
3315 PF_precache_model, // #20 void(string s) precache_model
3316 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3317 PF_findradius, // #22 entity(vector org, float rad) findradius
3318 PF_bprint, // #23 void(string s) bprint
3319 PF_sprint, // #24 void(entity client, string s) sprint
3320 PF_dprint, // #25 void(string s) dprint
3321 PF_ftos, // #26 void(string s) ftos
3322 PF_vtos, // #27 void(string s) vtos
3323 PF_coredump, // #28 void() coredump
3324 PF_traceon, // #29 void() traceon
3325 PF_traceoff, // #30 void() traceoff
3326 PF_eprint, // #31 void(entity e) eprint
3327 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3329 PF_droptofloor, // #34 float() droptofloor
3330 PF_lightstyle, // #35 void(float style, string value) lightstyle
3331 PF_rint, // #36 float(float v) rint
3332 PF_floor, // #37 float(float v) floor
3333 PF_ceil, // #38 float(float v) ceil
3335 PF_checkbottom, // #40 float(entity e) checkbottom
3336 PF_pointcontents , // #41 float(vector v) pointcontents
3338 PF_fabs, // #43 float(float f) fabs
3339 PF_aim, // #44 vector(entity e, float speed) aim
3340 PF_cvar, // #45 float(string s) cvar
3341 PF_localcmd, // #46 void(string s) localcmd
3342 PF_nextent, // #47 entity(entity e) nextent
3343 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3344 PF_changeyaw, // #49 void() ChangeYaw
3346 PF_vectoangles, // #51 vector(vector v) vectoangles
3347 PF_WriteByte, // #52 void(float to, float f) WriteByte
3348 PF_WriteChar, // #53 void(float to, float f) WriteChar
3349 PF_WriteShort, // #54 void(float to, float f) WriteShort
3350 PF_WriteLong, // #55 void(float to, float f) WriteLong
3351 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3352 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3353 PF_WriteString, // #58 void(float to, string s) WriteString
3354 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3355 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3356 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3357 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3358 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3359 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3360 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3362 SV_MoveToGoal, // #67 void(float step) movetogoal
3363 PF_precache_file, // #68 string(string s) precache_file
3364 PF_makestatic, // #69 void(entity e) makestatic
3365 PF_changelevel, // #70 void(string s) changelevel
3367 PF_cvar_set, // #72 void(string var, string val) cvar_set
3368 PF_centerprint, // #73 void(entity client, strings) centerprint
3369 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3370 PF_precache_model, // #75 string(string s) precache_model2
3371 PF_precache_sound, // #76 string(string s) precache_sound2
3372 PF_precache_file, // #77 string(string s) precache_file2
3373 PF_setspawnparms, // #78 void(entity e) setspawnparms
3376 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3385 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3386 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3387 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3388 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3389 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3390 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3391 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3392 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3393 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3394 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3405 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3406 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3407 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3408 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3409 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3410 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3411 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3412 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3413 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3414 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3415 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3416 a a a a a a a a // #120-199
3417 a a a a a a a a a a // #200-299
3418 a a a a a a a a a a // #300-399
3419 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3420 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3421 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3422 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3423 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3424 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3425 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3426 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3427 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3428 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3429 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3430 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3431 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3432 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3433 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3434 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3435 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3436 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3437 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3438 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3439 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3440 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3441 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3442 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3443 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3444 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3445 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3446 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3447 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3448 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3449 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3450 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3451 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3452 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3453 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3454 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3455 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3456 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3457 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3458 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3459 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3460 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3461 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3462 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3463 PF_search_begin, // #444
3464 PF_search_end, // #445
3465 PF_search_getsize, // #446
3466 PF_search_getfilename, // #447
3467 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3468 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3469 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3479 a a a a // #460-499 (LordHavoc)
3482 builtin_t *pr_builtins = pr_builtin;
3483 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3485 void PR_Cmd_Init(void)
3487 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3492 void PR_Cmd_Reset(void)
3494 Mem_EmptyPool(pr_strings_mempool);
3496 PR_Files_CloseAll();