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 "
101 "DP_MOVETYPEBOUNCEMISSILE "
108 "DP_QC_FINDCHAINFLAGS "
109 "DP_QC_FINDCHAINFLOAT "
112 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
116 "DP_QC_MULTIPLETEMPSTRINGS "
118 "DP_QC_SINCOSSQRTPOW "
121 "DP_QC_TRACE_MOVETYPE_HITMODEL "
122 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
123 "DP_QC_VECTORVECTORS "
127 "DP_SND_DIRECTIONLESSATTNNONE "
132 "DP_SV_DRAWONLYTOCLIENT "
134 "DP_SV_EXTERIORMODELTOCLIENT "
135 "DP_SV_NODRAWTOCLIENT "
136 "DP_SV_PLAYERPHYSICS "
137 "DP_SV_ROTATINGBMODEL "
143 "DP_TE_EXPLOSIONRGB "
145 "DP_TE_PARTICLECUBE "
146 "DP_TE_PARTICLERAIN "
147 "DP_TE_PARTICLESNOW "
149 "DP_TE_QUADEFFECTS1 "
152 "DP_TE_STANDARDEFFECTBUILTINS "
155 "KRIMZON_SV_PARSECLIENTCOMMAND "
159 "TENEBRAE_GFX_DLIGHTS "
163 qboolean checkextension(char *name)
168 for (e = ENGINE_EXTENSIONS;*e;e++)
175 while (*e && *e != ' ')
177 if (e - start == len)
178 if (!strncasecmp(start, name, len))
188 returns true if the extension is supported by the server
190 checkextension(extensionname)
193 void PF_checkextension (void)
195 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
202 This is a TERMINAL error, which will kill off the entire server.
211 char string[STRINGTEMP_LENGTH];
213 PF_VarString(0, string, sizeof(string));
214 Con_Printf("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
215 ed = PROG_TO_EDICT(pr_global_struct->self);
218 PF_ERROR("Program error");
225 Dumps out self, then an error message. The program is aborted and self is
226 removed, but the level can continue.
231 void PF_objerror (void)
234 char string[STRINGTEMP_LENGTH];
236 PF_VarString(0, string, sizeof(string));
237 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
238 ed = PROG_TO_EDICT(pr_global_struct->self);
248 Writes new values for v_forward, v_up, and v_right based on angles
252 void PF_makevectors (void)
254 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
261 Writes new values for v_forward, v_up, and v_right based on the given forward vector
262 vectorvectors(vector, vector)
265 void PF_vectorvectors (void)
267 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
268 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
275 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.
277 setorigin (entity, origin)
280 void PF_setorigin (void)
285 e = G_EDICT(OFS_PARM0);
287 PF_WARNING("setorigin: can not modify world entity\n");
289 PF_WARNING("setorigin: can not modify free entity\n");
290 org = G_VECTOR(OFS_PARM1);
291 VectorCopy (org, e->v->origin);
292 SV_LinkEdict (e, false);
296 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
300 for (i=0 ; i<3 ; i++)
302 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
304 // set derived values
305 VectorCopy (min, e->v->mins);
306 VectorCopy (max, e->v->maxs);
307 VectorSubtract (max, min, e->v->size);
309 SV_LinkEdict (e, false);
316 the size box is rotated by the current angle
317 LordHavoc: no it isn't...
319 setsize (entity, minvector, maxvector)
322 void PF_setsize (void)
327 e = G_EDICT(OFS_PARM0);
329 PF_WARNING("setsize: can not modify world entity\n");
331 PF_WARNING("setsize: can not modify free entity\n");
332 min = G_VECTOR(OFS_PARM1);
333 max = G_VECTOR(OFS_PARM2);
334 SetMinMaxSize (e, min, max, false);
342 setmodel(entity, model)
345 void PF_setmodel (void)
352 e = G_EDICT(OFS_PARM0);
354 PF_WARNING("setmodel: can not modify world entity\n");
356 PF_WARNING("setmodel: can not modify free entity\n");
357 m = G_STRING(OFS_PARM1);
359 // check to see if model was properly precached
360 for (i=0, check = sv.model_precache ; *check ; i++, check++)
361 if (!strcmp(*check, m))
365 PF_WARNING(va("setmodel: no precache for model \"%s\"\n", m));
368 e->v->model = PR_SetString(*check);
369 e->v->modelindex = i;
371 mod = sv.models[ (int)e->v->modelindex];
374 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
376 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
383 broadcast print to everyone on server
388 void PF_bprint (void)
390 char string[STRINGTEMP_LENGTH];
391 PF_VarString(0, string, sizeof(string));
392 SV_BroadcastPrint(string);
399 single print to a specific client
401 sprint(clientent, value)
404 void PF_sprint (void)
408 char string[STRINGTEMP_LENGTH];
410 entnum = G_EDICTNUM(OFS_PARM0);
412 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
414 Con_Print("tried to sprint to a non-client\n");
418 client = svs.clients + entnum-1;
419 if (!client->netconnection)
421 PF_VarString(1, string, sizeof(string));
422 MSG_WriteChar(&client->message,svc_print);
423 MSG_WriteString(&client->message, string);
431 single print to a specific client
433 centerprint(clientent, value)
436 void PF_centerprint (void)
440 char string[STRINGTEMP_LENGTH];
442 entnum = G_EDICTNUM(OFS_PARM0);
444 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
446 Con_Print("tried to sprint to a non-client\n");
450 client = svs.clients + entnum-1;
451 if (!client->netconnection)
453 PF_VarString(1, string, sizeof(string));
454 MSG_WriteChar(&client->message,svc_centerprint);
455 MSG_WriteString(&client->message, string);
463 vector normalize(vector)
466 void PF_normalize (void)
472 value1 = G_VECTOR(OFS_PARM0);
474 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
478 newvalue[0] = newvalue[1] = newvalue[2] = 0;
482 newvalue[0] = value1[0] * new;
483 newvalue[1] = value1[1] * new;
484 newvalue[2] = value1[2] * new;
487 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
502 value1 = G_VECTOR(OFS_PARM0);
504 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
507 G_FLOAT(OFS_RETURN) = new;
514 float vectoyaw(vector)
517 void PF_vectoyaw (void)
522 value1 = G_VECTOR(OFS_PARM0);
524 if (value1[1] == 0 && value1[0] == 0)
528 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
533 G_FLOAT(OFS_RETURN) = yaw;
541 vector vectoangles(vector)
544 void PF_vectoangles (void)
546 double value1[3], forward, yaw, pitch;
548 VectorCopy(G_VECTOR(OFS_PARM0), value1);
550 if (value1[1] == 0 && value1[0] == 0)
560 // LordHavoc: optimized a bit
563 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
567 else if (value1[1] > 0)
572 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
573 pitch = (atan2(value1[2], forward) * 180 / M_PI);
578 VectorSet(G_VECTOR(OFS_RETURN), pitch, yaw, 0);
585 Returns a number from 0<= num < 1
590 void PF_random (void)
594 num = (rand ()&0x7fff) / ((float)0x7fff);
596 G_FLOAT(OFS_RETURN) = num;
603 particle(origin, color, count)
606 void PF_particle (void)
612 org = G_VECTOR(OFS_PARM0);
613 dir = G_VECTOR(OFS_PARM1);
614 color = G_FLOAT(OFS_PARM2);
615 count = G_FLOAT(OFS_PARM3);
616 SV_StartParticle (org, dir, color, count);
626 void PF_ambientsound (void)
631 float vol, attenuation;
634 pos = G_VECTOR (OFS_PARM0);
635 samp = G_STRING(OFS_PARM1);
636 vol = G_FLOAT(OFS_PARM2);
637 attenuation = G_FLOAT(OFS_PARM3);
639 // check to see if samp was properly precached
640 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
641 if (!strcmp(*check,samp))
646 Con_Printf("no precache: %s\n", samp);
654 // add an svc_spawnambient command to the level signon packet
657 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
659 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
661 MSG_WriteVector(&sv.signon, pos, sv.protocol);
664 MSG_WriteShort (&sv.signon, soundnum);
666 MSG_WriteByte (&sv.signon, soundnum);
668 MSG_WriteByte (&sv.signon, vol*255);
669 MSG_WriteByte (&sv.signon, attenuation*64);
677 Each entity can have eight independant sound sources, like voice,
680 Channel 0 is an auto-allocate channel, the others override anything
681 already running on that entity/channel pair.
683 An attenuation of 0 will play full volume everywhere in the level.
684 Larger attenuations will drop off.
696 entity = G_EDICT(OFS_PARM0);
697 channel = G_FLOAT(OFS_PARM1);
698 sample = G_STRING(OFS_PARM2);
699 volume = G_FLOAT(OFS_PARM3) * 255;
700 attenuation = G_FLOAT(OFS_PARM4);
702 if (volume < 0 || volume > 255)
703 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
705 if (attenuation < 0 || attenuation > 4)
706 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
708 if (channel < 0 || channel > 7)
709 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
711 SV_StartSound (entity, channel, sample, volume, attenuation);
723 PF_ERROR("break: break statement\n");
730 Used for use tracing and shot targeting
731 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
732 if the tryents flag is set.
734 traceline (vector1, vector2, tryents)
737 void PF_traceline (void)
744 pr_xfunction->builtinsprofile += 30;
746 v1 = G_VECTOR(OFS_PARM0);
747 v2 = G_VECTOR(OFS_PARM1);
748 move = G_FLOAT(OFS_PARM2);
749 ent = G_EDICT(OFS_PARM3);
751 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
753 pr_global_struct->trace_allsolid = trace.allsolid;
754 pr_global_struct->trace_startsolid = trace.startsolid;
755 pr_global_struct->trace_fraction = trace.fraction;
756 pr_global_struct->trace_inwater = trace.inwater;
757 pr_global_struct->trace_inopen = trace.inopen;
758 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
759 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
760 pr_global_struct->trace_plane_dist = trace.plane.dist;
762 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
764 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
765 // FIXME: add trace_endcontents
773 Used for use tracing and shot targeting
774 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
775 if the tryents flag is set.
777 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
780 // LordHavoc: added this for my own use, VERY useful, similar to traceline
781 void PF_tracebox (void)
783 float *v1, *v2, *m1, *m2;
788 pr_xfunction->builtinsprofile += 30;
790 v1 = G_VECTOR(OFS_PARM0);
791 m1 = G_VECTOR(OFS_PARM1);
792 m2 = G_VECTOR(OFS_PARM2);
793 v2 = G_VECTOR(OFS_PARM3);
794 move = G_FLOAT(OFS_PARM4);
795 ent = G_EDICT(OFS_PARM5);
797 trace = SV_Move (v1, m1, m2, v2, move, ent);
799 pr_global_struct->trace_allsolid = trace.allsolid;
800 pr_global_struct->trace_startsolid = trace.startsolid;
801 pr_global_struct->trace_fraction = trace.fraction;
802 pr_global_struct->trace_inwater = trace.inwater;
803 pr_global_struct->trace_inopen = trace.inopen;
804 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
805 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
806 pr_global_struct->trace_plane_dist = trace.plane.dist;
808 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
810 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
813 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
814 void PF_TraceToss (void)
820 pr_xfunction->builtinsprofile += 600;
822 ent = G_EDICT(OFS_PARM0);
823 if (ent == sv.edicts)
824 PF_WARNING("tracetoss: can not use world entity\n");
825 ignore = G_EDICT(OFS_PARM1);
827 trace = SV_Trace_Toss (ent, ignore);
829 pr_global_struct->trace_allsolid = trace.allsolid;
830 pr_global_struct->trace_startsolid = trace.startsolid;
831 pr_global_struct->trace_fraction = trace.fraction;
832 pr_global_struct->trace_inwater = trace.inwater;
833 pr_global_struct->trace_inopen = trace.inopen;
834 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
835 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
836 pr_global_struct->trace_plane_dist = trace.plane.dist;
838 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
840 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
848 Returns true if the given entity can move to the given position from it's
849 current position by walking or rolling.
851 scalar checkpos (entity, vector)
854 void PF_checkpos (void)
858 //============================================================================
861 qbyte checkpvs[MAX_MAP_LEAFS/8];
863 int PF_newcheckclient (int check)
869 // cycle to the next one
871 check = bound(1, check, svs.maxclients);
872 if (check == svs.maxclients)
880 pr_xfunction->builtinsprofile++;
882 if (i == svs.maxclients+1)
884 // look up the client's edict
886 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
887 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
889 // found a valid client (possibly the same one again)
893 // get the PVS for the entity
894 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
896 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
897 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
906 Returns a client (or object that has a client enemy) that would be a
909 If there is more than one valid option, they are cycled each frame
911 If (self.origin + self.viewofs) is not in the PVS of the current target,
912 it is not returned at all.
917 int c_invis, c_notvis;
918 void PF_checkclient (void)
923 // find a new check if on a new frame
924 if (sv.time - sv.lastchecktime >= 0.1)
926 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
927 sv.lastchecktime = sv.time;
930 // return check if it might be visible
931 ent = EDICT_NUM(sv.lastcheck);
932 if (ent->e->free || ent->v->health <= 0)
934 RETURN_EDICT(sv.edicts);
938 // if current entity can't possibly see the check entity, return 0
939 self = PROG_TO_EDICT(pr_global_struct->self);
940 VectorAdd(self->v->origin, self->v->view_ofs, view);
941 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
944 RETURN_EDICT(sv.edicts);
948 // might be able to see it
953 //============================================================================
960 Sends text over to the client's execution buffer
962 stuffcmd (clientent, value)
965 void PF_stuffcmd (void)
971 entnum = G_EDICTNUM(OFS_PARM0);
972 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
974 Con_Print("Can't stuffcmd to a non-client\n");
977 str = G_STRING(OFS_PARM1);
980 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
981 Host_ClientCommands ("%s", str);
989 Sends text to server console
994 void PF_localcmd (void)
996 Cbuf_AddText(G_STRING(OFS_PARM0));
1008 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1018 void PF_cvar_set (void)
1020 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1027 Returns a chain of entities that have origins within a spherical area
1029 findradius (origin, radius)
1032 void PF_findradius (void)
1034 edict_t *ent, *chain;
1035 vec_t radius, radius2;
1036 vec3_t org, eorg, mins, maxs;
1039 edict_t *touchedicts[MAX_EDICTS];
1041 chain = (edict_t *)sv.edicts;
1043 VectorCopy(G_VECTOR(OFS_PARM0), org);
1044 radius = G_FLOAT(OFS_PARM1);
1045 radius2 = radius * radius;
1047 mins[0] = org[0] - radius;
1048 mins[1] = org[1] - radius;
1049 mins[2] = org[2] - radius;
1050 maxs[0] = org[0] + radius;
1051 maxs[1] = org[1] + radius;
1052 maxs[2] = org[2] + radius;
1053 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1054 if (numtouchedicts > MAX_EDICTS)
1056 // this never happens
1057 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1058 numtouchedicts = MAX_EDICTS;
1060 for (i = 0;i < numtouchedicts;i++)
1062 ent = touchedicts[i];
1063 pr_xfunction->builtinsprofile++;
1064 // LordHavoc: compare against bounding box rather than center so it
1065 // doesn't miss large objects, and use DotProduct instead of Length
1066 // for a major speedup
1067 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1068 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1069 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1070 if (DotProduct(eorg, eorg) < radius2)
1072 ent->v->chain = EDICT_TO_PROG(chain);
1077 RETURN_EDICT(chain);
1086 void PF_dprint (void)
1088 char string[STRINGTEMP_LENGTH];
1089 if (developer.integer)
1091 PF_VarString(0, string, sizeof(string));
1100 v = G_FLOAT(OFS_PARM0);
1102 s = PR_GetTempString();
1103 if ((float)((int)v) == v)
1104 sprintf(s, "%i", (int)v);
1106 sprintf(s, "%f", v);
1107 G_INT(OFS_RETURN) = PR_SetString(s);
1113 v = G_FLOAT(OFS_PARM0);
1114 G_FLOAT(OFS_RETURN) = fabs(v);
1120 s = PR_GetTempString();
1121 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1122 G_INT(OFS_RETURN) = PR_SetString(s);
1128 s = PR_GetTempString();
1129 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1130 G_INT(OFS_RETURN) = PR_SetString(s);
1133 void PF_Spawn (void)
1136 pr_xfunction->builtinsprofile += 20;
1141 void PF_Remove (void)
1144 pr_xfunction->builtinsprofile += 20;
1146 ed = G_EDICT(OFS_PARM0);
1147 if (ed == sv.edicts)
1148 PF_WARNING("remove: tried to remove world\n");
1149 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1150 PF_WARNING("remove: tried to remove a client\n");
1151 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1152 if (ed->e->free && developer.integer)
1153 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1158 // entity (entity start, .string field, string match) find = #5;
1166 e = G_EDICTNUM(OFS_PARM0);
1167 f = G_INT(OFS_PARM1);
1168 s = G_STRING(OFS_PARM2);
1171 RETURN_EDICT(sv.edicts);
1175 for (e++ ; e < sv.num_edicts ; e++)
1177 pr_xfunction->builtinsprofile++;
1191 RETURN_EDICT(sv.edicts);
1194 // LordHavoc: added this for searching float, int, and entity reference fields
1195 void PF_FindFloat (void)
1202 e = G_EDICTNUM(OFS_PARM0);
1203 f = G_INT(OFS_PARM1);
1204 s = G_FLOAT(OFS_PARM2);
1206 for (e++ ; e < sv.num_edicts ; e++)
1208 pr_xfunction->builtinsprofile++;
1212 if (E_FLOAT(ed,f) == s)
1219 RETURN_EDICT(sv.edicts);
1222 // chained search for strings in entity fields
1223 // entity(.string field, string match) findchain = #402;
1224 void PF_findchain (void)
1229 edict_t *ent, *chain;
1231 chain = (edict_t *)sv.edicts;
1233 f = G_INT(OFS_PARM0);
1234 s = G_STRING(OFS_PARM1);
1237 RETURN_EDICT(sv.edicts);
1241 ent = NEXT_EDICT(sv.edicts);
1242 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1244 pr_xfunction->builtinsprofile++;
1247 t = E_STRING(ent,f);
1253 ent->v->chain = EDICT_TO_PROG(chain);
1257 RETURN_EDICT(chain);
1260 // LordHavoc: chained search for float, int, and entity reference fields
1261 // entity(.string field, float match) findchainfloat = #403;
1262 void PF_findchainfloat (void)
1267 edict_t *ent, *chain;
1269 chain = (edict_t *)sv.edicts;
1271 f = G_INT(OFS_PARM0);
1272 s = G_FLOAT(OFS_PARM1);
1274 ent = NEXT_EDICT(sv.edicts);
1275 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1277 pr_xfunction->builtinsprofile++;
1280 if (E_FLOAT(ent,f) != s)
1283 ent->v->chain = EDICT_TO_PROG(chain);
1287 RETURN_EDICT(chain);
1290 // LordHavoc: search for flags in float fields
1291 void PF_findflags (void)
1298 e = G_EDICTNUM(OFS_PARM0);
1299 f = G_INT(OFS_PARM1);
1300 s = (int)G_FLOAT(OFS_PARM2);
1302 for (e++ ; e < sv.num_edicts ; e++)
1304 pr_xfunction->builtinsprofile++;
1308 if ((int)E_FLOAT(ed,f) & s)
1315 RETURN_EDICT(sv.edicts);
1318 // LordHavoc: chained search for flags in float fields
1319 void PF_findchainflags (void)
1324 edict_t *ent, *chain;
1326 chain = (edict_t *)sv.edicts;
1328 f = G_INT(OFS_PARM0);
1329 s = (int)G_FLOAT(OFS_PARM1);
1331 ent = NEXT_EDICT(sv.edicts);
1332 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1334 pr_xfunction->builtinsprofile++;
1337 if (!((int)E_FLOAT(ent,f) & s))
1340 ent->v->chain = EDICT_TO_PROG(chain);
1344 RETURN_EDICT(chain);
1347 void PR_CheckEmptyString (char *s)
1350 PF_ERROR("Bad string");
1353 void PF_precache_file (void)
1354 { // precache_file is only used to copy files with qcc, it does nothing
1355 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1358 void PF_precache_sound (void)
1362 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
1364 if (sv.state != ss_loading)
1365 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1367 s = G_STRING(OFS_PARM0);
1368 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1369 PR_CheckEmptyString (s);
1371 for (i=0 ; i<limit ; i++)
1373 if (!sv.sound_precache[i])
1375 sv.sound_precache[i] = s;
1378 if (!strcmp(sv.sound_precache[i], s))
1381 PF_ERROR("PF_precache_sound: overflow");
1384 void PF_precache_model (void)
1388 int limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
1390 if (sv.state != ss_loading)
1391 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1393 s = G_STRING(OFS_PARM0);
1394 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1396 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1397 PR_CheckEmptyString (s);
1399 for (i = 0;i < limit;i++)
1401 if (!sv.model_precache[i])
1403 sv.model_precache[i] = s;
1404 sv.models[i] = Mod_ForName (s, true, false, false);
1407 if (!strcmp(sv.model_precache[i], s))
1410 PF_ERROR("PF_precache_model: overflow");
1414 void PF_coredump (void)
1419 void PF_traceon (void)
1424 void PF_traceoff (void)
1429 void PF_eprint (void)
1431 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1438 float(float yaw, float dist) walkmove
1441 void PF_walkmove (void)
1449 // assume failure if it returns early
1450 G_FLOAT(OFS_RETURN) = 0;
1452 ent = PROG_TO_EDICT(pr_global_struct->self);
1453 if (ent == sv.edicts)
1454 PF_WARNING("walkmove: can not modify world entity\n");
1456 PF_WARNING("walkmove: can not modify free entity\n");
1457 yaw = G_FLOAT(OFS_PARM0);
1458 dist = G_FLOAT(OFS_PARM1);
1460 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1463 yaw = yaw*M_PI*2 / 360;
1465 move[0] = cos(yaw)*dist;
1466 move[1] = sin(yaw)*dist;
1469 // save program state, because SV_movestep may call other progs
1470 oldf = pr_xfunction;
1471 oldself = pr_global_struct->self;
1473 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1476 // restore program state
1477 pr_xfunction = oldf;
1478 pr_global_struct->self = oldself;
1488 void PF_droptofloor (void)
1494 // assume failure if it returns early
1495 G_FLOAT(OFS_RETURN) = 0;
1497 ent = PROG_TO_EDICT(pr_global_struct->self);
1498 if (ent == sv.edicts)
1499 PF_WARNING("droptofloor: can not modify world entity\n");
1501 PF_WARNING("droptofloor: can not modify free entity\n");
1503 VectorCopy (ent->v->origin, end);
1506 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1508 if (trace.fraction != 1)
1510 VectorCopy (trace.endpos, ent->v->origin);
1511 SV_LinkEdict (ent, false);
1512 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1513 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1514 G_FLOAT(OFS_RETURN) = 1;
1515 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1516 ent->e->suspendedinairflag = true;
1524 void(float style, string value) lightstyle
1527 void PF_lightstyle (void)
1534 style = G_FLOAT(OFS_PARM0);
1535 val = G_STRING(OFS_PARM1);
1537 // change the string in sv
1538 sv.lightstyles[style] = val;
1540 // send message to all clients on this server
1541 if (sv.state != ss_active)
1544 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1546 if (client->netconnection)
1548 MSG_WriteChar (&client->message, svc_lightstyle);
1549 MSG_WriteChar (&client->message,style);
1550 MSG_WriteString (&client->message, val);
1558 f = G_FLOAT(OFS_PARM0);
1560 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1562 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1564 void PF_floor (void)
1566 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1570 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1579 void PF_checkbottom (void)
1581 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1589 void PF_pointcontents (void)
1591 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1598 entity nextent(entity)
1601 void PF_nextent (void)
1606 i = G_EDICTNUM(OFS_PARM0);
1609 pr_xfunction->builtinsprofile++;
1611 if (i == sv.num_edicts)
1613 RETURN_EDICT(sv.edicts);
1629 Pick a vector for the player to shoot along
1630 vector aim(entity, missilespeed)
1635 edict_t *ent, *check, *bestent;
1636 vec3_t start, dir, end, bestdir;
1639 float dist, bestdist;
1642 // assume failure if it returns early
1643 VectorCopy(pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1644 // if sv_aim is so high it can't possibly accept anything, skip out early
1645 if (sv_aim.value >= 1)
1648 ent = G_EDICT(OFS_PARM0);
1649 if (ent == sv.edicts)
1650 PF_WARNING("aim: can not use world entity\n");
1652 PF_WARNING("aim: can not use free entity\n");
1653 speed = G_FLOAT(OFS_PARM1);
1655 VectorCopy (ent->v->origin, start);
1658 // try sending a trace straight
1659 VectorCopy (pr_global_struct->v_forward, dir);
1660 VectorMA (start, 2048, dir, end);
1661 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1662 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1663 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1665 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1670 // try all possible entities
1671 VectorCopy (dir, bestdir);
1672 bestdist = sv_aim.value;
1675 check = NEXT_EDICT(sv.edicts);
1676 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1678 pr_xfunction->builtinsprofile++;
1679 if (check->v->takedamage != DAMAGE_AIM)
1683 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1684 continue; // don't aim at teammate
1685 for (j=0 ; j<3 ; j++)
1686 end[j] = check->v->origin[j]
1687 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1688 VectorSubtract (end, start, dir);
1689 VectorNormalize (dir);
1690 dist = DotProduct (dir, pr_global_struct->v_forward);
1691 if (dist < bestdist)
1692 continue; // to far to turn
1693 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1694 if (tr.ent == check)
1695 { // can shoot at this one
1703 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1704 dist = DotProduct (dir, pr_global_struct->v_forward);
1705 VectorScale (pr_global_struct->v_forward, dist, end);
1707 VectorNormalize (end);
1708 VectorCopy (end, G_VECTOR(OFS_RETURN));
1712 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1720 This was a major timewaster in progs, so it was converted to C
1723 void PF_changeyaw (void)
1726 float ideal, current, move, speed;
1728 ent = PROG_TO_EDICT(pr_global_struct->self);
1729 if (ent == sv.edicts)
1730 PF_WARNING("changeyaw: can not modify world entity\n");
1732 PF_WARNING("changeyaw: can not modify free entity\n");
1733 current = ANGLEMOD(ent->v->angles[1]);
1734 ideal = ent->v->ideal_yaw;
1735 speed = ent->v->yaw_speed;
1737 if (current == ideal)
1739 move = ideal - current;
1740 if (ideal > current)
1761 ent->v->angles[1] = ANGLEMOD (current + move);
1769 void PF_changepitch (void)
1772 float ideal, current, move, speed;
1775 ent = G_EDICT(OFS_PARM0);
1776 if (ent == sv.edicts)
1777 PF_WARNING("changepitch: can not modify world entity\n");
1779 PF_WARNING("changepitch: can not modify free entity\n");
1780 current = ANGLEMOD( ent->v->angles[0] );
1781 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1782 ideal = val->_float;
1785 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1788 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1789 speed = val->_float;
1792 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1796 if (current == ideal)
1798 move = ideal - current;
1799 if (ideal > current)
1820 ent->v->angles[0] = ANGLEMOD (current + move);
1824 ===============================================================================
1828 ===============================================================================
1831 #define MSG_BROADCAST 0 // unreliable to all
1832 #define MSG_ONE 1 // reliable to one (msg_entity)
1833 #define MSG_ALL 2 // reliable to all
1834 #define MSG_INIT 3 // write to the init string
1836 sizebuf_t *WriteDest (void)
1842 dest = G_FLOAT(OFS_PARM0);
1846 return &sv.datagram;
1849 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1850 entnum = NUM_FOR_EDICT(ent);
1851 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1852 Host_Error("WriteDest: tried to write to non-client\n");
1853 return &svs.clients[entnum-1].message;
1856 return &sv.reliable_datagram;
1862 Host_Error("WriteDest: bad destination");
1869 void PF_WriteByte (void)
1871 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1874 void PF_WriteChar (void)
1876 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1879 void PF_WriteShort (void)
1881 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1884 void PF_WriteLong (void)
1886 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1889 void PF_WriteAngle (void)
1891 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1894 void PF_WriteCoord (void)
1896 MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1), sv.protocol);
1899 void PF_WriteString (void)
1901 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1905 void PF_WriteEntity (void)
1907 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1910 //=============================================================================
1912 void PF_makestatic (void)
1917 ent = G_EDICT(OFS_PARM0);
1918 if (ent == sv.edicts)
1919 PF_WARNING("makestatic: can not modify world entity\n");
1921 PF_WARNING("makestatic: can not modify free entity\n");
1924 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1929 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1930 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1931 MSG_WriteShort (&sv.signon, ent->v->frame);
1935 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1936 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1937 MSG_WriteByte (&sv.signon, ent->v->frame);
1940 MSG_WriteByte (&sv.signon, ent->v->colormap);
1941 MSG_WriteByte (&sv.signon, ent->v->skin);
1942 for (i=0 ; i<3 ; i++)
1944 MSG_WriteCoord(&sv.signon, ent->v->origin[i], sv.protocol);
1945 MSG_WriteAngle(&sv.signon, ent->v->angles[i], sv.protocol);
1948 // throw the entity away now
1952 //=============================================================================
1959 void PF_setspawnparms (void)
1965 ent = G_EDICT(OFS_PARM0);
1966 i = NUM_FOR_EDICT(ent);
1967 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1969 Con_Print("tried to setspawnparms on a non-client\n");
1973 // copy spawn parms out of the client_t
1974 client = svs.clients + i-1;
1975 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1976 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1984 void PF_changelevel (void)
1988 // make sure we don't issue two changelevels
1989 if (svs.changelevel_issued)
1991 svs.changelevel_issued = true;
1993 s = G_STRING(OFS_PARM0);
1994 Cbuf_AddText (va("changelevel %s\n",s));
1999 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
2004 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
2009 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
2016 Returns a vector of length < 1
2021 void PF_randomvec (void)
2026 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2027 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2028 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
2030 while (DotProduct(temp, temp) >= 1);
2031 VectorCopy (temp, G_VECTOR(OFS_RETURN));
2038 Returns a color vector indicating the lighting at the requested point.
2040 (Internal Operation note: actually measures the light beneath the point, just like
2041 the model lighting on the client)
2046 void PF_GetLight (void)
2048 vec3_t ambientcolor, diffusecolor, diffusenormal;
2050 p = G_VECTOR(OFS_PARM0);
2051 VectorClear(ambientcolor);
2052 VectorClear(diffusecolor);
2053 VectorClear(diffusenormal);
2054 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2055 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2056 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
2059 void PF_registercvar (void)
2062 name = G_STRING(OFS_PARM0);
2063 value = G_STRING(OFS_PARM1);
2064 G_FLOAT(OFS_RETURN) = 0;
2066 // first check to see if it has already been defined
2067 if (Cvar_FindVar (name))
2070 // check for overlap with a command
2071 if (Cmd_Exists (name))
2073 Con_Printf("PF_registercvar: %s is a command\n", name);
2077 Cvar_Get(name, value, 0);
2079 G_FLOAT(OFS_RETURN) = 1; // success
2086 returns the minimum of two supplied floats
2093 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2095 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2096 else if (pr_argc >= 3)
2099 float f = G_FLOAT(OFS_PARM0);
2100 for (i = 1;i < pr_argc;i++)
2101 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2102 f = G_FLOAT((OFS_PARM0+i*3));
2103 G_FLOAT(OFS_RETURN) = f;
2107 G_FLOAT(OFS_RETURN) = 0;
2108 PF_WARNING("min: must supply at least 2 floats\n");
2116 returns the maximum of two supplied floats
2123 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2125 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2126 else if (pr_argc >= 3)
2129 float f = G_FLOAT(OFS_PARM0);
2130 for (i = 1;i < pr_argc;i++)
2131 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2132 f = G_FLOAT((OFS_PARM0+i*3));
2133 G_FLOAT(OFS_RETURN) = f;
2137 G_FLOAT(OFS_RETURN) = 0;
2138 PF_WARNING("max: must supply at least 2 floats\n");
2146 returns number bounded by supplied range
2148 min(min, value, max)
2151 void PF_bound (void)
2153 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2160 returns a raised to power b
2167 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2174 copies data from one entity to another
2176 copyentity(src, dst)
2179 void PF_copyentity (void)
2182 in = G_EDICT(OFS_PARM0);
2183 if (in == sv.edicts)
2184 PF_WARNING("copyentity: can not read world entity\n");
2186 PF_WARNING("copyentity: can not read free entity\n");
2187 out = G_EDICT(OFS_PARM1);
2188 if (out == sv.edicts)
2189 PF_WARNING("copyentity: can not modify world entity\n");
2191 PF_WARNING("copyentity: can not modify free entity\n");
2192 memcpy(out->v, in->v, progs->entityfields * 4);
2199 sets the color of a client and broadcasts the update to all connected clients
2201 setcolor(clientent, value)
2204 void PF_setcolor (void)
2210 entnum = G_EDICTNUM(OFS_PARM0);
2211 i = G_FLOAT(OFS_PARM1);
2213 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2215 Con_Print("tried to setcolor a non-client\n");
2219 client = svs.clients + entnum-1;
2220 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2223 client->old_colors = i;
2224 client->edict->v->team = (i & 15) + 1;
2226 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2227 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2228 MSG_WriteByte (&sv.reliable_datagram, i);
2235 effect(origin, modelname, startframe, framecount, framerate)
2238 void PF_effect (void)
2242 s = G_STRING(OFS_PARM1);
2244 PF_WARNING("effect: no model specified\n");
2246 i = SV_ModelIndex(s);
2248 PF_WARNING("effect: model not precached\n");
2249 SV_StartEffect(G_VECTOR(OFS_PARM0), i, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2252 void PF_te_blood (void)
2254 if (G_FLOAT(OFS_PARM2) < 1)
2256 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2257 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2259 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2263 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2264 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2265 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2267 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2270 void PF_te_bloodshower (void)
2272 if (G_FLOAT(OFS_PARM3) < 1)
2274 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2275 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2277 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2278 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM2), sv.protocol);
2287 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2290 void PF_te_explosionrgb (void)
2292 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2293 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2295 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2296 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2297 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2299 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2300 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2301 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2304 void PF_te_particlecube (void)
2306 if (G_FLOAT(OFS_PARM3) < 1)
2308 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2309 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2311 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2317 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2319 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2320 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2321 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2323 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2325 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2326 // gravity true/false
2327 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2329 MSG_WriteCoord(&sv.datagram, G_FLOAT(OFS_PARM6), sv.protocol);
2332 void PF_te_particlerain (void)
2334 if (G_FLOAT(OFS_PARM3) < 1)
2336 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2337 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2339 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2341 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2343 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2344 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2345 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2347 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2348 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2349 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2351 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2353 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2356 void PF_te_particlesnow (void)
2358 if (G_FLOAT(OFS_PARM3) < 1)
2360 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2361 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2363 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2364 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2365 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2367 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2368 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2369 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2372 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2373 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2375 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2377 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2380 void PF_te_spark (void)
2382 if (G_FLOAT(OFS_PARM2) < 1)
2384 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2385 MSG_WriteByte(&sv.datagram, TE_SPARK);
2387 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2388 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2389 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2391 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2392 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2393 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2395 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2398 void PF_te_gunshotquad (void)
2400 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2401 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2403 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2404 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2405 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2408 void PF_te_spikequad (void)
2410 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2411 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2413 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2414 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2415 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2418 void PF_te_superspikequad (void)
2420 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2421 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2423 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2424 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2425 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2428 void PF_te_explosionquad (void)
2430 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2431 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2433 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2434 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2435 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2438 void PF_te_smallflash (void)
2440 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2441 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2443 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2444 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2445 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2448 void PF_te_customflash (void)
2450 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2452 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2453 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2455 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2456 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2457 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2459 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2461 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2463 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2464 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2465 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2468 void PF_te_gunshot (void)
2470 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2471 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2473 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2474 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2475 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2478 void PF_te_spike (void)
2480 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2481 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2483 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2484 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2485 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2488 void PF_te_superspike (void)
2490 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2491 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2493 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2494 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2495 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2498 void PF_te_explosion (void)
2500 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2501 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2503 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2504 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2505 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2508 void PF_te_tarexplosion (void)
2510 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2511 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2513 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2514 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2515 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2518 void PF_te_wizspike (void)
2520 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2521 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2523 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2524 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2525 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2528 void PF_te_knightspike (void)
2530 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2531 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2533 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2534 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2535 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2538 void PF_te_lavasplash (void)
2540 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2541 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2543 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2544 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2545 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2548 void PF_te_teleport (void)
2550 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2551 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2553 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2554 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2555 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2558 void PF_te_explosion2 (void)
2560 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2561 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2563 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2564 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2565 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2567 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2568 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM2));
2571 void PF_te_lightning1 (void)
2573 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2574 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2576 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2578 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2579 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2580 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2582 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2583 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2584 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2587 void PF_te_lightning2 (void)
2589 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2590 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2592 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2594 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2595 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2596 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2598 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2599 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2600 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2603 void PF_te_lightning3 (void)
2605 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2606 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2608 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2610 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2611 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2612 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2614 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2615 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2616 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2619 void PF_te_beam (void)
2621 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2622 MSG_WriteByte(&sv.datagram, TE_BEAM);
2624 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2626 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0], sv.protocol);
2627 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1], sv.protocol);
2628 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2], sv.protocol);
2630 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0], sv.protocol);
2631 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1], sv.protocol);
2632 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2], sv.protocol);
2635 void PF_te_plasmaburn (void)
2637 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2638 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2639 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0], sv.protocol);
2640 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1], sv.protocol);
2641 MSG_WriteCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2], sv.protocol);
2644 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2647 vec3_t v1, clipplanenormal, normal;
2648 vec_t clipplanedist, clipdist;
2650 if (surf->flags & SURF_PLANEBACK)
2651 VectorNegate(surf->plane->normal, normal);
2653 VectorCopy(surf->plane->normal, normal);
2654 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2656 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2657 VectorNormalizeFast(v1);
2658 CrossProduct(v1, normal, clipplanenormal);
2659 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2660 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2663 clipdist = -clipdist;
2664 VectorMA(out, clipdist, clipplanenormal, out);
2669 static msurface_t *getsurface(edict_t *ed, int surfnum)
2673 if (!ed || ed->e->free)
2675 modelindex = ed->v->modelindex;
2676 if (modelindex < 1 || modelindex >= MAX_MODELS)
2678 model = sv.models[modelindex];
2679 if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
2681 return model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2685 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2686 void PF_getsurfacenumpoints(void)
2689 // return 0 if no such surface
2690 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2692 G_FLOAT(OFS_RETURN) = 0;
2696 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2698 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2699 void PF_getsurfacepoint(void)
2704 VectorClear(G_VECTOR(OFS_RETURN));
2705 ed = G_EDICT(OFS_PARM0);
2706 if (!ed || ed->e->free)
2708 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2710 pointnum = G_FLOAT(OFS_PARM2);
2711 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2713 // FIXME: implement rotation/scaling
2714 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2716 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2717 void PF_getsurfacenormal(void)
2720 VectorClear(G_VECTOR(OFS_RETURN));
2721 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2723 // FIXME: implement rotation/scaling
2724 if (surf->flags & SURF_PLANEBACK)
2725 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2727 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2729 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2730 void PF_getsurfacetexture(void)
2733 G_INT(OFS_RETURN) = 0;
2734 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2736 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2738 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2739 void PF_getsurfacenearpoint(void)
2741 int surfnum, best, modelindex;
2743 vec_t dist, bestdist;
2748 G_FLOAT(OFS_RETURN) = -1;
2749 ed = G_EDICT(OFS_PARM0);
2750 point = G_VECTOR(OFS_PARM1);
2752 if (!ed || ed->e->free)
2754 modelindex = ed->v->modelindex;
2755 if (modelindex < 1 || modelindex >= MAX_MODELS)
2757 model = sv.models[modelindex];
2758 if (!model->brushq1.numsurfaces)
2761 // FIXME: implement rotation/scaling
2762 VectorSubtract(point, ed->v->origin, p);
2764 bestdist = 1000000000;
2765 for (surfnum = 0;surfnum < model->nummodelsurfaces;surfnum++)
2767 surf = model->brushq1.surfaces + surfnum + model->firstmodelsurface;
2768 dist = PlaneDiff(p, surf->plane);
2770 if (dist < bestdist)
2772 clippointtosurface(surf, p, clipped);
2773 VectorSubtract(clipped, p, clipped);
2774 dist += DotProduct(clipped, clipped);
2775 if (dist < bestdist)
2782 G_FLOAT(OFS_RETURN) = best;
2784 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2785 void PF_getsurfaceclippedpoint(void)
2790 VectorClear(G_VECTOR(OFS_RETURN));
2791 ed = G_EDICT(OFS_PARM0);
2792 if (!ed || ed->e->free)
2794 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2796 // FIXME: implement rotation/scaling
2797 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2798 clippointtosurface(surf, p, out);
2799 // FIXME: implement rotation/scaling
2800 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2803 #define MAX_PRFILES 256
2805 qfile_t *pr_files[MAX_PRFILES];
2807 void PR_Files_Init(void)
2809 memset(pr_files, 0, sizeof(pr_files));
2812 void PR_Files_CloseAll(void)
2815 for (i = 0;i < MAX_PRFILES;i++)
2818 FS_Close(pr_files[i]);
2823 //float(string s) stof = #81; // get numerical value from a string
2826 char string[STRINGTEMP_LENGTH];
2827 PF_VarString(0, string, sizeof(string));
2828 G_FLOAT(OFS_RETURN) = atof(string);
2831 //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
2834 int filenum, mode, i;
2835 char *modestring, *filename;
2836 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2837 if (pr_files[filenum] == NULL)
2839 if (filenum >= MAX_PRFILES)
2841 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2842 G_FLOAT(OFS_RETURN) = -2;
2845 mode = G_FLOAT(OFS_PARM1);
2848 case 0: // FILE_READ
2851 case 1: // FILE_APPEND
2854 case 2: // FILE_WRITE
2858 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2859 G_FLOAT(OFS_RETURN) = -3;
2862 filename = G_STRING(OFS_PARM0);
2863 // control characters do not cause issues with any platforms I know of, but they are usually annoying to deal with
2864 // ../ is parent directory on many platforms
2865 // // is parent directory on Amiga
2866 // / at the beginning of a path is root on unix, and parent directory on Amiga
2867 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2868 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2869 for (i = 0;filename[i];i++)
2871 if (filename[i] < ' ' || (filename[i] == '/' && filename[i+1] == '/') || (filename[i] == '.' && filename[i+1] == '.') || filename[i] == ':' || filename[i] == '\\' || filename[0] == '/')
2873 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);
2874 G_FLOAT(OFS_RETURN) = -4;
2878 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2880 if (pr_files[filenum] == NULL && modestring == "rb")
2881 pr_files[filenum] = FS_Open(filename, modestring, false);
2883 if (pr_files[filenum] == NULL)
2884 G_FLOAT(OFS_RETURN) = -1;
2886 G_FLOAT(OFS_RETURN) = filenum;
2889 //void(float fhandle) fclose = #111; // closes a file
2890 void PF_fclose(void)
2892 int filenum = G_FLOAT(OFS_PARM0);
2893 if (filenum < 0 || filenum >= MAX_PRFILES)
2895 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2898 if (pr_files[filenum] == NULL)
2900 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2903 FS_Close(pr_files[filenum]);
2904 pr_files[filenum] = NULL;
2907 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2911 static char string[STRINGTEMP_LENGTH];
2912 int filenum = G_FLOAT(OFS_PARM0);
2913 if (filenum < 0 || filenum >= MAX_PRFILES)
2915 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2918 if (pr_files[filenum] == NULL)
2920 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2926 c = FS_Getc(pr_files[filenum]);
2927 if (c == '\r' || c == '\n' || c < 0)
2929 if (end < STRINGTEMP_LENGTH - 1)
2933 // remove \n following \r
2935 c = FS_Getc(pr_files[filenum]);
2936 if (developer.integer)
2937 Con_Printf("fgets: %s\n", string);
2939 G_INT(OFS_RETURN) = PR_SetString(string);
2941 G_INT(OFS_RETURN) = 0;
2944 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2948 char string[STRINGTEMP_LENGTH];
2949 int filenum = G_FLOAT(OFS_PARM0);
2950 if (filenum < 0 || filenum >= MAX_PRFILES)
2952 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2955 if (pr_files[filenum] == NULL)
2957 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2960 PF_VarString(1, string, sizeof(string));
2961 if ((stringlength = strlen(string)))
2962 FS_Write(pr_files[filenum], string, stringlength);
2963 if (developer.integer)
2964 Con_Printf("fputs: %s\n", string);
2967 //float(string s) strlen = #114; // returns how many characters are in a string
2968 void PF_strlen(void)
2971 s = G_STRING(OFS_PARM0);
2973 G_FLOAT(OFS_RETURN) = strlen(s);
2975 G_FLOAT(OFS_RETURN) = 0;
2978 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2979 void PF_strcat(void)
2981 char *s = PR_GetTempString();
2982 PF_VarString(0, s, STRINGTEMP_LENGTH);
2983 G_INT(OFS_RETURN) = PR_SetString(s);
2986 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2987 void PF_substring(void)
2989 int i, start, length;
2990 char *s, *string = PR_GetTempString();
2991 s = G_STRING(OFS_PARM0);
2992 start = G_FLOAT(OFS_PARM1);
2993 length = G_FLOAT(OFS_PARM2);
2996 for (i = 0;i < start && *s;i++, s++);
2997 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
3000 G_INT(OFS_RETURN) = PR_SetString(string);
3003 //vector(string s) stov = #117; // returns vector value from a string
3006 char string[STRINGTEMP_LENGTH];
3007 PF_VarString(0, string, sizeof(string));
3008 Math_atov(string, G_VECTOR(OFS_RETURN));
3011 //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)
3012 void PF_strzone(void)
3015 in = G_STRING(OFS_PARM0);
3016 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
3018 G_INT(OFS_RETURN) = PR_SetString(out);
3021 //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!!!)
3022 void PF_strunzone(void)
3024 Mem_Free(G_STRING(OFS_PARM0));
3027 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3028 //this function originally written by KrimZon, made shorter by LordHavoc
3029 void PF_clientcommand (void)
3031 client_t *temp_client;
3034 //find client for this entity
3035 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
3036 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3038 Con_Print("PF_clientcommand: entity is not a client\n");
3042 temp_client = host_client;
3043 host_client = svs.clients + i;
3044 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
3045 host_client = temp_client;
3048 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3049 //this function originally written by KrimZon, made shorter by LordHavoc
3050 //20040203: rewritten by LordHavoc (no longer uses allocations)
3052 char *tokens[256], tokenbuf[4096];
3053 void PF_tokenize (void)
3057 p = G_STRING(OFS_PARM0);
3061 while(COM_ParseToken(&p, false))
3063 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3065 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3067 tokens[num_tokens++] = tokenbuf + pos;
3068 strcpy(tokenbuf + pos, com_token);
3069 pos += strlen(com_token) + 1;
3072 G_FLOAT(OFS_RETURN) = num_tokens;
3075 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3076 //this function originally written by KrimZon, made shorter by LordHavoc
3079 int token_num = G_FLOAT(OFS_PARM0);
3080 if (token_num >= 0 && token_num < num_tokens)
3081 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3083 G_INT(OFS_RETURN) = PR_SetString("");
3086 //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)
3087 void PF_setattachment (void)
3089 edict_t *e = G_EDICT(OFS_PARM0);
3090 edict_t *tagentity = G_EDICT(OFS_PARM1);
3091 char *tagname = G_STRING(OFS_PARM2);
3097 PF_WARNING("setattachment: can not modify world entity\n");
3099 PF_WARNING("setattachment: can not modify free entity\n");
3101 if (tagentity == NULL)
3102 tagentity = sv.edicts;
3104 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3106 v->edict = EDICT_TO_PROG(tagentity);
3108 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3111 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3113 modelindex = (int)tagentity->v->modelindex;
3114 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3116 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3117 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3118 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3120 // FIXME: use a model function to get tag info (need to handle skeletal)
3121 if (v->_float == 0 && model->alias.aliasnum_tags)
3122 for (i = 0;i < model->alias.aliasnum_tags;i++)
3123 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3126 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);
3129 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));
3134 /////////////////////////////////////////
3135 // DP_QC_FS_SEARCH extension
3137 // qc fs search handling
3138 #define MAX_SEARCHES 128
3140 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3142 void PR_Search_Init(void)
3144 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3147 void PR_Search_Reset(void)
3150 // reset the fssearch list
3151 for(i = 0; i < MAX_SEARCHES; i++)
3152 if(pr_fssearchlist[i])
3153 FS_FreeSearch(pr_fssearchlist[i]);
3154 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3161 float search_begin(string pattern, float caseinsensitive, float quiet)
3164 void PF_search_begin(void)
3168 int caseinsens, quiet;
3170 pattern = G_STRING(OFS_PARM0);
3172 PR_CheckEmptyString(pattern);
3174 caseinsens = G_FLOAT(OFS_PARM1);
3175 quiet = G_FLOAT(OFS_PARM2);
3177 for(handle = 0; handle < MAX_SEARCHES; handle++)
3178 if(!pr_fssearchlist[handle])
3181 if(handle >= MAX_SEARCHES)
3183 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3184 G_FLOAT(OFS_RETURN) = -2;
3188 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3189 G_FLOAT(OFS_RETURN) = -1;
3191 G_FLOAT(OFS_RETURN) = handle;
3198 void search_end(float handle)
3201 void PF_search_end(void)
3205 handle = G_FLOAT(OFS_PARM0);
3207 if(handle < 0 || handle >= MAX_SEARCHES)
3209 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3212 if(pr_fssearchlist[handle] == NULL)
3214 Con_Printf("PF_search_end: no such handle %i\n", handle);
3218 FS_FreeSearch(pr_fssearchlist[handle]);
3219 pr_fssearchlist[handle] = NULL;
3226 float search_getsize(float handle)
3229 void PF_search_getsize(void)
3233 handle = G_FLOAT(OFS_PARM0);
3235 if(handle < 0 || handle >= MAX_SEARCHES)
3237 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3240 if(pr_fssearchlist[handle] == NULL)
3242 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3246 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3251 VM_search_getfilename
3253 string search_getfilename(float handle, float num)
3256 void PF_search_getfilename(void)
3258 int handle, filenum;
3261 handle = G_FLOAT(OFS_PARM0);
3262 filenum = G_FLOAT(OFS_PARM1);
3264 if(handle < 0 || handle >= MAX_SEARCHES)
3266 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3269 if(pr_fssearchlist[handle] == NULL)
3271 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3274 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3276 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3280 tmp = PR_GetTempString();
3281 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3283 G_INT(OFS_RETURN) = PR_SetString(tmp);
3286 void PF_cvar_string (void)
3292 str = G_STRING(OFS_PARM0);
3293 var = Cvar_FindVar (str);
3296 tmp = PR_GetTempString();
3297 strcpy(tmp, var->string);
3301 G_INT(OFS_RETURN) = PR_SetString(tmp);
3306 builtin_t pr_builtin[] =
3309 PF_makevectors, // #1 void(entity e) makevectors
3310 PF_setorigin, // #2 void(entity e, vector o) setorigin
3311 PF_setmodel, // #3 void(entity e, string m) setmodel
3312 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3313 NULL, // #5 void(entity e, vector min, vector max) setabssize
3314 PF_break, // #6 void() break
3315 PF_random, // #7 float() random
3316 PF_sound, // #8 void(entity e, float chan, string samp) sound
3317 PF_normalize, // #9 vector(vector v) normalize
3318 PF_error, // #10 void(string e) error
3319 PF_objerror, // #11 void(string e) objerror
3320 PF_vlen, // #12 float(vector v) vlen
3321 PF_vectoyaw, // #13 float(vector v) vectoyaw
3322 PF_Spawn, // #14 entity() spawn
3323 PF_Remove, // #15 void(entity e) remove
3324 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3325 PF_checkclient, // #17 entity() clientlist
3326 PF_Find, // #18 entity(entity start, .string fld, string match) find
3327 PF_precache_sound, // #19 void(string s) precache_sound
3328 PF_precache_model, // #20 void(string s) precache_model
3329 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3330 PF_findradius, // #22 entity(vector org, float rad) findradius
3331 PF_bprint, // #23 void(string s) bprint
3332 PF_sprint, // #24 void(entity client, string s) sprint
3333 PF_dprint, // #25 void(string s) dprint
3334 PF_ftos, // #26 void(string s) ftos
3335 PF_vtos, // #27 void(string s) vtos
3336 PF_coredump, // #28 void() coredump
3337 PF_traceon, // #29 void() traceon
3338 PF_traceoff, // #30 void() traceoff
3339 PF_eprint, // #31 void(entity e) eprint
3340 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3342 PF_droptofloor, // #34 float() droptofloor
3343 PF_lightstyle, // #35 void(float style, string value) lightstyle
3344 PF_rint, // #36 float(float v) rint
3345 PF_floor, // #37 float(float v) floor
3346 PF_ceil, // #38 float(float v) ceil
3348 PF_checkbottom, // #40 float(entity e) checkbottom
3349 PF_pointcontents , // #41 float(vector v) pointcontents
3351 PF_fabs, // #43 float(float f) fabs
3352 PF_aim, // #44 vector(entity e, float speed) aim
3353 PF_cvar, // #45 float(string s) cvar
3354 PF_localcmd, // #46 void(string s) localcmd
3355 PF_nextent, // #47 entity(entity e) nextent
3356 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3357 PF_changeyaw, // #49 void() ChangeYaw
3359 PF_vectoangles, // #51 vector(vector v) vectoangles
3360 PF_WriteByte, // #52 void(float to, float f) WriteByte
3361 PF_WriteChar, // #53 void(float to, float f) WriteChar
3362 PF_WriteShort, // #54 void(float to, float f) WriteShort
3363 PF_WriteLong, // #55 void(float to, float f) WriteLong
3364 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3365 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3366 PF_WriteString, // #58 void(float to, string s) WriteString
3367 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3368 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3369 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3370 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3371 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3372 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3373 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3375 SV_MoveToGoal, // #67 void(float step) movetogoal
3376 PF_precache_file, // #68 string(string s) precache_file
3377 PF_makestatic, // #69 void(entity e) makestatic
3378 PF_changelevel, // #70 void(string s) changelevel
3380 PF_cvar_set, // #72 void(string var, string val) cvar_set
3381 PF_centerprint, // #73 void(entity client, strings) centerprint
3382 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3383 PF_precache_model, // #75 string(string s) precache_model2
3384 PF_precache_sound, // #76 string(string s) precache_sound2
3385 PF_precache_file, // #77 string(string s) precache_file2
3386 PF_setspawnparms, // #78 void(entity e) setspawnparms
3389 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3398 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3399 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3400 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3401 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3402 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3403 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3404 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3405 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3406 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3407 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3418 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3419 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3420 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3421 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3422 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3423 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3424 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3425 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3426 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3427 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3428 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3429 a a a a a a a a // #120-199
3430 a a a a a a a a a a // #200-299
3431 a a a a a a a a a a // #300-399
3432 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3433 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3434 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3435 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3436 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3437 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3438 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3439 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3440 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3441 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3442 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3443 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3444 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3445 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3446 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3447 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3448 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3449 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3450 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3451 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3452 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3453 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3454 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3455 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3456 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3457 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3458 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3459 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3460 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3461 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3462 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3463 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3464 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3465 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3466 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3467 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3468 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3469 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3470 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3471 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3472 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3473 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3474 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3475 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3476 PF_search_begin, // #444
3477 PF_search_end, // #445
3478 PF_search_getsize, // #446
3479 PF_search_getfilename, // #447
3480 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3481 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3482 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3492 a a a a // #460-499 (LordHavoc)
3495 builtin_t *pr_builtins = pr_builtin;
3496 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3498 void PR_Cmd_Init(void)
3500 pr_strings_mempool = Mem_AllocPool("pr_stringszone", 0, NULL);
3505 void PR_Cmd_Reset(void)
3507 Mem_EmptyPool(pr_strings_mempool);
3509 PR_Files_CloseAll();