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 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
27 #define STRINGTEMP_BUFFERS 16
28 #define STRINGTEMP_LENGTH 4096
29 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
30 static int pr_string_tempindex = 0;
32 static char *PR_GetTempString(void)
35 s = pr_string_temp[pr_string_tempindex];
36 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
40 #define RETURN_EDICT(e) (PRVM_G_INT(OFS_RETURN) = PRVM_EDICT_TO_PROG(e))
41 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
42 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
46 ===============================================================================
50 ===============================================================================
54 void PF_VarString(int first, char *out, int outlength)
60 outend = out + outlength - 1;
61 for (i = first;i < pr_argc && out < outend;i++)
63 s = PRVM_G_STRING((OFS_PARM0+i*3));
64 while (out < outend && *s)
70 char *ENGINE_EXTENSIONS =
87 "DP_ENT_CUSTOMCOLORMAP "
88 "DP_ENT_EXTERIORMODELTOCLIENT "
90 "DP_ENT_LOWPRECISION "
93 "DP_GFX_EXTERNALTEXTURES "
95 "DP_GFX_QUAKE3MODELTAGS "
99 "DP_HALFLIFE_MAP_CVAR "
100 "DP_HALFLIFE_SPRITE "
105 "DP_MOVETYPEBOUNCEMISSILE "
112 "DP_QC_FINDCHAINFLAGS "
113 "DP_QC_FINDCHAINFLOAT "
116 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
121 "DP_QC_MULTIPLETEMPSTRINGS "
123 "DP_QC_SINCOSSQRTPOW "
126 "DP_QC_TRACE_MOVETYPE_HITMODEL "
127 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
128 "DP_QC_VECTORVECTORS "
134 "DP_SND_DIRECTIONLESSATTNNONE "
141 "DP_SV_CLIENTCOLORS "
143 "DP_SV_DRAWONLYTOCLIENT "
146 "DP_SV_NODRAWTOCLIENT "
148 "DP_SV_PLAYERPHYSICS "
150 "DP_SV_ROTATINGBMODEL "
156 "DP_TE_EXPLOSIONRGB "
158 "DP_TE_PARTICLECUBE "
159 "DP_TE_PARTICLERAIN "
160 "DP_TE_PARTICLESNOW "
162 "DP_TE_QUADEFFECTS1 "
165 "DP_TE_STANDARDEFFECTBUILTINS "
168 "KRIMZON_SV_PARSECLIENTCOMMAND "
172 "PRYDON_CLIENTCURSOR "
173 "TENEBRAE_GFX_DLIGHTS "
175 "NEXUIZ_PLAYERMODEL "
179 qboolean checkextension(const char *name)
184 for (e = ENGINE_EXTENSIONS;*e;e++)
191 while (*e && *e != ' ')
193 if (e - start == len)
194 if (!strncasecmp(start, name, len))
204 returns true if the extension is supported by the server
206 checkextension(extensionname)
209 void PF_checkextension (void)
211 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
218 This is a TERMINAL error, which will kill off the entire server.
227 char string[STRINGTEMP_LENGTH];
229 PF_VarString(0, string, sizeof(string));
230 Con_Printf("======SERVER ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string);
231 ed = PRVM_PROG_TO_EDICT(prog->globals.server->self);
234 PF_ERROR("Program error");
241 Dumps out self, then an error message. The program is aborted and self is
242 removed, but the level can continue.
247 void PF_objerror (void)
250 char string[STRINGTEMP_LENGTH];
252 PF_VarString(0, string, sizeof(string));
253 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string);
254 ed = PRVM_PROG_TO_EDICT(prog->globals.server->self);
264 Writes new values for v_forward, v_up, and v_right based on angles
268 void PF_makevectors (void)
270 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
277 Writes new values for v_forward, v_up, and v_right based on the given forward vector
278 vectorvectors(vector, vector)
281 void PF_vectorvectors (void)
283 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
284 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
291 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.
293 setorigin (entity, origin)
296 void PF_setorigin (void)
301 e = PRVM_G_EDICT(OFS_PARM0);
302 if (e == prog->edicts)
303 PF_WARNING("setorigin: can not modify world entity\n");
304 if (e->priv.server->free)
305 PF_WARNING("setorigin: can not modify free entity\n");
306 org = PRVM_G_VECTOR(OFS_PARM1);
307 VectorCopy (org, e->fields.server->origin);
308 SV_LinkEdict (e, false);
312 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
316 for (i=0 ; i<3 ; i++)
318 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
320 // set derived values
321 VectorCopy (min, e->fields.server->mins);
322 VectorCopy (max, e->fields.server->maxs);
323 VectorSubtract (max, min, e->fields.server->size);
325 SV_LinkEdict (e, false);
332 the size box is rotated by the current angle
333 LordHavoc: no it isn't...
335 setsize (entity, minvector, maxvector)
338 void PF_setsize (void)
343 e = PRVM_G_EDICT(OFS_PARM0);
344 if (e == prog->edicts)
345 PF_WARNING("setsize: can not modify world entity\n");
346 if (e->priv.server->free)
347 PF_WARNING("setsize: can not modify free entity\n");
348 min = PRVM_G_VECTOR(OFS_PARM1);
349 max = PRVM_G_VECTOR(OFS_PARM2);
350 SetMinMaxSize (e, min, max, false);
358 setmodel(entity, model)
361 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
362 void PF_setmodel (void)
368 e = PRVM_G_EDICT(OFS_PARM0);
369 if (e == prog->edicts)
370 PF_WARNING("setmodel: can not modify world entity\n");
371 if (e->priv.server->free)
372 PF_WARNING("setmodel: can not modify free entity\n");
373 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
374 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
375 e->fields.server->modelindex = i;
381 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
382 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
384 SetMinMaxSize (e, quakemins, quakemaxs, true);
387 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
394 broadcast print to everyone on server
399 void PF_bprint (void)
401 char string[STRINGTEMP_LENGTH];
402 PF_VarString(0, string, sizeof(string));
403 SV_BroadcastPrint(string);
410 single print to a specific client
412 sprint(clientent, value)
415 void PF_sprint (void)
419 char string[STRINGTEMP_LENGTH];
421 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
423 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
425 Con_Print("tried to sprint to a non-client\n");
429 client = svs.clients + entnum-1;
430 PF_VarString(1, string, sizeof(string));
431 MSG_WriteChar(&client->message,svc_print);
432 MSG_WriteString(&client->message, string);
440 single print to a specific client
442 centerprint(clientent, value)
445 void PF_centerprint (void)
449 char string[STRINGTEMP_LENGTH];
451 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
453 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
455 Con_Print("tried to sprint to a non-client\n");
459 client = svs.clients + entnum-1;
460 PF_VarString(1, string, sizeof(string));
461 MSG_WriteChar(&client->message,svc_centerprint);
462 MSG_WriteString(&client->message, string);
470 vector normalize(vector)
473 void PF_normalize (void)
479 value1 = PRVM_G_VECTOR(OFS_PARM0);
481 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
485 newvalue[0] = newvalue[1] = newvalue[2] = 0;
489 newvalue[0] = value1[0] * new;
490 newvalue[1] = value1[1] * new;
491 newvalue[2] = value1[2] * new;
494 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
509 value1 = PRVM_G_VECTOR(OFS_PARM0);
511 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
514 PRVM_G_FLOAT(OFS_RETURN) = new;
521 float vectoyaw(vector)
524 void PF_vectoyaw (void)
529 value1 = PRVM_G_VECTOR(OFS_PARM0);
531 if (value1[1] == 0 && value1[0] == 0)
535 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
540 PRVM_G_FLOAT(OFS_RETURN) = yaw;
548 vector vectoangles(vector)
551 void PF_vectoangles (void)
553 double value1[3], forward, yaw, pitch;
555 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), value1);
557 if (value1[1] == 0 && value1[0] == 0)
567 // LordHavoc: optimized a bit
570 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
574 else if (value1[1] > 0)
579 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
580 pitch = (atan2(value1[2], forward) * 180 / M_PI);
585 VectorSet(PRVM_G_VECTOR(OFS_RETURN), pitch, yaw, 0);
592 Returns a number from 0<= num < 1
597 void PF_random (void)
599 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
606 particle(origin, color, count)
609 void PF_particle (void)
615 org = PRVM_G_VECTOR(OFS_PARM0);
616 dir = PRVM_G_VECTOR(OFS_PARM1);
617 color = PRVM_G_FLOAT(OFS_PARM2);
618 count = PRVM_G_FLOAT(OFS_PARM3);
619 SV_StartParticle (org, dir, color, count);
629 void PF_ambientsound (void)
633 float vol, attenuation;
636 pos = PRVM_G_VECTOR (OFS_PARM0);
637 samp = PRVM_G_STRING(OFS_PARM1);
638 vol = PRVM_G_FLOAT(OFS_PARM2);
639 attenuation = PRVM_G_FLOAT(OFS_PARM3);
641 // check to see if samp was properly precached
642 soundnum = SV_SoundIndex(samp, 1);
650 // add an svc_spawnambient command to the level signon packet
653 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
655 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
657 MSG_WriteVector(&sv.signon, pos, sv.protocol);
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.
688 prvm_edict_t *entity;
692 entity = PRVM_G_EDICT(OFS_PARM0);
693 channel = PRVM_G_FLOAT(OFS_PARM1);
694 sample = PRVM_G_STRING(OFS_PARM2);
695 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
696 attenuation = PRVM_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 = PRVM_G_VECTOR(OFS_PARM0);
743 v2 = PRVM_G_VECTOR(OFS_PARM1);
744 move = PRVM_G_FLOAT(OFS_PARM2);
745 ent = PRVM_G_EDICT(OFS_PARM3);
747 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
749 prog->globals.server->trace_allsolid = trace.allsolid;
750 prog->globals.server->trace_startsolid = trace.startsolid;
751 prog->globals.server->trace_fraction = trace.fraction;
752 prog->globals.server->trace_inwater = trace.inwater;
753 prog->globals.server->trace_inopen = trace.inopen;
754 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
755 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
756 prog->globals.server->trace_plane_dist = trace.plane.dist;
758 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
760 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->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 = PRVM_G_VECTOR(OFS_PARM0);
787 m1 = PRVM_G_VECTOR(OFS_PARM1);
788 m2 = PRVM_G_VECTOR(OFS_PARM2);
789 v2 = PRVM_G_VECTOR(OFS_PARM3);
790 move = PRVM_G_FLOAT(OFS_PARM4);
791 ent = PRVM_G_EDICT(OFS_PARM5);
793 trace = SV_Move (v1, m1, m2, v2, move, ent);
795 prog->globals.server->trace_allsolid = trace.allsolid;
796 prog->globals.server->trace_startsolid = trace.startsolid;
797 prog->globals.server->trace_fraction = trace.fraction;
798 prog->globals.server->trace_inwater = trace.inwater;
799 prog->globals.server->trace_inopen = trace.inopen;
800 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
801 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
802 prog->globals.server->trace_plane_dist = trace.plane.dist;
804 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
806 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
809 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
810 void PF_tracetoss (void)
814 prvm_edict_t *ignore;
816 pr_xfunction->builtinsprofile += 600;
818 ent = PRVM_G_EDICT(OFS_PARM0);
819 if (ent == prog->edicts)
820 PF_WARNING("tracetoss: can not use world entity\n");
821 ignore = PRVM_G_EDICT(OFS_PARM1);
823 trace = SV_Trace_Toss (ent, ignore);
825 prog->globals.server->trace_allsolid = trace.allsolid;
826 prog->globals.server->trace_startsolid = trace.startsolid;
827 prog->globals.server->trace_fraction = trace.fraction;
828 prog->globals.server->trace_inwater = trace.inwater;
829 prog->globals.server->trace_inopen = trace.inopen;
830 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
831 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
832 prog->globals.server->trace_plane_dist = trace.plane.dist;
834 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
836 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->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
881 ent = PRVM_EDICT_NUM(i);
882 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
883 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
885 // found a valid client (possibly the same one again)
889 // get the PVS for the entity
890 VectorAdd(ent->fields.server->origin, ent->fields.server->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)
916 prvm_edict_t *ent, *self;
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 = PRVM_EDICT_NUM(sv.lastcheck);
928 if (ent->priv.server->free || ent->fields.server->health <= 0)
930 RETURN_EDICT(prog->edicts);
934 // if current entity can't possibly see the check entity, return 0
935 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
936 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
937 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
940 RETURN_EDICT(prog->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 = PRVM_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 = PRVM_G_STRING(OFS_PARM1);
976 host_client = svs.clients + entnum-1;
977 Host_ClientCommands ("%s", str);
985 Sends text to server console
990 void PF_localcmd (void)
992 Cbuf_AddText(PRVM_G_STRING(OFS_PARM0));
1004 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
1014 void PF_cvar_set (void)
1016 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_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 prvm_edict_t *ent, *chain;
1031 vec_t radius, radius2;
1032 vec3_t org, eorg, mins, maxs;
1035 prvm_edict_t *touchedicts[MAX_EDICTS];
1037 chain = (prvm_edict_t *)prog->edicts;
1039 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1040 radius = PRVM_G_FLOAT(OFS_PARM1);
1041 radius2 = radius * radius;
1043 mins[0] = org[0] - (radius + 1);
1044 mins[1] = org[1] - (radius + 1);
1045 mins[2] = org[2] - (radius + 1);
1046 maxs[0] = org[0] + (radius + 1);
1047 maxs[1] = org[1] + (radius + 1);
1048 maxs[2] = org[2] + (radius + 1);
1049 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1050 if (numtouchedicts > MAX_EDICTS)
1052 // this never happens
1053 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1054 numtouchedicts = MAX_EDICTS;
1056 for (i = 0;i < numtouchedicts;i++)
1058 ent = touchedicts[i];
1059 pr_xfunction->builtinsprofile++;
1060 // Quake did not return non-solid entities but darkplaces does
1061 // (note: this is the reason you can't blow up fallen zombies)
1062 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
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 VectorSubtract(org, ent->fields.server->origin, eorg);
1068 if (sv_gameplayfix_findradiusdistancetobox.integer)
1070 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
1071 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
1072 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
1075 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
1076 if (DotProduct(eorg, eorg) < radius2)
1078 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1083 RETURN_EDICT(chain);
1092 void PF_dprint (void)
1094 char string[STRINGTEMP_LENGTH];
1095 if (developer.integer)
1097 PF_VarString(0, string, sizeof(string));
1106 v = PRVM_G_FLOAT(OFS_PARM0);
1108 s = PR_GetTempString();
1109 if ((float)((int)v) == v)
1110 sprintf(s, "%i", (int)v);
1112 sprintf(s, "%f", v);
1113 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1119 v = PRVM_G_FLOAT(OFS_PARM0);
1120 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
1126 s = PR_GetTempString();
1127 sprintf (s, "'%5.1f %5.1f %5.1f'", PRVM_G_VECTOR(OFS_PARM0)[0], PRVM_G_VECTOR(OFS_PARM0)[1], PRVM_G_VECTOR(OFS_PARM0)[2]);
1128 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1134 s = PR_GetTempString();
1135 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
1136 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1139 void PF_Spawn (void)
1142 pr_xfunction->builtinsprofile += 20;
1147 void PF_Remove (void)
1150 pr_xfunction->builtinsprofile += 20;
1152 ed = PRVM_G_EDICT(OFS_PARM0);
1153 if (ed == prog->edicts)
1154 PF_WARNING("remove: tried to remove world\n");
1155 if (PRVM_NUM_FOR_EDICT(ed) <= svs.maxclients)
1156 PF_WARNING("remove: tried to remove a client\n");
1157 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1158 if (ed->priv.server->free && developer.integer)
1159 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1164 // entity (entity start, .string field, string match) find = #5;
1172 e = PRVM_G_EDICTNUM(OFS_PARM0);
1173 f = PRVM_G_INT(OFS_PARM1);
1174 s = PRVM_G_STRING(OFS_PARM2);
1177 RETURN_EDICT(prog->edicts);
1181 for (e++ ; e < prog->num_edicts ; e++)
1183 pr_xfunction->builtinsprofile++;
1184 ed = PRVM_EDICT_NUM(e);
1185 if (ed->priv.server->free)
1197 RETURN_EDICT(prog->edicts);
1200 // LordHavoc: added this for searching float, int, and entity reference fields
1201 void PF_FindFloat (void)
1208 e = PRVM_G_EDICTNUM(OFS_PARM0);
1209 f = PRVM_G_INT(OFS_PARM1);
1210 s = PRVM_G_FLOAT(OFS_PARM2);
1212 for (e++ ; e < prog->num_edicts ; e++)
1214 pr_xfunction->builtinsprofile++;
1215 ed = PRVM_EDICT_NUM(e);
1216 if (ed->priv.server->free)
1218 if (E_FLOAT(ed,f) == s)
1225 RETURN_EDICT(prog->edicts);
1228 // chained search for strings in entity fields
1229 // entity(.string field, string match) findchain = #402;
1230 void PF_findchain (void)
1235 prvm_edict_t *ent, *chain;
1237 chain = (prvm_edict_t *)prog->edicts;
1239 f = PRVM_G_INT(OFS_PARM0);
1240 s = PRVM_G_STRING(OFS_PARM1);
1243 RETURN_EDICT(prog->edicts);
1247 ent = PRVM_NEXT_EDICT(prog->edicts);
1248 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1250 pr_xfunction->builtinsprofile++;
1251 if (ent->priv.server->free)
1253 t = E_STRING(ent,f);
1259 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1263 RETURN_EDICT(chain);
1266 // LordHavoc: chained search for float, int, and entity reference fields
1267 // entity(.string field, float match) findchainfloat = #403;
1268 void PF_findchainfloat (void)
1273 prvm_edict_t *ent, *chain;
1275 chain = (prvm_edict_t *)prog->edicts;
1277 f = PRVM_G_INT(OFS_PARM0);
1278 s = PRVM_G_FLOAT(OFS_PARM1);
1280 ent = PRVM_NEXT_EDICT(prog->edicts);
1281 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1283 pr_xfunction->builtinsprofile++;
1284 if (ent->priv.server->free)
1286 if (E_FLOAT(ent,f) != s)
1289 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1293 RETURN_EDICT(chain);
1296 // LordHavoc: search for flags in float fields
1297 void PF_findflags (void)
1304 e = PRVM_G_EDICTNUM(OFS_PARM0);
1305 f = PRVM_G_INT(OFS_PARM1);
1306 s = (int)PRVM_G_FLOAT(OFS_PARM2);
1308 for (e++ ; e < prog->num_edicts ; e++)
1310 pr_xfunction->builtinsprofile++;
1311 ed = PRVM_EDICT_NUM(e);
1312 if (ed->priv.server->free)
1314 if ((int)E_FLOAT(ed,f) & s)
1321 RETURN_EDICT(prog->edicts);
1324 // LordHavoc: chained search for flags in float fields
1325 void PF_findchainflags (void)
1330 prvm_edict_t *ent, *chain;
1332 chain = (prvm_edict_t *)prog->edicts;
1334 f = PRVM_G_INT(OFS_PARM0);
1335 s = (int)PRVM_G_FLOAT(OFS_PARM1);
1337 ent = PRVM_NEXT_EDICT(prog->edicts);
1338 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1340 pr_xfunction->builtinsprofile++;
1341 if (ent->priv.server->free)
1343 if (!((int)E_FLOAT(ent,f) & s))
1346 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1350 RETURN_EDICT(chain);
1353 void PF_precache_file (void)
1354 { // precache_file is only used to copy files with qcc, it does nothing
1355 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1359 void PF_precache_sound (void)
1361 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1362 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1365 void PF_precache_model (void)
1367 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1368 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1372 void PF_coredump (void)
1377 void PF_traceon (void)
1382 void PF_traceoff (void)
1387 void PF_eprint (void)
1389 ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1396 float(float yaw, float dist) walkmove
1399 void PF_walkmove (void)
1407 // assume failure if it returns early
1408 PRVM_G_FLOAT(OFS_RETURN) = 0;
1410 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1411 if (ent == prog->edicts)
1412 PF_WARNING("walkmove: can not modify world entity\n");
1413 if (ent->priv.server->free)
1414 PF_WARNING("walkmove: can not modify free entity\n");
1415 yaw = PRVM_G_FLOAT(OFS_PARM0);
1416 dist = PRVM_G_FLOAT(OFS_PARM1);
1418 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1421 yaw = yaw*M_PI*2 / 360;
1423 move[0] = cos(yaw)*dist;
1424 move[1] = sin(yaw)*dist;
1427 // save program state, because SV_movestep may call other progs
1428 oldf = pr_xfunction;
1429 oldself = prog->globals.server->self;
1431 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1434 // restore program state
1435 pr_xfunction = oldf;
1436 prog->globals.server->self = oldself;
1446 void PF_droptofloor (void)
1452 // assume failure if it returns early
1453 PRVM_G_FLOAT(OFS_RETURN) = 0;
1455 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1456 if (ent == prog->edicts)
1457 PF_WARNING("droptofloor: can not modify world entity\n");
1458 if (ent->priv.server->free)
1459 PF_WARNING("droptofloor: can not modify free entity\n");
1461 VectorCopy (ent->fields.server->origin, end);
1464 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
1466 if (trace.fraction != 1)
1468 VectorCopy (trace.endpos, ent->fields.server->origin);
1469 SV_LinkEdict (ent, false);
1470 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1471 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1472 PRVM_G_FLOAT(OFS_RETURN) = 1;
1473 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1474 ent->priv.server->suspendedinairflag = true;
1482 void(float style, string value) lightstyle
1485 void PF_lightstyle (void)
1492 style = PRVM_G_FLOAT(OFS_PARM0);
1493 val = PRVM_G_STRING(OFS_PARM1);
1495 // change the string in sv
1496 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1498 // send message to all clients on this server
1499 if (sv.state != ss_active)
1502 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1506 MSG_WriteChar (&client->message, svc_lightstyle);
1507 MSG_WriteChar (&client->message,style);
1508 MSG_WriteString (&client->message, val);
1516 f = PRVM_G_FLOAT(OFS_PARM0);
1518 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1520 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1522 void PF_floor (void)
1524 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1528 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1537 void PF_checkbottom (void)
1539 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1547 void PF_pointcontents (void)
1549 PRVM_G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(PRVM_G_VECTOR(OFS_PARM0));
1556 entity nextent(entity)
1559 void PF_nextent (void)
1564 i = PRVM_G_EDICTNUM(OFS_PARM0);
1567 pr_xfunction->builtinsprofile++;
1569 if (i == prog->num_edicts)
1571 RETURN_EDICT(prog->edicts);
1574 ent = PRVM_EDICT_NUM(i);
1575 if (!ent->priv.server->free)
1587 Pick a vector for the player to shoot along
1588 vector aim(entity, missilespeed)
1593 prvm_edict_t *ent, *check, *bestent;
1594 vec3_t start, dir, end, bestdir;
1597 float dist, bestdist;
1600 // assume failure if it returns early
1601 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1602 // if sv_aim is so high it can't possibly accept anything, skip out early
1603 if (sv_aim.value >= 1)
1606 ent = PRVM_G_EDICT(OFS_PARM0);
1607 if (ent == prog->edicts)
1608 PF_WARNING("aim: can not use world entity\n");
1609 if (ent->priv.server->free)
1610 PF_WARNING("aim: can not use free entity\n");
1611 speed = PRVM_G_FLOAT(OFS_PARM1);
1613 VectorCopy (ent->fields.server->origin, start);
1616 // try sending a trace straight
1617 VectorCopy (prog->globals.server->v_forward, dir);
1618 VectorMA (start, 2048, dir, end);
1619 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1620 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1621 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1623 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1628 // try all possible entities
1629 VectorCopy (dir, bestdir);
1630 bestdist = sv_aim.value;
1633 check = PRVM_NEXT_EDICT(prog->edicts);
1634 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1636 pr_xfunction->builtinsprofile++;
1637 if (check->fields.server->takedamage != DAMAGE_AIM)
1641 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1642 continue; // don't aim at teammate
1643 for (j=0 ; j<3 ; j++)
1644 end[j] = check->fields.server->origin[j]
1645 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1646 VectorSubtract (end, start, dir);
1647 VectorNormalize (dir);
1648 dist = DotProduct (dir, prog->globals.server->v_forward);
1649 if (dist < bestdist)
1650 continue; // to far to turn
1651 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1652 if (tr.ent == check)
1653 { // can shoot at this one
1661 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1662 dist = DotProduct (dir, prog->globals.server->v_forward);
1663 VectorScale (prog->globals.server->v_forward, dist, end);
1665 VectorNormalize (end);
1666 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1670 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1678 This was a major timewaster in progs, so it was converted to C
1681 void PF_changeyaw (void)
1684 float ideal, current, move, speed;
1686 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1687 if (ent == prog->edicts)
1688 PF_WARNING("changeyaw: can not modify world entity\n");
1689 if (ent->priv.server->free)
1690 PF_WARNING("changeyaw: can not modify free entity\n");
1691 current = ANGLEMOD(ent->fields.server->angles[1]);
1692 ideal = ent->fields.server->ideal_yaw;
1693 speed = ent->fields.server->yaw_speed;
1695 if (current == ideal)
1697 move = ideal - current;
1698 if (ideal > current)
1719 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1727 void PF_changepitch (void)
1730 float ideal, current, move, speed;
1733 ent = PRVM_G_EDICT(OFS_PARM0);
1734 if (ent == prog->edicts)
1735 PF_WARNING("changepitch: can not modify world entity\n");
1736 if (ent->priv.server->free)
1737 PF_WARNING("changepitch: can not modify free entity\n");
1738 current = ANGLEMOD( ent->fields.server->angles[0] );
1739 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1740 ideal = val->_float;
1743 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1746 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1747 speed = val->_float;
1750 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1754 if (current == ideal)
1756 move = ideal - current;
1757 if (ideal > current)
1778 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1782 ===============================================================================
1786 ===============================================================================
1789 #define MSG_BROADCAST 0 // unreliable to all
1790 #define MSG_ONE 1 // reliable to one (msg_entity)
1791 #define MSG_ALL 2 // reliable to all
1792 #define MSG_INIT 3 // write to the init string
1794 sizebuf_t *WriteDest (void)
1800 dest = PRVM_G_FLOAT(OFS_PARM0);
1804 return &sv.datagram;
1807 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1808 entnum = PRVM_NUM_FOR_EDICT(ent);
1809 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1810 Host_Error("WriteDest: tried to write to non-client\n");
1811 return &svs.clients[entnum-1].message;
1814 return &sv.reliable_datagram;
1820 Host_Error("WriteDest: bad destination");
1827 void PF_WriteByte (void)
1829 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1832 void PF_WriteChar (void)
1834 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1837 void PF_WriteShort (void)
1839 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1842 void PF_WriteLong (void)
1844 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1847 void PF_WriteAngle (void)
1849 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1852 void PF_WriteCoord (void)
1854 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1857 void PF_WriteString (void)
1859 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1863 void PF_WriteEntity (void)
1865 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1868 //=============================================================================
1870 void PF_makestatic (void)
1875 ent = PRVM_G_EDICT(OFS_PARM0);
1876 if (ent == prog->edicts)
1877 PF_WARNING("makestatic: can not modify world entity\n");
1878 if (ent->priv.server->free)
1879 PF_WARNING("makestatic: can not modify free entity\n");
1882 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1887 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1888 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1889 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1893 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1894 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1895 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1898 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1899 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1900 for (i=0 ; i<3 ; i++)
1902 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1903 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1906 // throw the entity away now
1910 //=============================================================================
1917 void PF_setspawnparms (void)
1923 ent = PRVM_G_EDICT(OFS_PARM0);
1924 i = PRVM_NUM_FOR_EDICT(ent);
1925 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1927 Con_Print("tried to setspawnparms on a non-client\n");
1931 // copy spawn parms out of the client_t
1932 client = svs.clients + i-1;
1933 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1934 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1942 void PF_changelevel (void)
1946 // make sure we don't issue two changelevels
1947 if (svs.changelevel_issued)
1949 svs.changelevel_issued = true;
1951 s = PRVM_G_STRING(OFS_PARM0);
1952 Cbuf_AddText (va("changelevel %s\n",s));
1957 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1962 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1967 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1974 Returns a vector of length < 1
1979 void PF_randomvec (void)
1984 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1985 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1986 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1988 while (DotProduct(temp, temp) >= 1);
1989 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1996 Returns a color vector indicating the lighting at the requested point.
1998 (Internal Operation note: actually measures the light beneath the point, just like
1999 the model lighting on the client)
2004 void PF_GetLight (void)
2006 vec3_t ambientcolor, diffusecolor, diffusenormal;
2008 p = PRVM_G_VECTOR(OFS_PARM0);
2009 VectorClear(ambientcolor);
2010 VectorClear(diffusecolor);
2011 VectorClear(diffusenormal);
2012 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2013 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2014 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
2017 void PF_registercvar (void)
2019 const char *name, *value;
2020 name = PRVM_G_STRING(OFS_PARM0);
2021 value = PRVM_G_STRING(OFS_PARM1);
2022 PRVM_G_FLOAT(OFS_RETURN) = 0;
2024 // first check to see if it has already been defined
2025 if (Cvar_FindVar (name))
2028 // check for overlap with a command
2029 if (Cmd_Exists (name))
2031 Con_Printf("PF_registercvar: %s is a command\n", name);
2035 Cvar_Get(name, value, 0);
2037 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
2044 returns the minimum of two supplied floats
2051 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2053 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2054 else if (pr_argc >= 3)
2057 float f = PRVM_G_FLOAT(OFS_PARM0);
2058 for (i = 1;i < pr_argc;i++)
2059 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
2060 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
2061 PRVM_G_FLOAT(OFS_RETURN) = f;
2065 PRVM_G_FLOAT(OFS_RETURN) = 0;
2066 PF_WARNING("min: must supply at least 2 floats\n");
2074 returns the maximum of two supplied floats
2081 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2083 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2084 else if (pr_argc >= 3)
2087 float f = PRVM_G_FLOAT(OFS_PARM0);
2088 for (i = 1;i < pr_argc;i++)
2089 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
2090 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
2091 PRVM_G_FLOAT(OFS_RETURN) = f;
2095 PRVM_G_FLOAT(OFS_RETURN) = 0;
2096 PF_WARNING("max: must supply at least 2 floats\n");
2104 returns number bounded by supplied range
2106 min(min, value, max)
2109 void PF_bound (void)
2111 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
2118 returns a raised to power b
2125 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2132 copies data from one entity to another
2134 copyentity(src, dst)
2137 void PF_copyentity (void)
2139 prvm_edict_t *in, *out;
2140 in = PRVM_G_EDICT(OFS_PARM0);
2141 if (in == prog->edicts)
2142 PF_WARNING("copyentity: can not read world entity\n");
2143 if (in->priv.server->free)
2144 PF_WARNING("copyentity: can not read free entity\n");
2145 out = PRVM_G_EDICT(OFS_PARM1);
2146 if (out == prog->edicts)
2147 PF_WARNING("copyentity: can not modify world entity\n");
2148 if (out->priv.server->free)
2149 PF_WARNING("copyentity: can not modify free entity\n");
2150 memcpy(out->v, in->v, progs->entityfields * 4);
2157 sets the color of a client and broadcasts the update to all connected clients
2159 setcolor(clientent, value)
2162 void PF_setcolor (void)
2168 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
2169 i = PRVM_G_FLOAT(OFS_PARM1);
2171 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2173 Con_Print("tried to setcolor a non-client\n");
2177 client = svs.clients + entnum-1;
2180 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2182 client->edict->fields.server->team = (i & 15) + 1;
2185 if (client->old_colors != client->colors)
2187 client->old_colors = client->colors;
2188 // send notification to all clients
2189 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2190 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
2191 MSG_WriteByte (&sv.reliable_datagram, client->colors);
2199 effect(origin, modelname, startframe, framecount, framerate)
2202 void PF_effect (void)
2206 s = PRVM_G_STRING(OFS_PARM1);
2208 PF_WARNING("effect: no model specified\n");
2210 i = SV_ModelIndex(s, 1);
2212 PF_WARNING("effect: model not precached\n");
2213 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
2216 void PF_te_blood (void)
2218 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2220 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2221 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2223 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2224 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2225 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2227 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2228 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2229 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2231 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2234 void PF_te_bloodshower (void)
2236 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2238 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2239 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2241 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2242 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2243 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2247 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
2251 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2254 void PF_te_explosionrgb (void)
2256 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2257 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2259 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2260 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2261 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2263 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
2264 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
2265 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
2268 void PF_te_particlecube (void)
2270 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2272 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2273 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2275 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2276 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2277 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2281 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2285 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2287 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2289 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2290 // gravity true/false
2291 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2293 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2296 void PF_te_particlerain (void)
2298 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2300 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2301 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2303 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2304 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2305 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2309 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2313 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2315 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2317 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2320 void PF_te_particlesnow (void)
2322 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2324 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2325 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2327 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2328 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2329 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2333 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2337 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2339 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2341 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2344 void PF_te_spark (void)
2346 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2348 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2349 MSG_WriteByte(&sv.datagram, TE_SPARK);
2351 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2352 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2353 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2355 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2356 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2357 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2359 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2362 void PF_te_gunshotquad (void)
2364 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2365 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2367 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2368 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2369 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2372 void PF_te_spikequad (void)
2374 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2375 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2377 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2378 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2379 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2382 void PF_te_superspikequad (void)
2384 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2385 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2387 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2388 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2389 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2392 void PF_te_explosionquad (void)
2394 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2395 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2397 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2398 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2399 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2402 void PF_te_smallflash (void)
2404 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2405 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2407 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2408 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2409 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2412 void PF_te_customflash (void)
2414 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2416 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2417 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2419 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2420 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2421 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2423 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2425 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2427 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2428 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2429 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2432 void PF_te_gunshot (void)
2434 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2435 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2437 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2438 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2439 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2442 void PF_te_spike (void)
2444 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2445 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2447 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2448 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2449 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2452 void PF_te_superspike (void)
2454 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2455 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2457 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2458 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2459 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2462 void PF_te_explosion (void)
2464 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2465 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2467 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2468 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2469 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2472 void PF_te_tarexplosion (void)
2474 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2475 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2477 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2478 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2479 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2482 void PF_te_wizspike (void)
2484 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2485 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2487 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2488 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2489 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2492 void PF_te_knightspike (void)
2494 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2495 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2497 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2498 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2499 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2502 void PF_te_lavasplash (void)
2504 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2505 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2507 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2508 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2509 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2512 void PF_te_teleport (void)
2514 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2515 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2517 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2518 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2519 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2522 void PF_te_explosion2 (void)
2524 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2525 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2527 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2528 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2529 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2531 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
2532 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
2535 void PF_te_lightning1 (void)
2537 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2538 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2540 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2542 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2543 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2544 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2548 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2551 void PF_te_lightning2 (void)
2553 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2554 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2556 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2558 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2559 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2560 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2564 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2567 void PF_te_lightning3 (void)
2569 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2570 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2572 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2574 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2575 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2576 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2578 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2579 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2580 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2583 void PF_te_beam (void)
2585 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2586 MSG_WriteByte(&sv.datagram, TE_BEAM);
2588 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2590 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2591 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2592 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2594 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2595 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2596 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2599 void PF_te_plasmaburn (void)
2601 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2602 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2603 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2604 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2605 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2608 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
2611 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2613 bestdist = 1000000000;
2615 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2617 // clip original point to each triangle of the surface and find the
2618 // triangle that is closest
2619 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
2620 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
2621 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
2622 TriangleNormal(v[0], v[1], v[2], facenormal);
2623 VectorNormalize(facenormal);
2624 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2625 VectorMA(p, offsetdist, facenormal, temp);
2626 for (j = 0, k = 2;j < 3;k = j, j++)
2628 VectorSubtract(v[k], v[j], edgenormal);
2629 CrossProduct(edgenormal, facenormal, sidenormal);
2630 VectorNormalize(sidenormal);
2631 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2633 VectorMA(temp, offsetdist, sidenormal, temp);
2635 dist = VectorDistance2(temp, p);
2636 if (bestdist > dist)
2639 VectorCopy(temp, out);
2644 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2648 if (!ed || ed->priv.server->free)
2650 modelindex = ed->fields.server->modelindex;
2651 if (modelindex < 1 || modelindex >= MAX_MODELS)
2653 model = sv.models[modelindex];
2654 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2656 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2660 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2661 void PF_getsurfacenumpoints(void)
2663 msurface_t *surface;
2664 // return 0 if no such surface
2665 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2667 PRVM_G_FLOAT(OFS_RETURN) = 0;
2671 // note: this (incorrectly) assumes it is a simple polygon
2672 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2674 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2675 void PF_getsurfacepoint(void)
2678 msurface_t *surface;
2680 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2681 ed = PRVM_G_EDICT(OFS_PARM0);
2682 if (!ed || ed->priv.server->free)
2684 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2686 // note: this (incorrectly) assumes it is a simple polygon
2687 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2688 if (pointnum < 0 || pointnum >= surface->num_vertices)
2690 // FIXME: implement rotation/scaling
2691 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2693 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2694 void PF_getsurfacenormal(void)
2696 msurface_t *surface;
2698 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2699 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2701 // FIXME: implement rotation/scaling
2702 // note: this (incorrectly) assumes it is a simple polygon
2703 // note: this only returns the first triangle, so it doesn't work very
2704 // well for curved surfaces or arbitrary meshes
2705 TriangleNormal((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 3, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal);
2706 VectorNormalize(normal);
2707 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2709 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2710 void PF_getsurfacetexture(void)
2712 msurface_t *surface;
2713 PRVM_G_INT(OFS_RETURN) = 0;
2714 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2716 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2718 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2719 void PF_getsurfacenearpoint(void)
2721 int surfacenum, best, modelindex;
2723 vec_t dist, bestdist;
2726 msurface_t *surface;
2728 PRVM_G_FLOAT(OFS_RETURN) = -1;
2729 ed = PRVM_G_EDICT(OFS_PARM0);
2730 point = PRVM_G_VECTOR(OFS_PARM1);
2732 if (!ed || ed->priv.server->free)
2734 modelindex = ed->fields.server->modelindex;
2735 if (modelindex < 1 || modelindex >= MAX_MODELS)
2737 model = sv.models[modelindex];
2738 if (!model->num_surfaces)
2741 // FIXME: implement rotation/scaling
2742 VectorSubtract(point, ed->fields.server->origin, p);
2744 bestdist = 1000000000;
2745 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2747 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2748 // first see if the nearest point on the surface's box is closer than the previous match
2749 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2750 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2751 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2752 dist = VectorLength2(clipped);
2753 if (dist < bestdist)
2755 // it is, check the nearest point on the actual geometry
2756 clippointtosurface(surface, p, clipped);
2757 VectorSubtract(clipped, p, clipped);
2758 dist += VectorLength2(clipped);
2759 if (dist < bestdist)
2761 // that's closer too, store it as the best match
2767 PRVM_G_FLOAT(OFS_RETURN) = best;
2769 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2770 void PF_getsurfaceclippedpoint(void)
2773 msurface_t *surface;
2775 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2776 ed = PRVM_G_EDICT(OFS_PARM0);
2777 if (!ed || ed->priv.server->free)
2779 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2781 // FIXME: implement rotation/scaling
2782 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2783 clippointtosurface(surface, p, out);
2784 // FIXME: implement rotation/scaling
2785 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2788 #define MAX_PRFILES 256
2790 qfile_t *pr_files[MAX_PRFILES];
2792 void PR_Files_Init(void)
2794 memset(pr_files, 0, sizeof(pr_files));
2797 void PR_Files_CloseAll(void)
2800 for (i = 0;i < MAX_PRFILES;i++)
2803 FS_Close(pr_files[i]);
2808 //float(string s) stof = #81; // get numerical value from a string
2811 char string[STRINGTEMP_LENGTH];
2812 PF_VarString(0, string, sizeof(string));
2813 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
2816 //float(string filename, float mode) fopen = #110; // opens a file inside quake/gamedir/data/ (mode is FILE_READ, FILE_APPEND, or FILE_WRITE), returns fhandle >= 0 if successful, or fhandle < 0 if unable to open file for any reason
2820 const char *modestring, *filename;
2821 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2822 if (pr_files[filenum] == NULL)
2824 if (filenum >= MAX_PRFILES)
2826 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2827 PRVM_G_FLOAT(OFS_RETURN) = -2;
2830 mode = PRVM_G_FLOAT(OFS_PARM1);
2833 case 0: // FILE_READ
2836 case 1: // FILE_APPEND
2839 case 2: // FILE_WRITE
2843 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2844 PRVM_G_FLOAT(OFS_RETURN) = -3;
2847 filename = PRVM_G_STRING(OFS_PARM0);
2848 // -4 failure (dangerous/non-portable filename) removed, FS_Open checks
2849 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
2851 if (pr_files[filenum] == NULL && modestring == "rb")
2852 pr_files[filenum] = FS_Open(filename, modestring, false, false);
2854 if (pr_files[filenum] == NULL)
2855 PRVM_G_FLOAT(OFS_RETURN) = -1;
2857 PRVM_G_FLOAT(OFS_RETURN) = filenum;
2860 //void(float fhandle) fclose = #111; // closes a file
2861 void PF_fclose(void)
2863 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2864 if (filenum < 0 || filenum >= MAX_PRFILES)
2866 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2869 if (pr_files[filenum] == NULL)
2871 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2874 FS_Close(pr_files[filenum]);
2875 pr_files[filenum] = NULL;
2878 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2882 static char string[STRINGTEMP_LENGTH];
2883 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2884 if (filenum < 0 || filenum >= MAX_PRFILES)
2886 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2889 if (pr_files[filenum] == NULL)
2891 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2897 c = FS_Getc(pr_files[filenum]);
2898 if (c == '\r' || c == '\n' || c < 0)
2900 if (end < STRINGTEMP_LENGTH - 1)
2904 // remove \n following \r
2907 c = FS_Getc(pr_files[filenum]);
2909 FS_UnGetc(pr_files[filenum], (unsigned char)c);
2911 if (developer.integer)
2912 Con_Printf("fgets: %s\n", string);
2914 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
2916 PRVM_G_INT(OFS_RETURN) = 0;
2919 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2923 char string[STRINGTEMP_LENGTH];
2924 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2925 if (filenum < 0 || filenum >= MAX_PRFILES)
2927 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2930 if (pr_files[filenum] == NULL)
2932 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2935 PF_VarString(1, string, sizeof(string));
2936 if ((stringlength = strlen(string)))
2937 FS_Write(pr_files[filenum], string, stringlength);
2938 if (developer.integer)
2939 Con_Printf("fputs: %s\n", string);
2942 //float(string s) strlen = #114; // returns how many characters are in a string
2943 void PF_strlen(void)
2946 s = PRVM_G_STRING(OFS_PARM0);
2948 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
2950 PRVM_G_FLOAT(OFS_RETURN) = 0;
2953 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2954 void PF_strcat(void)
2956 char *s = PR_GetTempString();
2957 PF_VarString(0, s, STRINGTEMP_LENGTH);
2958 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
2961 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2962 void PF_substring(void)
2964 int i, start, length;
2966 char *string = PR_GetTempString();
2967 s = PRVM_G_STRING(OFS_PARM0);
2968 start = PRVM_G_FLOAT(OFS_PARM1);
2969 length = PRVM_G_FLOAT(OFS_PARM2);
2972 for (i = 0;i < start && *s;i++, s++);
2973 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2976 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
2979 //vector(string s) stov = #117; // returns vector value from a string
2982 char string[STRINGTEMP_LENGTH];
2983 PF_VarString(0, string, sizeof(string));
2984 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
2987 //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)
2988 void PF_strzone(void)
2992 in = PRVM_G_STRING(OFS_PARM0);
2993 out = PR_AllocString(strlen(in) + 1);
2995 PRVM_G_INT(OFS_RETURN) = PR_SetQCString(out);
2998 //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!!!)
2999 void PF_strunzone(void)
3001 PR_FreeString((char *)PRVM_G_STRING(OFS_PARM0));
3004 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3005 //this function originally written by KrimZon, made shorter by LordHavoc
3006 void PF_clientcommand (void)
3008 client_t *temp_client;
3011 //find client for this entity
3012 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
3013 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3015 Con_Print("PF_clientcommand: entity is not a client\n");
3019 temp_client = host_client;
3020 host_client = svs.clients + i;
3021 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
3022 host_client = temp_client;
3025 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3026 //this function originally written by KrimZon, made shorter by LordHavoc
3027 //20040203: rewritten by LordHavoc (no longer uses allocations)
3029 char *tokens[256], tokenbuf[4096];
3030 void PF_tokenize (void)
3034 p = PRVM_G_STRING(OFS_PARM0);
3038 while(COM_ParseToken(&p, false))
3040 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3042 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3044 tokens[num_tokens++] = tokenbuf + pos;
3045 strcpy(tokenbuf + pos, com_token);
3046 pos += strlen(com_token) + 1;
3049 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
3052 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3053 //this function originally written by KrimZon, made shorter by LordHavoc
3056 int token_num = PRVM_G_FLOAT(OFS_PARM0);
3057 if (token_num >= 0 && token_num < num_tokens)
3058 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]);
3060 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
3063 //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)
3064 void PF_setattachment (void)
3066 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
3067 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
3068 const char *tagname = PRVM_G_STRING(OFS_PARM2);
3073 if (e == prog->edicts)
3074 PF_WARNING("setattachment: can not modify world entity\n");
3075 if (e->priv.server->free)
3076 PF_WARNING("setattachment: can not modify free entity\n");
3078 if (tagentity == NULL)
3079 tagentity = prog->edicts;
3081 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
3083 fields.server->edict = PRVM_EDICT_TO_PROG(tagentity);
3085 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
3087 fields.server->_float = 0;
3088 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
3090 modelindex = (int)tagentity->fields.server->modelindex;
3091 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3093 fields.server->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
3094 if (fields.server->_float == 0)
3095 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", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity), model->name);
3098 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", PRVM_NUM_FOR_EDICT(e), PRVM_NUM_FOR_EDICT(tagentity), tagname, tagname, PRVM_NUM_FOR_EDICT(tagentity));
3102 /////////////////////////////////////////
3103 // DP_MD3_TAGINFO extension coded by VorteX
3105 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
3110 i = e->fields.server->modelindex;
3111 if (i < 1 || i >= MAX_MODELS)
3113 model = sv.models[i];
3115 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
3118 // Warnings/errors code:
3119 // 0 - normal (everything all-right)
3122 // 3 - null or non-precached model
3123 // 4 - no tags with requested index
3124 // 5 - runaway loop at attachment chain
3125 extern cvar_t cl_bob;
3126 extern cvar_t cl_bobcycle;
3127 extern cvar_t cl_bobup;
3128 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
3131 int modelindex, reqframe, attachloop;
3132 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
3133 prvm_edict_t *attachent;
3136 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
3138 if (ent == prog->edicts)
3140 if (ent->priv.server->free)
3143 modelindex = (int)ent->fields.server->modelindex;
3144 if (modelindex <= 0 || modelindex > MAX_MODELS)
3147 model = sv.models[modelindex];
3149 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
3150 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
3152 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
3154 // get initial tag matrix
3157 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
3162 Matrix4x4_CreateIdentity(&tagmatrix);
3164 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
3165 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
3169 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
3170 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
3171 if (val->_float >= 1 && attachent->fields.server->modelindex >= 1 && attachent->fields.server->modelindex < MAX_MODELS && (model = sv.models[(int)attachent->fields.server->modelindex]) && model->animscenes && attachent->fields.server->frame >= 0 && attachent->fields.server->frame < model->numframes)
3172 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
3174 Matrix4x4_CreateIdentity(&attachmatrix);
3176 // apply transformation by child entity matrix
3177 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3178 if (val->_float == 0)
3180 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], val->_float);
3181 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3182 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
3183 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
3184 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
3185 Matrix4x4_Copy(&tagmatrix, out);
3187 // finally transformate by matrix of tag on parent entity
3188 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
3189 out->m[0][3] = attachmatrix.m[0][3] + attachmatrix.m[0][0]*tagmatrix.m[0][3] + attachmatrix.m[0][1]*tagmatrix.m[1][3] + attachmatrix.m[0][2]*tagmatrix.m[2][3];
3190 out->m[1][3] = attachmatrix.m[1][3] + attachmatrix.m[1][0]*tagmatrix.m[0][3] + attachmatrix.m[1][1]*tagmatrix.m[1][3] + attachmatrix.m[1][2]*tagmatrix.m[2][3];
3191 out->m[2][3] = attachmatrix.m[2][3] + attachmatrix.m[2][0]*tagmatrix.m[0][3] + attachmatrix.m[2][1]*tagmatrix.m[1][3] + attachmatrix.m[2][2]*tagmatrix.m[2][3];
3192 Matrix4x4_Copy(&tagmatrix, out);
3196 if (attachloop > 255) // prevent runaway looping
3199 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
3202 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
3203 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3204 if (val->_float == 0)
3206 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
3207 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], -ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], val->_float);
3208 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3209 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
3210 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
3211 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
3213 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
3214 {// RENDER_VIEWMODEL magic
3215 Matrix4x4_Copy(&tagmatrix, out);
3216 ent = PRVM_EDICT_NUM(val->edict);
3218 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3219 if (val->_float == 0)
3222 Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], val->_float);
3223 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3224 out->m[0][3] = entitymatrix.m[0][3] + val->_float*(entitymatrix.m[0][0]*tagmatrix.m[0][3] + entitymatrix.m[0][1]*tagmatrix.m[1][3] + entitymatrix.m[0][2]*tagmatrix.m[2][3]);
3225 out->m[1][3] = entitymatrix.m[1][3] + val->_float*(entitymatrix.m[1][0]*tagmatrix.m[0][3] + entitymatrix.m[1][1]*tagmatrix.m[1][3] + entitymatrix.m[1][2]*tagmatrix.m[2][3]);
3226 out->m[2][3] = entitymatrix.m[2][3] + val->_float*(entitymatrix.m[2][0]*tagmatrix.m[0][3] + entitymatrix.m[2][1]*tagmatrix.m[1][3] + entitymatrix.m[2][2]*tagmatrix.m[2][3]);
3229 // Cl_bob, ported from rendering code
3230 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
3233 // LordHavoc: this code is *weird*, but not replacable (I think it
3234 // should be done in QC on the server, but oh well, quake is quake)
3235 // LordHavoc: figured out bobup: the time at which the sin is at 180
3236 // degrees (which allows lengthening or squishing the peak or valley)
3237 cycle = sv.time/cl_bobcycle.value;
3238 cycle -= (int)cycle;
3239 if (cycle < cl_bobup.value)
3240 cycle = sin(M_PI * cycle / cl_bobup.value);
3242 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
3243 // bob is proportional to velocity in the xy plane
3244 // (don't count Z, or jumping messes it up)
3245 bob = sqrt(ent->fields.server->velocity[0]*ent->fields.server->velocity[0] + ent->fields.server->velocity[1]*ent->fields.server->velocity[1])*cl_bob.value;
3246 bob = bob*0.3 + bob*0.7*cycle;
3247 out->m[2][3] += bound(-7, bob, 4);
3254 //float(entity ent, string tagname) gettagindex;
3256 void PF_gettagindex (void)
3258 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
3259 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
3260 int modelindex, tag_index;
3262 if (ent == prog->edicts)
3263 PF_WARNING("gettagindex: can't affect world entity\n");
3264 if (ent->priv.server->free)
3265 PF_WARNING("gettagindex: can't affect free entity\n");
3267 modelindex = (int)ent->fields.server->modelindex;
3269 if (modelindex <= 0 || modelindex > MAX_MODELS)
3270 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
3273 tag_index = SV_GetTagIndex(ent, tag_name);
3275 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
3277 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
3280 //vector(entity ent, float tagindex) gettaginfo;
3281 void PF_gettaginfo (void)
3283 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
3284 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
3285 matrix4x4_t tag_matrix;
3288 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
3289 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
3294 PF_WARNING("gettagindex: can't affect world entity\n");
3297 PF_WARNING("gettagindex: can't affect free entity\n");
3300 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
3303 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
3306 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
3312 /////////////////////////////////////////
3313 // DP_QC_FS_SEARCH extension
3315 // qc fs search handling
3316 #define MAX_SEARCHES 128
3318 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3320 void PR_Search_Init(void)
3322 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3325 void PR_Search_Reset(void)
3328 // reset the fssearch list
3329 for(i = 0; i < MAX_SEARCHES; i++)
3330 if(pr_fssearchlist[i])
3331 FS_FreeSearch(pr_fssearchlist[i]);
3332 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3339 float search_begin(string pattern, float caseinsensitive, float quiet)
3342 void PF_search_begin(void)
3345 const char *pattern;
3346 int caseinsens, quiet;
3348 pattern = PRVM_G_STRING(OFS_PARM0);
3349 if (!pattern || pattern[0] <= ' ')
3350 PF_ERROR("PF_search_begin: Bad string");
3352 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
3353 quiet = PRVM_G_FLOAT(OFS_PARM2);
3355 for(handle = 0; handle < MAX_SEARCHES; handle++)
3356 if(!pr_fssearchlist[handle])
3359 if(handle >= MAX_SEARCHES)
3361 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3362 PRVM_G_FLOAT(OFS_RETURN) = -2;
3366 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3367 PRVM_G_FLOAT(OFS_RETURN) = -1;
3369 PRVM_G_FLOAT(OFS_RETURN) = handle;
3376 void search_end(float handle)
3379 void PF_search_end(void)
3383 handle = PRVM_G_FLOAT(OFS_PARM0);
3385 if(handle < 0 || handle >= MAX_SEARCHES)
3387 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3390 if(pr_fssearchlist[handle] == NULL)
3392 Con_Printf("PF_search_end: no such handle %i\n", handle);
3396 FS_FreeSearch(pr_fssearchlist[handle]);
3397 pr_fssearchlist[handle] = NULL;
3404 float search_getsize(float handle)
3407 void PF_search_getsize(void)
3411 handle = PRVM_G_FLOAT(OFS_PARM0);
3413 if(handle < 0 || handle >= MAX_SEARCHES)
3415 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3418 if(pr_fssearchlist[handle] == NULL)
3420 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3424 PRVM_G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3429 VM_search_getfilename
3431 string search_getfilename(float handle, float num)
3434 void PF_search_getfilename(void)
3436 int handle, filenum;
3439 handle = PRVM_G_FLOAT(OFS_PARM0);
3440 filenum = PRVM_G_FLOAT(OFS_PARM1);
3442 if(handle < 0 || handle >= MAX_SEARCHES)
3444 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3447 if(pr_fssearchlist[handle] == NULL)
3449 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3452 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3454 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3458 tmp = PR_GetTempString();
3459 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3461 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3464 void PF_cvar_string (void)
3470 str = PRVM_G_STRING(OFS_PARM0);
3471 var = Cvar_FindVar (str);
3474 tmp = PR_GetTempString();
3475 strcpy(tmp, var->string);
3479 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3482 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
3483 void PF_dropclient (void)
3486 client_t *oldhostclient;
3487 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
3488 if (clientnum < 0 || clientnum >= svs.maxclients)
3489 PF_WARNING("dropclient: not a client\n");
3490 if (!svs.clients[clientnum].active)
3491 PF_WARNING("dropclient: that client slot is not connected\n");
3492 oldhostclient = host_client;
3493 host_client = svs.clients + clientnum;
3494 SV_DropClient(false);
3495 host_client = oldhostclient;
3498 //entity() spawnclient (DP_SV_BOTCLIENT)
3499 void PF_spawnclient (void)
3503 pr_xfunction->builtinsprofile += 2;
3505 for (i = 0;i < svs.maxclients;i++)
3507 if (!svs.clients[i].active)
3509 pr_xfunction->builtinsprofile += 100;
3510 SV_ConnectClient (i, NULL);
3511 ed = PRVM_EDICT_NUM(i + 1);
3518 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
3519 void PF_clienttype (void)
3522 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
3523 if (clientnum < 0 || clientnum >= svs.maxclients)
3524 PRVM_G_FLOAT(OFS_RETURN) = 3;
3525 else if (!svs.clients[clientnum].active)
3526 PRVM_G_FLOAT(OFS_RETURN) = 0;
3527 else if (svs.clients[clientnum].netconnection)
3528 PRVM_G_FLOAT(OFS_RETURN) = 1;
3530 PRVM_G_FLOAT(OFS_RETURN) = 2;
3533 builtin_t pr_builtin[] =
3536 PF_makevectors, // #1 void(entity e) makevectors
3537 PF_setorigin, // #2 void(entity e, vector o) setorigin
3538 PF_setmodel, // #3 void(entity e, string m) setmodel
3539 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3540 NULL, // #5 void(entity e, vector min, vector max) setabssize
3541 PF_break, // #6 void() break
3542 PF_random, // #7 float() random
3543 PF_sound, // #8 void(entity e, float chan, string samp) sound
3544 PF_normalize, // #9 vector(vector v) normalize
3545 PF_error, // #10 void(string e) error
3546 PF_objerror, // #11 void(string e) objerror
3547 PF_vlen, // #12 float(vector v) vlen
3548 PF_vectoyaw, // #13 float(vector v) vectoyaw
3549 PF_Spawn, // #14 entity() spawn
3550 PF_Remove, // #15 void(entity e) remove
3551 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3552 PF_checkclient, // #17 entity() clientlist
3553 PF_Find, // #18 entity(entity start, .string fld, string match) find
3554 PF_precache_sound, // #19 void(string s) precache_sound
3555 PF_precache_model, // #20 void(string s) precache_model
3556 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3557 PF_findradius, // #22 entity(vector org, float rad) findradius
3558 PF_bprint, // #23 void(string s) bprint
3559 PF_sprint, // #24 void(entity client, string s) sprint
3560 PF_dprint, // #25 void(string s) dprint
3561 PF_ftos, // #26 void(string s) ftos
3562 PF_vtos, // #27 void(string s) vtos
3563 PF_coredump, // #28 void() coredump
3564 PF_traceon, // #29 void() traceon
3565 PF_traceoff, // #30 void() traceoff
3566 PF_eprint, // #31 void(entity e) eprint
3567 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3569 PF_droptofloor, // #34 float() droptofloor
3570 PF_lightstyle, // #35 void(float style, string value) lightstyle
3571 PF_rint, // #36 float(float v) rint
3572 PF_floor, // #37 float(float v) floor
3573 PF_ceil, // #38 float(float v) ceil
3575 PF_checkbottom, // #40 float(entity e) checkbottom
3576 PF_pointcontents, // #41 float(vector v) pointcontents
3578 PF_fabs, // #43 float(float f) fabs
3579 PF_aim, // #44 vector(entity e, float speed) aim
3580 PF_cvar, // #45 float(string s) cvar
3581 PF_localcmd, // #46 void(string s) localcmd
3582 PF_nextent, // #47 entity(entity e) nextent
3583 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3584 PF_changeyaw, // #49 void() ChangeYaw
3586 PF_vectoangles, // #51 vector(vector v) vectoangles
3587 PF_WriteByte, // #52 void(float to, float f) WriteByte
3588 PF_WriteChar, // #53 void(float to, float f) WriteChar
3589 PF_WriteShort, // #54 void(float to, float f) WriteShort
3590 PF_WriteLong, // #55 void(float to, float f) WriteLong
3591 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3592 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3593 PF_WriteString, // #58 void(float to, string s) WriteString
3594 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3595 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3596 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3597 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3598 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3599 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3600 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3602 SV_MoveToGoal, // #67 void(float step) movetogoal
3603 PF_precache_file, // #68 string(string s) precache_file
3604 PF_makestatic, // #69 void(entity e) makestatic
3605 PF_changelevel, // #70 void(string s) changelevel
3607 PF_cvar_set, // #72 void(string var, string val) cvar_set
3608 PF_centerprint, // #73 void(entity client, strings) centerprint
3609 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3610 PF_precache_model, // #75 string(string s) precache_model2
3611 PF_precache_sound, // #76 string(string s) precache_sound2
3612 PF_precache_file, // #77 string(string s) precache_file2
3613 PF_setspawnparms, // #78 void(entity e) setspawnparms
3616 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3625 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3626 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3627 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3628 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3629 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3630 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3631 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3632 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3633 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3634 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3645 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3646 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3647 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3648 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3649 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3650 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3651 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3652 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3653 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3654 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3655 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3656 a a a a a a a a // #120-199
3657 a a a a a a a a a a // #200-299
3658 a a a a a a a a a a // #300-399
3659 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3660 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3661 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3662 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3663 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3664 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3665 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3666 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3667 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3668 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3669 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3670 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3671 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3672 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3673 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3674 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3675 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3676 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3677 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3678 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3679 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3680 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3681 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3682 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3683 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3684 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3685 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3686 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3687 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3688 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3689 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3690 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3691 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3692 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3693 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3694 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3695 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3696 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3697 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3698 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3699 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3700 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3701 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3702 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3703 PF_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
3704 PF_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
3705 PF_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
3706 PF_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
3707 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3708 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3709 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3710 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3711 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3712 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3713 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3714 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3719 a a a a // #460-499 (LordHavoc)
3722 builtin_t *pr_builtins = pr_builtin;
3723 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3725 void PR_Cmd_Init(void)
3731 void PR_Cmd_Shutdown(void)
3735 void PR_Cmd_Reset(void)
3738 PR_Files_CloseAll();