2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
24 cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
26 mempool_t *pr_strings_mempool;
28 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
29 #define STRINGTEMP_BUFFERS 16
30 #define STRINGTEMP_LENGTH 4096
31 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
32 static int pr_string_tempindex = 0;
34 static char *PR_GetTempString(void)
37 s = pr_string_temp[pr_string_tempindex];
38 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
42 #define RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
43 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
44 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
48 ===============================================================================
52 ===============================================================================
56 void PF_VarString(int first, char *out, int outlength)
62 outend = out + outlength - 1;
63 for (i = first;i < pr_argc && out < outend;i++)
65 s = G_STRING((OFS_PARM0+i*3));
66 while (out < outend && *s)
72 char *ENGINE_EXTENSIONS =
83 "DP_ENT_CUSTOMCOLORMAP "
84 "DP_ENT_EXTERIORMODELTOCLIENT "
86 "DP_ENT_LOWPRECISION "
89 "DP_GFX_EXTERNALTEXTURES "
91 "DP_GFX_QUAKE3MODELTAGS "
95 "DP_HALFLIFE_MAP_CVAR "
99 "DP_MOVETYPEBOUNCEMISSILE "
106 "DP_QC_FINDCHAINFLOAT "
108 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
113 "DP_QC_SINCOSSQRTPOW "
116 "DP_QC_TRACE_MOVETYPE_HITMODEL "
117 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
118 "DP_QC_VECTORVECTORS "
124 "DP_SV_DRAWONLYTOCLIENT "
126 "DP_SV_EXTERIORMODELTOCLIENT "
127 "DP_SV_NODRAWTOCLIENT "
128 "DP_SV_PLAYERPHYSICS "
129 "DP_SV_ROTATINGBMODEL "
135 "DP_TE_EXPLOSIONRGB "
137 "DP_TE_PARTICLECUBE "
138 "DP_TE_PARTICLERAIN "
139 "DP_TE_PARTICLESNOW "
141 "DP_TE_QUADEFFECTS1 "
144 "DP_TE_STANDARDEFFECTBUILTINS "
147 "KRIMZON_SV_PARSECLIENTCOMMAND "
150 "TENEBRAE_GFX_DLIGHTS "
154 qboolean checkextension(char *name)
159 for (e = ENGINE_EXTENSIONS;*e;e++)
166 while (*e && *e != ' ')
168 if (e - start == len)
169 if (!strncasecmp(start, name, len))
179 returns true if the extension is supported by the server
181 checkextension(extensionname)
184 void PF_checkextension (void)
186 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
193 This is a TERMINAL error, which will kill off the entire server.
202 char string[STRINGTEMP_LENGTH];
204 PF_VarString(0, string, sizeof(string));
205 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
206 ed = PROG_TO_EDICT(pr_global_struct->self);
209 PF_ERROR("Program error");
216 Dumps out self, then an error message. The program is aborted and self is
217 removed, but the level can continue.
222 void PF_objerror (void)
225 char string[STRINGTEMP_LENGTH];
227 PF_VarString(0, string, sizeof(string));
228 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
229 ed = PROG_TO_EDICT(pr_global_struct->self);
239 Writes new values for v_forward, v_up, and v_right based on angles
243 void PF_makevectors (void)
245 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
252 Writes new values for v_forward, v_up, and v_right based on the given forward vector
253 vectorvectors(vector, vector)
256 void PF_vectorvectors (void)
258 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
259 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
266 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.
268 setorigin (entity, origin)
271 void PF_setorigin (void)
276 e = G_EDICT(OFS_PARM0);
278 PF_WARNING("setorigin: can not modify world entity\n");
280 PF_WARNING("setorigin: can not modify free entity\n");
281 org = G_VECTOR(OFS_PARM1);
282 VectorCopy (org, e->v->origin);
283 SV_LinkEdict (e, false);
287 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
291 for (i=0 ; i<3 ; i++)
293 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
295 // set derived values
296 VectorCopy (min, e->v->mins);
297 VectorCopy (max, e->v->maxs);
298 VectorSubtract (max, min, e->v->size);
300 SV_LinkEdict (e, false);
307 the size box is rotated by the current angle
308 LordHavoc: no it isn't...
310 setsize (entity, minvector, maxvector)
313 void PF_setsize (void)
318 e = G_EDICT(OFS_PARM0);
320 PF_WARNING("setsize: can not modify world entity\n");
322 PF_WARNING("setsize: can not modify free entity\n");
323 min = G_VECTOR(OFS_PARM1);
324 max = G_VECTOR(OFS_PARM2);
325 SetMinMaxSize (e, min, max, false);
333 setmodel(entity, model)
336 void PF_setmodel (void)
343 e = G_EDICT(OFS_PARM0);
345 PF_WARNING("setmodel: can not modify world entity\n");
347 PF_WARNING("setmodel: can not modify free entity\n");
348 m = G_STRING(OFS_PARM1);
350 // check to see if model was properly precached
351 for (i=0, check = sv.model_precache ; *check ; i++, check++)
352 if (!strcmp(*check, m))
356 PF_WARNING("setmodel: no precache\n");
359 e->v->model = PR_SetString(*check);
360 e->v->modelindex = i;
362 mod = sv.models[ (int)e->v->modelindex];
365 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
367 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
374 broadcast print to everyone on server
379 void PF_bprint (void)
381 char string[STRINGTEMP_LENGTH];
382 PF_VarString(0, string, sizeof(string));
383 SV_BroadcastPrint(string);
390 single print to a specific client
392 sprint(clientent, value)
395 void PF_sprint (void)
399 char string[STRINGTEMP_LENGTH];
401 entnum = G_EDICTNUM(OFS_PARM0);
403 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
405 Con_Print("tried to sprint to a non-client\n");
409 client = svs.clients + entnum-1;
410 if (!client->netconnection)
412 PF_VarString(1, string, sizeof(string));
413 MSG_WriteChar(&client->message,svc_print);
414 MSG_WriteString(&client->message, string);
422 single print to a specific client
424 centerprint(clientent, value)
427 void PF_centerprint (void)
431 char string[STRINGTEMP_LENGTH];
433 entnum = G_EDICTNUM(OFS_PARM0);
435 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
437 Con_Print("tried to sprint to a non-client\n");
441 client = svs.clients + entnum-1;
442 if (!client->netconnection)
444 PF_VarString(1, string, sizeof(string));
445 MSG_WriteChar(&client->message,svc_centerprint);
446 MSG_WriteString(&client->message, string);
454 vector normalize(vector)
457 void PF_normalize (void)
463 value1 = G_VECTOR(OFS_PARM0);
465 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
469 newvalue[0] = newvalue[1] = newvalue[2] = 0;
473 newvalue[0] = value1[0] * new;
474 newvalue[1] = value1[1] * new;
475 newvalue[2] = value1[2] * new;
478 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
493 value1 = G_VECTOR(OFS_PARM0);
495 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
498 G_FLOAT(OFS_RETURN) = new;
505 float vectoyaw(vector)
508 void PF_vectoyaw (void)
513 value1 = G_VECTOR(OFS_PARM0);
515 if (value1[1] == 0 && value1[0] == 0)
519 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
524 G_FLOAT(OFS_RETURN) = yaw;
532 vector vectoangles(vector)
535 void PF_vectoangles (void)
541 value1 = G_VECTOR(OFS_PARM0);
543 if (value1[1] == 0 && value1[0] == 0)
553 // LordHavoc: optimized a bit
556 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
560 else if (value1[1] > 0)
565 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
566 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
571 G_FLOAT(OFS_RETURN+0) = pitch;
572 G_FLOAT(OFS_RETURN+1) = yaw;
573 G_FLOAT(OFS_RETURN+2) = 0;
580 Returns a number from 0<= num < 1
585 void PF_random (void)
589 num = (rand ()&0x7fff) / ((float)0x7fff);
591 G_FLOAT(OFS_RETURN) = num;
598 particle(origin, color, count)
601 void PF_particle (void)
607 org = G_VECTOR(OFS_PARM0);
608 dir = G_VECTOR(OFS_PARM1);
609 color = G_FLOAT(OFS_PARM2);
610 count = G_FLOAT(OFS_PARM3);
611 SV_StartParticle (org, dir, color, count);
621 void PF_ambientsound (void)
626 float vol, attenuation;
627 int i, soundnum, large;
629 pos = G_VECTOR (OFS_PARM0);
630 samp = G_STRING(OFS_PARM1);
631 vol = G_FLOAT(OFS_PARM2);
632 attenuation = G_FLOAT(OFS_PARM3);
634 // check to see if samp was properly precached
635 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
636 if (!strcmp(*check,samp))
641 Con_Printf("no precache: %s\n", samp);
649 // add an svc_spawnambient command to the level signon packet
652 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
654 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
656 for (i=0 ; i<3 ; i++)
657 MSG_WriteDPCoord(&sv.signon, pos[i]);
660 MSG_WriteShort (&sv.signon, soundnum);
662 MSG_WriteByte (&sv.signon, soundnum);
664 MSG_WriteByte (&sv.signon, vol*255);
665 MSG_WriteByte (&sv.signon, attenuation*64);
673 Each entity can have eight independant sound sources, like voice,
676 Channel 0 is an auto-allocate channel, the others override anything
677 already running on that entity/channel pair.
679 An attenuation of 0 will play full volume everywhere in the level.
680 Larger attenuations will drop off.
692 entity = G_EDICT(OFS_PARM0);
693 channel = G_FLOAT(OFS_PARM1);
694 sample = G_STRING(OFS_PARM2);
695 volume = G_FLOAT(OFS_PARM3) * 255;
696 attenuation = G_FLOAT(OFS_PARM4);
698 if (volume < 0 || volume > 255)
699 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
701 if (attenuation < 0 || attenuation > 4)
702 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
704 if (channel < 0 || channel > 7)
705 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
707 SV_StartSound (entity, channel, sample, volume, attenuation);
719 PF_ERROR("break: break statement\n");
726 Used for use tracing and shot targeting
727 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
728 if the tryents flag is set.
730 traceline (vector1, vector2, tryents)
733 void PF_traceline (void)
740 pr_xfunction->builtinsprofile += 30;
742 v1 = G_VECTOR(OFS_PARM0);
743 v2 = G_VECTOR(OFS_PARM1);
744 move = G_FLOAT(OFS_PARM2);
745 ent = G_EDICT(OFS_PARM3);
747 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
749 pr_global_struct->trace_allsolid = trace.allsolid;
750 pr_global_struct->trace_startsolid = trace.startsolid;
751 pr_global_struct->trace_fraction = trace.fraction;
752 pr_global_struct->trace_inwater = trace.inwater;
753 pr_global_struct->trace_inopen = trace.inopen;
754 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
755 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
756 pr_global_struct->trace_plane_dist = trace.plane.dist;
758 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
760 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
761 // FIXME: add trace_endcontents
769 Used for use tracing and shot targeting
770 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
771 if the tryents flag is set.
773 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
776 // LordHavoc: added this for my own use, VERY useful, similar to traceline
777 void PF_tracebox (void)
779 float *v1, *v2, *m1, *m2;
784 pr_xfunction->builtinsprofile += 30;
786 v1 = G_VECTOR(OFS_PARM0);
787 m1 = G_VECTOR(OFS_PARM1);
788 m2 = G_VECTOR(OFS_PARM2);
789 v2 = G_VECTOR(OFS_PARM3);
790 move = G_FLOAT(OFS_PARM4);
791 ent = G_EDICT(OFS_PARM5);
793 trace = SV_Move (v1, m1, m2, v2, move, ent);
795 pr_global_struct->trace_allsolid = trace.allsolid;
796 pr_global_struct->trace_startsolid = trace.startsolid;
797 pr_global_struct->trace_fraction = trace.fraction;
798 pr_global_struct->trace_inwater = trace.inwater;
799 pr_global_struct->trace_inopen = trace.inopen;
800 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
801 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
802 pr_global_struct->trace_plane_dist = trace.plane.dist;
804 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
806 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
809 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
810 void PF_TraceToss (void)
816 pr_xfunction->builtinsprofile += 600;
818 ent = G_EDICT(OFS_PARM0);
819 if (ent == sv.edicts)
820 PF_WARNING("tracetoss: can not use world entity\n");
821 ignore = G_EDICT(OFS_PARM1);
823 trace = SV_Trace_Toss (ent, ignore);
825 pr_global_struct->trace_allsolid = trace.allsolid;
826 pr_global_struct->trace_startsolid = trace.startsolid;
827 pr_global_struct->trace_fraction = trace.fraction;
828 pr_global_struct->trace_inwater = trace.inwater;
829 pr_global_struct->trace_inopen = trace.inopen;
830 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
831 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
832 pr_global_struct->trace_plane_dist = trace.plane.dist;
834 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
836 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
844 Returns true if the given entity can move to the given position from it's
845 current position by walking or rolling.
847 scalar checkpos (entity, vector)
850 void PF_checkpos (void)
854 //============================================================================
857 qbyte checkpvs[MAX_MAP_LEAFS/8];
859 int PF_newcheckclient (int check)
865 // cycle to the next one
867 check = bound(1, check, svs.maxclients);
868 if (check == svs.maxclients)
876 pr_xfunction->builtinsprofile++;
878 if (i == svs.maxclients+1)
880 // look up the client's edict
882 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
883 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
885 // found a valid client (possibly the same one again)
889 // get the PVS for the entity
890 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
892 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
893 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
902 Returns a client (or object that has a client enemy) that would be a
905 If there is more than one valid option, they are cycled each frame
907 If (self.origin + self.viewofs) is not in the PVS of the current target,
908 it is not returned at all.
913 int c_invis, c_notvis;
914 void PF_checkclient (void)
919 // find a new check if on a new frame
920 if (sv.time - sv.lastchecktime >= 0.1)
922 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
923 sv.lastchecktime = sv.time;
926 // return check if it might be visible
927 ent = EDICT_NUM(sv.lastcheck);
928 if (ent->e->free || ent->v->health <= 0)
930 RETURN_EDICT(sv.edicts);
934 // if current entity can't possibly see the check entity, return 0
935 self = PROG_TO_EDICT(pr_global_struct->self);
936 VectorAdd(self->v->origin, self->v->view_ofs, view);
937 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
940 RETURN_EDICT(sv.edicts);
944 // might be able to see it
949 //============================================================================
956 Sends text over to the client's execution buffer
958 stuffcmd (clientent, value)
961 void PF_stuffcmd (void)
967 entnum = G_EDICTNUM(OFS_PARM0);
968 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
970 Con_Print("Can't stuffcmd to a non-client\n");
973 str = G_STRING(OFS_PARM1);
976 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
977 Host_ClientCommands ("%s", str);
985 Sends text to server console
990 void PF_localcmd (void)
992 Cbuf_AddText(G_STRING(OFS_PARM0));
1004 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1014 void PF_cvar_set (void)
1016 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1023 Returns a chain of entities that have origins within a spherical area
1025 findradius (origin, radius)
1028 void PF_findradius (void)
1030 edict_t *ent, *chain;
1037 chain = (edict_t *)sv.edicts;
1039 org = G_VECTOR(OFS_PARM0);
1040 radius = G_FLOAT(OFS_PARM1);
1041 radius2 = radius * radius;
1043 ent = NEXT_EDICT(sv.edicts);
1044 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1046 pr_xfunction->builtinsprofile++;
1049 if (ent->v->solid == SOLID_NOT)
1052 // LordHavoc: compare against bounding box rather than center,
1053 // and use DotProduct instead of Length, major speedup
1054 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1055 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1056 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1057 if (DotProduct(eorg, eorg) > radius2)
1060 ent->v->chain = EDICT_TO_PROG(chain);
1064 RETURN_EDICT(chain);
1073 void PF_dprint (void)
1075 char string[STRINGTEMP_LENGTH];
1076 if (developer.integer)
1078 PF_VarString(0, string, sizeof(string));
1087 v = G_FLOAT(OFS_PARM0);
1089 s = PR_GetTempString();
1090 if ((float)((int)v) == v)
1091 sprintf(s, "%i", (int)v);
1093 sprintf(s, "%f", v);
1094 G_INT(OFS_RETURN) = PR_SetString(s);
1100 v = G_FLOAT(OFS_PARM0);
1101 G_FLOAT(OFS_RETURN) = fabs(v);
1107 s = PR_GetTempString();
1108 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1109 G_INT(OFS_RETURN) = PR_SetString(s);
1115 s = PR_GetTempString();
1116 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1117 G_INT(OFS_RETURN) = PR_SetString(s);
1120 void PF_Spawn (void)
1123 pr_xfunction->builtinsprofile += 20;
1128 void PF_Remove (void)
1131 pr_xfunction->builtinsprofile += 20;
1133 ed = G_EDICT(OFS_PARM0);
1134 if (ed == sv.edicts)
1135 PF_WARNING("remove: tried to remove world\n");
1136 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1137 PF_WARNING("remove: tried to remove a client\n");
1138 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1139 if (ed->e->free && developer.integer)
1140 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1145 // entity (entity start, .string field, string match) find = #5;
1153 e = G_EDICTNUM(OFS_PARM0);
1154 f = G_INT(OFS_PARM1);
1155 s = G_STRING(OFS_PARM2);
1158 RETURN_EDICT(sv.edicts);
1162 for (e++ ; e < sv.num_edicts ; e++)
1164 pr_xfunction->builtinsprofile++;
1178 RETURN_EDICT(sv.edicts);
1181 // LordHavoc: added this for searching float, int, and entity reference fields
1182 void PF_FindFloat (void)
1189 e = G_EDICTNUM(OFS_PARM0);
1190 f = G_INT(OFS_PARM1);
1191 s = G_FLOAT(OFS_PARM2);
1193 for (e++ ; e < sv.num_edicts ; e++)
1195 pr_xfunction->builtinsprofile++;
1199 if (E_FLOAT(ed,f) == s)
1206 RETURN_EDICT(sv.edicts);
1209 // chained search for strings in entity fields
1210 // entity(.string field, string match) findchain = #402;
1211 void PF_findchain (void)
1216 edict_t *ent, *chain;
1218 chain = (edict_t *)sv.edicts;
1220 f = G_INT(OFS_PARM0);
1221 s = G_STRING(OFS_PARM1);
1224 RETURN_EDICT(sv.edicts);
1228 ent = NEXT_EDICT(sv.edicts);
1229 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1231 pr_xfunction->builtinsprofile++;
1234 t = E_STRING(ent,f);
1240 ent->v->chain = EDICT_TO_PROG(chain);
1244 RETURN_EDICT(chain);
1247 // LordHavoc: chained search for float, int, and entity reference fields
1248 // entity(.string field, float match) findchainfloat = #403;
1249 void PF_findchainfloat (void)
1254 edict_t *ent, *chain;
1256 chain = (edict_t *)sv.edicts;
1258 f = G_INT(OFS_PARM0);
1259 s = G_FLOAT(OFS_PARM1);
1261 ent = NEXT_EDICT(sv.edicts);
1262 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1264 pr_xfunction->builtinsprofile++;
1267 if (E_FLOAT(ent,f) != s)
1270 ent->v->chain = EDICT_TO_PROG(chain);
1274 RETURN_EDICT(chain);
1277 void PR_CheckEmptyString (char *s)
1280 PF_ERROR("Bad string");
1283 void PF_precache_file (void)
1284 { // precache_file is only used to copy files with qcc, it does nothing
1285 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1288 void PF_precache_sound (void)
1293 if (sv.state != ss_loading)
1294 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1296 s = G_STRING(OFS_PARM0);
1297 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1298 PR_CheckEmptyString (s);
1300 for (i=0 ; i<MAX_SOUNDS ; i++)
1302 if (!sv.sound_precache[i])
1304 sv.sound_precache[i] = s;
1307 if (!strcmp(sv.sound_precache[i], s))
1310 PF_ERROR("PF_precache_sound: overflow");
1313 void PF_precache_model (void)
1318 if (sv.state != ss_loading)
1319 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1321 s = G_STRING(OFS_PARM0);
1322 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1324 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1325 PR_CheckEmptyString (s);
1327 for (i=0 ; i<MAX_MODELS ; i++)
1329 if (!sv.model_precache[i])
1331 sv.model_precache[i] = s;
1332 sv.models[i] = Mod_ForName (s, true, false, false);
1335 if (!strcmp(sv.model_precache[i], s))
1338 PF_ERROR("PF_precache_model: overflow");
1342 void PF_coredump (void)
1347 void PF_traceon (void)
1352 void PF_traceoff (void)
1357 void PF_eprint (void)
1359 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1366 float(float yaw, float dist) walkmove
1369 void PF_walkmove (void)
1377 // assume failure if it returns early
1378 G_FLOAT(OFS_RETURN) = 0;
1380 ent = PROG_TO_EDICT(pr_global_struct->self);
1381 if (ent == sv.edicts)
1382 PF_WARNING("walkmove: can not modify world entity\n");
1384 PF_WARNING("walkmove: can not modify free entity\n");
1385 yaw = G_FLOAT(OFS_PARM0);
1386 dist = G_FLOAT(OFS_PARM1);
1388 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1391 yaw = yaw*M_PI*2 / 360;
1393 move[0] = cos(yaw)*dist;
1394 move[1] = sin(yaw)*dist;
1397 // save program state, because SV_movestep may call other progs
1398 oldf = pr_xfunction;
1399 oldself = pr_global_struct->self;
1401 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1404 // restore program state
1405 pr_xfunction = oldf;
1406 pr_global_struct->self = oldself;
1416 void PF_droptofloor (void)
1422 // assume failure if it returns early
1423 G_FLOAT(OFS_RETURN) = 0;
1425 ent = PROG_TO_EDICT(pr_global_struct->self);
1426 if (ent == sv.edicts)
1427 PF_WARNING("droptofloor: can not modify world entity\n");
1429 PF_WARNING("droptofloor: can not modify free entity\n");
1431 VectorCopy (ent->v->origin, end);
1434 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1436 if (trace.fraction != 1)
1438 VectorCopy (trace.endpos, ent->v->origin);
1439 SV_LinkEdict (ent, false);
1440 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1441 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1442 G_FLOAT(OFS_RETURN) = 1;
1443 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1444 ent->e->suspendedinairflag = true;
1452 void(float style, string value) lightstyle
1455 void PF_lightstyle (void)
1462 style = G_FLOAT(OFS_PARM0);
1463 val = G_STRING(OFS_PARM1);
1465 // change the string in sv
1466 sv.lightstyles[style] = val;
1468 // send message to all clients on this server
1469 if (sv.state != ss_active)
1472 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1474 if (client->netconnection)
1476 MSG_WriteChar (&client->message, svc_lightstyle);
1477 MSG_WriteChar (&client->message,style);
1478 MSG_WriteString (&client->message, val);
1486 f = G_FLOAT(OFS_PARM0);
1488 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1490 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1492 void PF_floor (void)
1494 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1498 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1507 void PF_checkbottom (void)
1509 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1517 void PF_pointcontents (void)
1519 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1526 entity nextent(entity)
1529 void PF_nextent (void)
1534 i = G_EDICTNUM(OFS_PARM0);
1537 pr_xfunction->builtinsprofile++;
1539 if (i == sv.num_edicts)
1541 RETURN_EDICT(sv.edicts);
1557 Pick a vector for the player to shoot along
1558 vector aim(entity, missilespeed)
1563 edict_t *ent, *check, *bestent;
1564 vec3_t start, dir, end, bestdir;
1567 float dist, bestdist;
1570 // assume failure if it returns early
1571 VectorClear(G_VECTOR(OFS_RETURN));
1573 ent = G_EDICT(OFS_PARM0);
1574 if (ent == sv.edicts)
1575 PF_WARNING("aim: can not use world entity\n");
1577 PF_WARNING("aim: can not use free entity\n");
1578 speed = G_FLOAT(OFS_PARM1);
1580 VectorCopy (ent->v->origin, start);
1583 // try sending a trace straight
1584 VectorCopy (pr_global_struct->v_forward, dir);
1585 VectorMA (start, 2048, dir, end);
1586 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1587 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1588 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1590 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1595 // try all possible entities
1596 VectorCopy (dir, bestdir);
1597 bestdist = sv_aim.value;
1600 check = NEXT_EDICT(sv.edicts);
1601 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1603 pr_xfunction->builtinsprofile++;
1604 if (check->v->takedamage != DAMAGE_AIM)
1608 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1609 continue; // don't aim at teammate
1610 for (j=0 ; j<3 ; j++)
1611 end[j] = check->v->origin[j]
1612 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1613 VectorSubtract (end, start, dir);
1614 VectorNormalize (dir);
1615 dist = DotProduct (dir, pr_global_struct->v_forward);
1616 if (dist < bestdist)
1617 continue; // to far to turn
1618 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1619 if (tr.ent == check)
1620 { // can shoot at this one
1628 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1629 dist = DotProduct (dir, pr_global_struct->v_forward);
1630 VectorScale (pr_global_struct->v_forward, dist, end);
1632 VectorNormalize (end);
1633 VectorCopy (end, G_VECTOR(OFS_RETURN));
1637 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1645 This was a major timewaster in progs, so it was converted to C
1648 void PF_changeyaw (void)
1651 float ideal, current, move, speed;
1653 ent = PROG_TO_EDICT(pr_global_struct->self);
1654 if (ent == sv.edicts)
1655 PF_WARNING("changeyaw: can not modify world entity\n");
1657 PF_WARNING("changeyaw: can not modify free entity\n");
1658 current = ANGLEMOD(ent->v->angles[1]);
1659 ideal = ent->v->ideal_yaw;
1660 speed = ent->v->yaw_speed;
1662 if (current == ideal)
1664 move = ideal - current;
1665 if (ideal > current)
1686 ent->v->angles[1] = ANGLEMOD (current + move);
1694 void PF_changepitch (void)
1697 float ideal, current, move, speed;
1700 ent = G_EDICT(OFS_PARM0);
1701 if (ent == sv.edicts)
1702 PF_WARNING("changepitch: can not modify world entity\n");
1704 PF_WARNING("changepitch: can not modify free entity\n");
1705 current = ANGLEMOD( ent->v->angles[0] );
1706 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1707 ideal = val->_float;
1710 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1713 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1714 speed = val->_float;
1717 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1721 if (current == ideal)
1723 move = ideal - current;
1724 if (ideal > current)
1745 ent->v->angles[0] = ANGLEMOD (current + move);
1749 ===============================================================================
1753 ===============================================================================
1756 #define MSG_BROADCAST 0 // unreliable to all
1757 #define MSG_ONE 1 // reliable to one (msg_entity)
1758 #define MSG_ALL 2 // reliable to all
1759 #define MSG_INIT 3 // write to the init string
1761 sizebuf_t *WriteDest (void)
1767 dest = G_FLOAT(OFS_PARM0);
1771 return &sv.datagram;
1774 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1775 entnum = NUM_FOR_EDICT(ent);
1776 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1777 Host_Error("WriteDest: tried to write to non-client\n");
1778 return &svs.clients[entnum-1].message;
1781 return &sv.reliable_datagram;
1787 Host_Error("WriteDest: bad destination");
1794 void PF_WriteByte (void)
1796 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1799 void PF_WriteChar (void)
1801 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1804 void PF_WriteShort (void)
1806 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1809 void PF_WriteLong (void)
1811 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1814 void PF_WriteAngle (void)
1816 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1819 void PF_WriteCoord (void)
1821 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1824 void PF_WriteString (void)
1826 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1830 void PF_WriteEntity (void)
1832 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1835 //=============================================================================
1837 void PF_makestatic (void)
1842 ent = G_EDICT(OFS_PARM0);
1843 if (ent == sv.edicts)
1844 PF_WARNING("makestatic: can not modify world entity\n");
1846 PF_WARNING("makestatic: can not modify free entity\n");
1849 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1854 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1855 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1856 MSG_WriteShort (&sv.signon, ent->v->frame);
1860 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1861 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1862 MSG_WriteByte (&sv.signon, ent->v->frame);
1865 MSG_WriteByte (&sv.signon, ent->v->colormap);
1866 MSG_WriteByte (&sv.signon, ent->v->skin);
1867 for (i=0 ; i<3 ; i++)
1869 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1870 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1873 // throw the entity away now
1877 //=============================================================================
1884 void PF_setspawnparms (void)
1890 ent = G_EDICT(OFS_PARM0);
1891 i = NUM_FOR_EDICT(ent);
1892 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1894 Con_Print("tried to setspawnparms on a non-client\n");
1898 // copy spawn parms out of the client_t
1899 client = svs.clients + i-1;
1900 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1901 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1909 void PF_changelevel (void)
1913 // make sure we don't issue two changelevels
1914 if (svs.changelevel_issued)
1916 svs.changelevel_issued = true;
1918 s = G_STRING(OFS_PARM0);
1919 Cbuf_AddText (va("changelevel %s\n",s));
1924 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1929 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1934 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1941 Returns a vector of length < 1
1946 void PF_randomvec (void)
1951 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1952 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1953 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1955 while (DotProduct(temp, temp) >= 1);
1956 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1963 Returns a color vector indicating the lighting at the requested point.
1965 (Internal Operation note: actually measures the light beneath the point, just like
1966 the model lighting on the client)
1971 void PF_GetLight (void)
1973 vec3_t ambientcolor, diffusecolor, diffusenormal;
1975 p = G_VECTOR(OFS_PARM0);
1976 VectorClear(ambientcolor);
1977 VectorClear(diffusecolor);
1978 VectorClear(diffusenormal);
1979 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1980 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1981 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1984 #define MAX_QC_CVARS 128
1985 cvar_t qc_cvar[MAX_QC_CVARS];
1988 void PF_registercvar (void)
1992 name = G_STRING(OFS_PARM0);
1993 value = G_STRING(OFS_PARM1);
1994 G_FLOAT(OFS_RETURN) = 0;
1995 // first check to see if it has already been defined
1996 if (Cvar_FindVar (name))
1999 // check for overlap with a command
2000 if (Cmd_Exists (name))
2002 Con_Printf("PF_registercvar: %s is a command\n", name);
2006 if (currentqc_cvar >= MAX_QC_CVARS)
2007 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2009 // copy the name and value
2010 variable = &qc_cvar[currentqc_cvar++];
2011 variable->name = Z_Malloc (strlen(name)+1);
2012 strcpy (variable->name, name);
2013 variable->string = Z_Malloc (strlen(value)+1);
2014 strcpy (variable->string, value);
2015 variable->value = atof (value);
2017 Cvar_RegisterVariable(variable);
2018 G_FLOAT(OFS_RETURN) = 1; // success
2025 returns the minimum of two supplied floats
2032 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2034 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2035 else if (pr_argc >= 3)
2038 float f = G_FLOAT(OFS_PARM0);
2039 for (i = 1;i < pr_argc;i++)
2040 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2041 f = G_FLOAT((OFS_PARM0+i*3));
2042 G_FLOAT(OFS_RETURN) = f;
2046 G_FLOAT(OFS_RETURN) = 0;
2047 PF_WARNING("min: must supply at least 2 floats\n");
2055 returns the maximum of two supplied floats
2062 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2064 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2065 else if (pr_argc >= 3)
2068 float f = G_FLOAT(OFS_PARM0);
2069 for (i = 1;i < pr_argc;i++)
2070 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2071 f = G_FLOAT((OFS_PARM0+i*3));
2072 G_FLOAT(OFS_RETURN) = f;
2076 G_FLOAT(OFS_RETURN) = 0;
2077 PF_WARNING("max: must supply at least 2 floats\n");
2085 returns number bounded by supplied range
2087 min(min, value, max)
2090 void PF_bound (void)
2092 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2099 returns a raised to power b
2106 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2113 copies data from one entity to another
2115 copyentity(src, dst)
2118 void PF_copyentity (void)
2121 in = G_EDICT(OFS_PARM0);
2122 if (in == sv.edicts)
2123 PF_WARNING("copyentity: can not read world entity\n");
2125 PF_WARNING("copyentity: can not read free entity\n");
2126 out = G_EDICT(OFS_PARM1);
2127 if (out == sv.edicts)
2128 PF_WARNING("copyentity: can not modify world entity\n");
2130 PF_WARNING("copyentity: can not modify free entity\n");
2131 memcpy(out->v, in->v, progs->entityfields * 4);
2138 sets the color of a client and broadcasts the update to all connected clients
2140 setcolor(clientent, value)
2143 void PF_setcolor (void)
2149 entnum = G_EDICTNUM(OFS_PARM0);
2150 i = G_FLOAT(OFS_PARM1);
2152 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2154 Con_Print("tried to setcolor a non-client\n");
2158 client = svs.clients + entnum-1;
2159 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2162 client->old_colors = i;
2163 client->edict->v->team = (i & 15) + 1;
2165 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2166 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2167 MSG_WriteByte (&sv.reliable_datagram, i);
2174 effect(origin, modelname, startframe, framecount, framerate)
2177 void PF_effect (void)
2180 s = G_STRING(OFS_PARM1);
2182 PF_WARNING("effect: no model specified\n");
2184 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2187 void PF_te_blood (void)
2189 if (G_FLOAT(OFS_PARM2) < 1)
2191 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2192 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2194 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2195 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2196 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2198 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2199 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2200 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2202 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2205 void PF_te_bloodshower (void)
2207 if (G_FLOAT(OFS_PARM3) < 1)
2209 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2210 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2212 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2213 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2214 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2217 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2218 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2220 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2222 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2225 void PF_te_explosionrgb (void)
2227 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2228 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2230 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2231 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2232 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2234 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2235 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2236 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2239 void PF_te_particlecube (void)
2241 if (G_FLOAT(OFS_PARM3) < 1)
2243 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2244 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2246 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2247 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2248 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2250 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2251 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2252 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2255 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2256 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2258 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2260 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2261 // gravity true/false
2262 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2264 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2267 void PF_te_particlerain (void)
2269 if (G_FLOAT(OFS_PARM3) < 1)
2271 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2272 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2274 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2275 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2279 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2284 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2286 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2288 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2291 void PF_te_particlesnow (void)
2293 if (G_FLOAT(OFS_PARM3) < 1)
2295 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2296 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2298 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2299 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2300 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2304 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2306 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2307 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2308 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2310 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2312 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2315 void PF_te_spark (void)
2317 if (G_FLOAT(OFS_PARM2) < 1)
2319 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2320 MSG_WriteByte(&sv.datagram, TE_SPARK);
2322 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2323 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2324 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2326 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2327 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2328 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2330 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2333 void PF_te_gunshotquad (void)
2335 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2336 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2338 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2339 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2340 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2343 void PF_te_spikequad (void)
2345 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2346 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2348 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2349 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2350 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2353 void PF_te_superspikequad (void)
2355 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2356 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2358 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2359 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2360 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2363 void PF_te_explosionquad (void)
2365 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2366 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2368 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2369 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2370 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2373 void PF_te_smallflash (void)
2375 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2376 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2378 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2379 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2380 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2383 void PF_te_customflash (void)
2385 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2387 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2388 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2390 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2391 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2392 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2394 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2396 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2398 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2399 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2400 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2403 void PF_te_gunshot (void)
2405 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2406 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2408 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2409 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2410 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2413 void PF_te_spike (void)
2415 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2416 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2418 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2419 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2420 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2423 void PF_te_superspike (void)
2425 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2426 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2428 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2429 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2430 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2433 void PF_te_explosion (void)
2435 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2436 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2438 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2439 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2440 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2443 void PF_te_tarexplosion (void)
2445 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2446 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2448 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2449 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2450 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2453 void PF_te_wizspike (void)
2455 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2456 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2458 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2459 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2460 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2463 void PF_te_knightspike (void)
2465 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2466 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2468 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2469 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2470 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2473 void PF_te_lavasplash (void)
2475 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2476 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2478 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2479 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2480 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2483 void PF_te_teleport (void)
2485 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2486 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2488 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2489 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2490 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2493 void PF_te_explosion2 (void)
2495 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2496 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2498 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2499 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2500 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2502 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2505 void PF_te_lightning1 (void)
2507 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2508 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2510 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2513 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2518 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2521 void PF_te_lightning2 (void)
2523 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2524 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2526 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2528 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2529 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2533 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2534 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2537 void PF_te_lightning3 (void)
2539 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2540 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2542 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2544 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2545 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2548 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2549 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2550 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2553 void PF_te_beam (void)
2555 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2556 MSG_WriteByte(&sv.datagram, TE_BEAM);
2558 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2560 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2561 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2562 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2564 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2565 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2566 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2569 void PF_te_plasmaburn (void)
2571 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2572 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2573 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2574 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2575 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2578 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2581 vec3_t v1, clipplanenormal, normal;
2582 vec_t clipplanedist, clipdist;
2584 if (surf->flags & SURF_PLANEBACK)
2585 VectorNegate(surf->plane->normal, normal);
2587 VectorCopy(surf->plane->normal, normal);
2588 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2590 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2591 VectorNormalizeFast(v1);
2592 CrossProduct(v1, normal, clipplanenormal);
2593 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2594 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2597 clipdist = -clipdist;
2598 VectorMA(out, clipdist, clipplanenormal, out);
2603 static msurface_t *getsurface(edict_t *ed, int surfnum)
2607 if (!ed || ed->e->free)
2609 modelindex = ed->v->modelindex;
2610 if (modelindex < 1 || modelindex >= MAX_MODELS)
2612 model = sv.models[modelindex];
2613 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2615 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2619 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2620 void PF_getsurfacenumpoints(void)
2623 // return 0 if no such surface
2624 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2626 G_FLOAT(OFS_RETURN) = 0;
2630 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2632 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2633 void PF_getsurfacepoint(void)
2638 VectorClear(G_VECTOR(OFS_RETURN));
2639 ed = G_EDICT(OFS_PARM0);
2640 if (!ed || ed->e->free)
2642 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2644 pointnum = G_FLOAT(OFS_PARM2);
2645 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2647 // FIXME: implement rotation/scaling
2648 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2650 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2651 void PF_getsurfacenormal(void)
2654 VectorClear(G_VECTOR(OFS_RETURN));
2655 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2657 // FIXME: implement rotation/scaling
2658 if (surf->flags & SURF_PLANEBACK)
2659 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2661 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2663 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2664 void PF_getsurfacetexture(void)
2667 G_INT(OFS_RETURN) = 0;
2668 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2670 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2672 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2673 void PF_getsurfacenearpoint(void)
2675 int surfnum, best, modelindex;
2677 vec_t dist, bestdist;
2682 G_FLOAT(OFS_RETURN) = -1;
2683 ed = G_EDICT(OFS_PARM0);
2684 point = G_VECTOR(OFS_PARM1);
2686 if (!ed || ed->e->free)
2688 modelindex = ed->v->modelindex;
2689 if (modelindex < 1 || modelindex >= MAX_MODELS)
2691 model = sv.models[modelindex];
2692 if (!model->brushq1.numsurfaces)
2695 // FIXME: implement rotation/scaling
2696 VectorSubtract(point, ed->v->origin, p);
2698 bestdist = 1000000000;
2699 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2701 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2702 dist = PlaneDiff(p, surf->plane);
2704 if (dist < bestdist)
2706 clippointtosurface(surf, p, clipped);
2707 VectorSubtract(clipped, p, clipped);
2708 dist += DotProduct(clipped, clipped);
2709 if (dist < bestdist)
2716 G_FLOAT(OFS_RETURN) = best;
2718 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2719 void PF_getsurfaceclippedpoint(void)
2724 VectorClear(G_VECTOR(OFS_RETURN));
2725 ed = G_EDICT(OFS_PARM0);
2726 if (!ed || ed->e->free)
2728 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2730 // FIXME: implement rotation/scaling
2731 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2732 clippointtosurface(surf, p, out);
2733 // FIXME: implement rotation/scaling
2734 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2737 #define MAX_PRFILES 256
2739 qfile_t *pr_files[MAX_PRFILES];
2741 void PR_Files_Init(void)
2743 memset(pr_files, 0, sizeof(pr_files));
2746 void PR_Files_CloseAll(void)
2749 for (i = 0;i < MAX_PRFILES;i++)
2752 FS_Close(pr_files[i]);
2757 //float(string s) stof = #81; // get numerical value from a string
2760 char string[STRINGTEMP_LENGTH];
2761 PF_VarString(0, string, sizeof(string));
2762 G_FLOAT(OFS_RETURN) = atof(string);
2765 //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
2769 char *modestring, *filename;
2770 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2771 if (pr_files[filenum] == NULL)
2773 if (filenum >= MAX_PRFILES)
2775 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2776 G_FLOAT(OFS_RETURN) = -2;
2779 mode = G_FLOAT(OFS_PARM1);
2782 case 0: // FILE_READ
2785 case 1: // FILE_APPEND
2788 case 2: // FILE_WRITE
2792 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2793 G_FLOAT(OFS_RETURN) = -3;
2796 filename = G_STRING(OFS_PARM0);
2797 // .. is parent directory on many platforms
2798 // / is parent directory on Amiga
2799 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2800 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2801 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2803 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2804 G_FLOAT(OFS_RETURN) = -4;
2807 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2808 if (pr_files[filenum] == NULL)
2809 G_FLOAT(OFS_RETURN) = -1;
2811 G_FLOAT(OFS_RETURN) = filenum;
2814 //void(float fhandle) fclose = #111; // closes a file
2815 void PF_fclose(void)
2817 int filenum = G_FLOAT(OFS_PARM0);
2818 if (filenum < 0 || filenum >= MAX_PRFILES)
2820 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2823 if (pr_files[filenum] == NULL)
2825 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2828 FS_Close(pr_files[filenum]);
2829 pr_files[filenum] = NULL;
2832 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2836 static char string[STRINGTEMP_LENGTH];
2837 int filenum = G_FLOAT(OFS_PARM0);
2838 if (filenum < 0 || filenum >= MAX_PRFILES)
2840 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2843 if (pr_files[filenum] == NULL)
2845 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2851 c = FS_Getc(pr_files[filenum]);
2852 if (c == '\r' || c == '\n' || c < 0)
2854 if (end < STRINGTEMP_LENGTH - 1)
2858 // remove \n following \r
2860 c = FS_Getc(pr_files[filenum]);
2861 if (developer.integer)
2862 Con_Printf("fgets: %s\n", string);
2864 G_INT(OFS_RETURN) = PR_SetString(string);
2866 G_INT(OFS_RETURN) = 0;
2869 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2873 char string[STRINGTEMP_LENGTH];
2874 int filenum = G_FLOAT(OFS_PARM0);
2875 if (filenum < 0 || filenum >= MAX_PRFILES)
2877 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2880 if (pr_files[filenum] == NULL)
2882 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2885 PF_VarString(1, string, sizeof(string));
2886 if ((stringlength = strlen(string)))
2887 FS_Write(pr_files[filenum], string, stringlength);
2888 if (developer.integer)
2889 Con_Printf("fputs: %s\n", string);
2892 //float(string s) strlen = #114; // returns how many characters are in a string
2893 void PF_strlen(void)
2896 s = G_STRING(OFS_PARM0);
2898 G_FLOAT(OFS_RETURN) = strlen(s);
2900 G_FLOAT(OFS_RETURN) = 0;
2903 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2904 void PF_strcat(void)
2906 char *s = PR_GetTempString();
2907 PF_VarString(0, s, STRINGTEMP_LENGTH);
2908 G_INT(OFS_RETURN) = PR_SetString(s);
2911 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2912 void PF_substring(void)
2914 int i, start, length;
2915 char *s, *string = PR_GetTempString();
2916 s = G_STRING(OFS_PARM0);
2917 start = G_FLOAT(OFS_PARM1);
2918 length = G_FLOAT(OFS_PARM2);
2921 for (i = 0;i < start && *s;i++, s++);
2922 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2925 G_INT(OFS_RETURN) = PR_SetString(string);
2928 //vector(string s) stov = #117; // returns vector value from a string
2931 char string[STRINGTEMP_LENGTH];
2932 PF_VarString(0, string, sizeof(string));
2933 Math_atov(string, G_VECTOR(OFS_RETURN));
2936 //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)
2937 void PF_strzone(void)
2940 in = G_STRING(OFS_PARM0);
2941 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2943 G_INT(OFS_RETURN) = PR_SetString(out);
2946 //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!!!)
2947 void PF_strunzone(void)
2949 Mem_Free(G_STRING(OFS_PARM0));
2952 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2953 //this function originally written by KrimZon, made shorter by LordHavoc
2954 void PF_clientcommand (void)
2956 client_t *temp_client;
2959 //find client for this entity
2960 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2961 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2963 Con_Print("PF_clientcommand: entity is not a client\n");
2967 temp_client = host_client;
2968 host_client = svs.clients + i;
2969 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2970 host_client = temp_client;
2973 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2974 //this function originally written by KrimZon, made shorter by LordHavoc
2975 //20040203: rewritten by LordHavoc (no longer uses allocations)
2977 char *tokens[256], tokenbuf[4096];
2978 void PF_tokenize (void)
2982 p = G_STRING(OFS_PARM0);
2986 while(COM_ParseToken(&p, false))
2988 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
2990 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
2992 tokens[num_tokens++] = tokenbuf + pos;
2993 strcpy(tokenbuf + pos, com_token);
2994 pos += strlen(com_token) + 1;
2997 G_FLOAT(OFS_RETURN) = num_tokens;
3000 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3001 //this function originally written by KrimZon, made shorter by LordHavoc
3004 int token_num = G_FLOAT(OFS_PARM0);
3005 if (token_num >= 0 && token_num < num_tokens)
3006 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3008 G_INT(OFS_RETURN) = PR_SetString("");
3011 //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)
3012 void PF_setattachment (void)
3014 edict_t *e = G_EDICT(OFS_PARM0);
3015 edict_t *tagentity = G_EDICT(OFS_PARM1);
3016 char *tagname = G_STRING(OFS_PARM2);
3022 PF_WARNING("setattachment: can not modify world entity\n");
3024 PF_WARNING("setattachment: can not modify free entity\n");
3026 if (tagentity == NULL)
3027 tagentity = sv.edicts;
3029 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3031 v->edict = EDICT_TO_PROG(tagentity);
3033 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3036 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3038 modelindex = (int)tagentity->v->modelindex;
3039 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3041 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3042 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3043 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3045 if (v->_float == 0 && model->alias.aliasnum_tags)
3046 for (i = 0;i < model->alias.aliasnum_tags;i++)
3047 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3050 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);
3053 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));
3058 /////////////////////////////////////////
3059 // DP_QC_FS_SEARCH extension
3061 // qc fs search handling
3062 #define MAX_SEARCHES 128
3064 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3066 void PR_Search_Init(void)
3068 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3071 void PR_Search_Reset(void)
3074 // reset the fssearch list
3075 for(i = 0; i < MAX_SEARCHES; i++)
3076 if(pr_fssearchlist[i])
3077 FS_FreeSearch(pr_fssearchlist[i]);
3078 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3085 float search_begin(string pattern, float caseinsensitive, float quiet)
3088 void PF_search_begin(void)
3092 int caseinsens, quiet;
3094 pattern = G_STRING(OFS_PARM0);
3096 PR_CheckEmptyString(pattern);
3098 caseinsens = G_FLOAT(OFS_PARM1);
3099 quiet = G_FLOAT(OFS_PARM2);
3101 for(handle = 0; handle < MAX_SEARCHES; handle++)
3102 if(!pr_fssearchlist[handle])
3105 if(handle >= MAX_SEARCHES)
3107 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3108 G_FLOAT(OFS_RETURN) = -2;
3112 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3113 G_FLOAT(OFS_RETURN) = -1;
3115 G_FLOAT(OFS_RETURN) = handle;
3122 void search_end(float handle)
3125 void PF_search_end(void)
3129 handle = G_FLOAT(OFS_PARM0);
3131 if(handle < 0 || handle >= MAX_SEARCHES)
3133 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3136 if(pr_fssearchlist[handle] == NULL)
3138 Con_Printf("PF_search_end: no such handle %i\n", handle);
3142 FS_FreeSearch(pr_fssearchlist[handle]);
3143 pr_fssearchlist[handle] = NULL;
3150 float search_getsize(float handle)
3153 void PF_search_getsize(void)
3157 handle = G_FLOAT(OFS_PARM0);
3159 if(handle < 0 || handle >= MAX_SEARCHES)
3161 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3164 if(pr_fssearchlist[handle] == NULL)
3166 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3170 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3175 VM_search_getfilename
3177 string search_getfilename(float handle, float num)
3180 void PF_search_getfilename(void)
3182 int handle, filenum;
3185 handle = G_FLOAT(OFS_PARM0);
3186 filenum = G_FLOAT(OFS_PARM1);
3188 if(handle < 0 || handle >= MAX_SEARCHES)
3190 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3193 if(pr_fssearchlist[handle] == NULL)
3195 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3198 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3200 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3204 tmp = PR_GetTempString();
3205 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3207 G_INT(OFS_RETURN) = PR_SetString(tmp);
3210 void PF_cvar_string (void)
3216 str = G_STRING(OFS_PARM0);
3217 var = Cvar_FindVar (str);
3219 tmp = PR_GetTempString();
3220 strcpy(tmp, var->string);
3222 G_INT(OFS_RETURN) = PR_SetString(tmp);
3227 builtin_t pr_builtin[] =
3230 PF_makevectors, // #1 void(entity e) makevectors
3231 PF_setorigin, // #2 void(entity e, vector o) setorigin
3232 PF_setmodel, // #3 void(entity e, string m) setmodel
3233 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3234 NULL, // #5 void(entity e, vector min, vector max) setabssize
3235 PF_break, // #6 void() break
3236 PF_random, // #7 float() random
3237 PF_sound, // #8 void(entity e, float chan, string samp) sound
3238 PF_normalize, // #9 vector(vector v) normalize
3239 PF_error, // #10 void(string e) error
3240 PF_objerror, // #11 void(string e) objerror
3241 PF_vlen, // #12 float(vector v) vlen
3242 PF_vectoyaw, // #13 float(vector v) vectoyaw
3243 PF_Spawn, // #14 entity() spawn
3244 PF_Remove, // #15 void(entity e) remove
3245 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3246 PF_checkclient, // #17 entity() clientlist
3247 PF_Find, // #18 entity(entity start, .string fld, string match) find
3248 PF_precache_sound, // #19 void(string s) precache_sound
3249 PF_precache_model, // #20 void(string s) precache_model
3250 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3251 PF_findradius, // #22 entity(vector org, float rad) findradius
3252 PF_bprint, // #23 void(string s) bprint
3253 PF_sprint, // #24 void(entity client, string s) sprint
3254 PF_dprint, // #25 void(string s) dprint
3255 PF_ftos, // #26 void(string s) ftos
3256 PF_vtos, // #27 void(string s) vtos
3257 PF_coredump, // #28 void() coredump
3258 PF_traceon, // #29 void() traceon
3259 PF_traceoff, // #30 void() traceoff
3260 PF_eprint, // #31 void(entity e) eprint
3261 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3263 PF_droptofloor, // #34 float() droptofloor
3264 PF_lightstyle, // #35 void(float style, string value) lightstyle
3265 PF_rint, // #36 float(float v) rint
3266 PF_floor, // #37 float(float v) floor
3267 PF_ceil, // #38 float(float v) ceil
3269 PF_checkbottom, // #40 float(entity e) checkbottom
3270 PF_pointcontents , // #41 float(vector v) pointcontents
3272 PF_fabs, // #43 float(float f) fabs
3273 PF_aim, // #44 vector(entity e, float speed) aim
3274 PF_cvar, // #45 float(string s) cvar
3275 PF_localcmd, // #46 void(string s) localcmd
3276 PF_nextent, // #47 entity(entity e) nextent
3277 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3278 PF_changeyaw, // #49 void() ChangeYaw
3280 PF_vectoangles, // #51 vector(vector v) vectoangles
3281 PF_WriteByte, // #52 void(float to, float f) WriteByte
3282 PF_WriteChar, // #53 void(float to, float f) WriteChar
3283 PF_WriteShort, // #54 void(float to, float f) WriteShort
3284 PF_WriteLong, // #55 void(float to, float f) WriteLong
3285 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3286 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3287 PF_WriteString, // #58 void(float to, string s) WriteString
3288 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3289 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3290 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3291 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3292 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3293 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3294 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3296 SV_MoveToGoal, // #67 void(float step) movetogoal
3297 PF_precache_file, // #68 string(string s) precache_file
3298 PF_makestatic, // #69 void(entity e) makestatic
3299 PF_changelevel, // #70 void(string s) changelevel
3301 PF_cvar_set, // #72 void(string var, string val) cvar_set
3302 PF_centerprint, // #73 void(entity client, strings) centerprint
3303 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3304 PF_precache_model, // #75 string(string s) precache_model2
3305 PF_precache_sound, // #76 string(string s) precache_sound2
3306 PF_precache_file, // #77 string(string s) precache_file2
3307 PF_setspawnparms, // #78 void(entity e) setspawnparms
3310 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3319 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3320 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3321 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3322 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3323 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3324 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3325 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3326 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3327 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3328 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3339 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3340 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3341 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3342 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3343 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3344 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3345 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3346 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3347 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3348 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3349 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3350 a a a a a a a a // #120-199
3351 a a a a a a a a a a // #200-299
3352 a a a a a a a a a a // #300-399
3353 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3354 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3355 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3356 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3357 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3358 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3359 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3360 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3361 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3362 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3363 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3364 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3365 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3366 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3367 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3368 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3369 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3370 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3371 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3372 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3373 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3374 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3375 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3376 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3377 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3378 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3379 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3380 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3381 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3382 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3383 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3384 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3385 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3386 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3387 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3388 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3389 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3390 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3391 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3392 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3393 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3394 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3395 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3396 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3397 PF_search_begin, // #444
3398 PF_search_end, // #445
3399 PF_search_getsize, // #446
3400 PF_search_getfilename, // #447
3401 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3403 a a a a a // #450-499 (LordHavoc)
3406 builtin_t *pr_builtins = pr_builtin;
3407 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3409 void PR_Cmd_Init(void)
3411 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3416 void PR_Cmd_Reset(void)
3418 Mem_EmptyPool(pr_strings_mempool);
3420 PR_Files_CloseAll();