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 MAX_INPUTLINE
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 =
88 "DP_ENT_CUSTOMCOLORMAP "
89 "DP_ENT_EXTERIORMODELTOCLIENT "
91 "DP_ENT_LOWPRECISION "
94 "DP_GFX_EXTERNALTEXTURES "
96 "DP_GFX_QUAKE3MODELTAGS "
100 "DP_HALFLIFE_MAP_CVAR "
101 "DP_HALFLIFE_SPRITE "
106 "DP_MOVETYPEBOUNCEMISSILE "
113 "DP_QC_FINDCHAINFLAGS "
114 "DP_QC_FINDCHAINFLOAT "
117 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
122 "DP_QC_MULTIPLETEMPSTRINGS "
124 "DP_QC_SINCOSSQRTPOW "
127 "DP_QC_TRACE_MOVETYPE_HITMODEL "
128 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
129 "DP_QC_VECTORVECTORS "
135 "DP_SND_DIRECTIONLESSATTNNONE "
142 "DP_SV_CLIENTCOLORS "
144 "DP_SV_DRAWONLYTOCLIENT "
147 "DP_SV_NODRAWTOCLIENT "
149 "DP_SV_PLAYERPHYSICS "
150 "DP_SV_PRECACHEANYTIME "
152 "DP_SV_ROTATINGBMODEL "
158 "DP_TE_EXPLOSIONRGB "
160 "DP_TE_PARTICLECUBE "
161 "DP_TE_PARTICLERAIN "
162 "DP_TE_PARTICLESNOW "
164 "DP_TE_QUADEFFECTS1 "
167 "DP_TE_STANDARDEFFECTBUILTINS "
170 "KRIMZON_SV_PARSECLIENTCOMMAND "
174 "PRYDON_CLIENTCURSOR "
175 "TENEBRAE_GFX_DLIGHTS "
177 "NEXUIZ_PLAYERMODEL "
180 qboolean checkextension(const char *name)
185 for (e = ENGINE_EXTENSIONS;*e;e++)
192 while (*e && *e != ' ')
194 if (e - start == len)
195 if (!strncasecmp(start, name, len))
205 returns true if the extension is supported by the server
207 checkextension(extensionname)
210 void PF_checkextension (void)
212 PRVM_G_FLOAT(OFS_RETURN) = checkextension(PRVM_G_STRING(OFS_PARM0));
219 This is a TERMINAL error, which will kill off the entire server.
228 char string[STRINGTEMP_LENGTH];
230 PF_VarString(0, string, sizeof(string));
231 Con_Printf("======SERVER ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string);
232 ed = PRVM_PROG_TO_EDICT(prog->globals.server->self);
235 PF_ERROR("Program error");
242 Dumps out self, then an error message. The program is aborted and self is
243 removed, but the level can continue.
248 void PF_objerror (void)
251 char string[STRINGTEMP_LENGTH];
253 PF_VarString(0, string, sizeof(string));
254 Con_Printf("======OBJECT ERROR in %s:\n%s\n", PRVM_GetString(pr_xfunction->s_name), string);
255 ed = PRVM_PROG_TO_EDICT(prog->globals.server->self);
265 Writes new values for v_forward, v_up, and v_right based on angles
269 void PF_makevectors (void)
271 AngleVectors (PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
278 Writes new values for v_forward, v_up, and v_right based on the given forward vector
279 vectorvectors(vector, vector)
282 void PF_vectorvectors (void)
284 VectorNormalize2(PRVM_G_VECTOR(OFS_PARM0), prog->globals.server->v_forward);
285 VectorVectors(prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up);
292 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.
294 setorigin (entity, origin)
297 void PF_setorigin (void)
302 e = PRVM_G_EDICT(OFS_PARM0);
303 if (e == prog->edicts)
304 PF_WARNING("setorigin: can not modify world entity\n");
305 if (e->priv.server->free)
306 PF_WARNING("setorigin: can not modify free entity\n");
307 org = PRVM_G_VECTOR(OFS_PARM1);
308 VectorCopy (org, e->fields.server->origin);
309 SV_LinkEdict (e, false);
313 void SetMinMaxSize (prvm_edict_t *e, float *min, float *max, qboolean rotate)
317 for (i=0 ; i<3 ; i++)
319 PF_ERROR("SetMinMaxSize: backwards mins/maxs");
321 // set derived values
322 VectorCopy (min, e->fields.server->mins);
323 VectorCopy (max, e->fields.server->maxs);
324 VectorSubtract (max, min, e->fields.server->size);
326 SV_LinkEdict (e, false);
333 the size box is rotated by the current angle
334 LordHavoc: no it isn't...
336 setsize (entity, minvector, maxvector)
339 void PF_setsize (void)
344 e = PRVM_G_EDICT(OFS_PARM0);
345 if (e == prog->edicts)
346 PF_WARNING("setsize: can not modify world entity\n");
347 if (e->priv.server->free)
348 PF_WARNING("setsize: can not modify free entity\n");
349 min = PRVM_G_VECTOR(OFS_PARM1);
350 max = PRVM_G_VECTOR(OFS_PARM2);
351 SetMinMaxSize (e, min, max, false);
359 setmodel(entity, model)
362 static vec3_t quakemins = {-16, -16, -16}, quakemaxs = {16, 16, 16};
363 void PF_setmodel (void)
369 e = PRVM_G_EDICT(OFS_PARM0);
370 if (e == prog->edicts)
371 PF_WARNING("setmodel: can not modify world entity\n");
372 if (e->priv.server->free)
373 PF_WARNING("setmodel: can not modify free entity\n");
374 i = SV_ModelIndex(PRVM_G_STRING(OFS_PARM1), 1);
375 e->fields.server->model = PRVM_SetEngineString(sv.model_precache[i]);
376 e->fields.server->modelindex = i;
382 if (mod->type != mod_alias || sv_gameplayfix_setmodelrealbox.integer)
383 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
385 SetMinMaxSize (e, quakemins, quakemaxs, true);
388 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
395 broadcast print to everyone on server
400 void PF_bprint (void)
402 char string[STRINGTEMP_LENGTH];
403 PF_VarString(0, string, sizeof(string));
404 SV_BroadcastPrint(string);
411 single print to a specific client
413 sprint(clientent, value)
416 void PF_sprint (void)
420 char string[STRINGTEMP_LENGTH];
422 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
424 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
426 Con_Print("tried to sprint to a non-client\n");
430 client = svs.clients + entnum-1;
431 PF_VarString(1, string, sizeof(string));
432 MSG_WriteChar(&client->message,svc_print);
433 MSG_WriteString(&client->message, string);
441 single print to a specific client
443 centerprint(clientent, value)
446 void PF_centerprint (void)
450 char string[STRINGTEMP_LENGTH];
452 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
454 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
456 Con_Print("tried to sprint to a non-client\n");
460 client = svs.clients + entnum-1;
461 PF_VarString(1, string, sizeof(string));
462 MSG_WriteChar(&client->message,svc_centerprint);
463 MSG_WriteString(&client->message, string);
471 vector normalize(vector)
474 void PF_normalize (void)
480 value1 = PRVM_G_VECTOR(OFS_PARM0);
482 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
486 newvalue[0] = newvalue[1] = newvalue[2] = 0;
490 newvalue[0] = value1[0] * new;
491 newvalue[1] = value1[1] * new;
492 newvalue[2] = value1[2] * new;
495 VectorCopy (newvalue, PRVM_G_VECTOR(OFS_RETURN));
510 value1 = PRVM_G_VECTOR(OFS_PARM0);
512 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
515 PRVM_G_FLOAT(OFS_RETURN) = new;
522 float vectoyaw(vector)
525 void PF_vectoyaw (void)
530 value1 = PRVM_G_VECTOR(OFS_PARM0);
532 if (value1[1] == 0 && value1[0] == 0)
536 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
541 PRVM_G_FLOAT(OFS_RETURN) = yaw;
549 vector vectoangles(vector)
552 void PF_vectoangles (void)
554 double value1[3], forward, yaw, pitch;
556 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), value1);
558 if (value1[1] == 0 && value1[0] == 0)
568 // LordHavoc: optimized a bit
571 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
575 else if (value1[1] > 0)
580 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
581 pitch = (atan2(value1[2], forward) * 180 / M_PI);
586 VectorSet(PRVM_G_VECTOR(OFS_RETURN), pitch, yaw, 0);
593 Returns a number from 0<= num < 1
598 void PF_random (void)
600 PRVM_G_FLOAT(OFS_RETURN) = lhrandom(0, 1);
607 particle(origin, color, count)
610 void PF_particle (void)
616 org = PRVM_G_VECTOR(OFS_PARM0);
617 dir = PRVM_G_VECTOR(OFS_PARM1);
618 color = PRVM_G_FLOAT(OFS_PARM2);
619 count = PRVM_G_FLOAT(OFS_PARM3);
620 SV_StartParticle (org, dir, color, count);
630 void PF_ambientsound (void)
634 float vol, attenuation;
637 pos = PRVM_G_VECTOR (OFS_PARM0);
638 samp = PRVM_G_STRING(OFS_PARM1);
639 vol = PRVM_G_FLOAT(OFS_PARM2);
640 attenuation = PRVM_G_FLOAT(OFS_PARM3);
642 // check to see if samp was properly precached
643 soundnum = SV_SoundIndex(samp, 1);
651 // add an svc_spawnambient command to the level signon packet
654 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
656 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
658 MSG_WriteVector(&sv.signon, pos, sv.protocol);
661 MSG_WriteShort (&sv.signon, soundnum);
663 MSG_WriteByte (&sv.signon, soundnum);
665 MSG_WriteByte (&sv.signon, vol*255);
666 MSG_WriteByte (&sv.signon, attenuation*64);
674 Each entity can have eight independant sound sources, like voice,
677 Channel 0 is an auto-allocate channel, the others override anything
678 already running on that entity/channel pair.
680 An attenuation of 0 will play full volume everywhere in the level.
681 Larger attenuations will drop off.
689 prvm_edict_t *entity;
693 entity = PRVM_G_EDICT(OFS_PARM0);
694 channel = PRVM_G_FLOAT(OFS_PARM1);
695 sample = PRVM_G_STRING(OFS_PARM2);
696 volume = PRVM_G_FLOAT(OFS_PARM3) * 255;
697 attenuation = PRVM_G_FLOAT(OFS_PARM4);
699 if (volume < 0 || volume > 255)
700 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
702 if (attenuation < 0 || attenuation > 4)
703 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
705 if (channel < 0 || channel > 7)
706 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
708 SV_StartSound (entity, channel, sample, volume, attenuation);
720 PF_ERROR("break: break statement");
727 Used for use tracing and shot targeting
728 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
729 if the tryents flag is set.
731 traceline (vector1, vector2, tryents)
734 void PF_traceline (void)
741 pr_xfunction->builtinsprofile += 30;
743 v1 = PRVM_G_VECTOR(OFS_PARM0);
744 v2 = PRVM_G_VECTOR(OFS_PARM1);
745 move = PRVM_G_FLOAT(OFS_PARM2);
746 ent = PRVM_G_EDICT(OFS_PARM3);
748 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
750 prog->globals.server->trace_allsolid = trace.allsolid;
751 prog->globals.server->trace_startsolid = trace.startsolid;
752 prog->globals.server->trace_fraction = trace.fraction;
753 prog->globals.server->trace_inwater = trace.inwater;
754 prog->globals.server->trace_inopen = trace.inopen;
755 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
756 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
757 prog->globals.server->trace_plane_dist = trace.plane.dist;
759 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
761 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
762 // FIXME: add trace_endcontents
770 Used for use tracing and shot targeting
771 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
772 if the tryents flag is set.
774 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
777 // LordHavoc: added this for my own use, VERY useful, similar to traceline
778 void PF_tracebox (void)
780 float *v1, *v2, *m1, *m2;
785 pr_xfunction->builtinsprofile += 30;
787 v1 = PRVM_G_VECTOR(OFS_PARM0);
788 m1 = PRVM_G_VECTOR(OFS_PARM1);
789 m2 = PRVM_G_VECTOR(OFS_PARM2);
790 v2 = PRVM_G_VECTOR(OFS_PARM3);
791 move = PRVM_G_FLOAT(OFS_PARM4);
792 ent = PRVM_G_EDICT(OFS_PARM5);
794 trace = SV_Move (v1, m1, m2, v2, move, ent);
796 prog->globals.server->trace_allsolid = trace.allsolid;
797 prog->globals.server->trace_startsolid = trace.startsolid;
798 prog->globals.server->trace_fraction = trace.fraction;
799 prog->globals.server->trace_inwater = trace.inwater;
800 prog->globals.server->trace_inopen = trace.inopen;
801 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
802 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
803 prog->globals.server->trace_plane_dist = trace.plane.dist;
805 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
807 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
810 extern trace_t SV_Trace_Toss (prvm_edict_t *ent, prvm_edict_t *ignore);
811 void PF_tracetoss (void)
815 prvm_edict_t *ignore;
817 pr_xfunction->builtinsprofile += 600;
819 ent = PRVM_G_EDICT(OFS_PARM0);
820 if (ent == prog->edicts)
821 PF_WARNING("tracetoss: can not use world entity\n");
822 ignore = PRVM_G_EDICT(OFS_PARM1);
824 trace = SV_Trace_Toss (ent, ignore);
826 prog->globals.server->trace_allsolid = trace.allsolid;
827 prog->globals.server->trace_startsolid = trace.startsolid;
828 prog->globals.server->trace_fraction = trace.fraction;
829 prog->globals.server->trace_inwater = trace.inwater;
830 prog->globals.server->trace_inopen = trace.inopen;
831 VectorCopy (trace.endpos, prog->globals.server->trace_endpos);
832 VectorCopy (trace.plane.normal, prog->globals.server->trace_plane_normal);
833 prog->globals.server->trace_plane_dist = trace.plane.dist;
835 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(trace.ent);
837 prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(prog->edicts);
845 Returns true if the given entity can move to the given position from it's
846 current position by walking or rolling.
848 scalar checkpos (entity, vector)
851 void PF_checkpos (void)
855 //============================================================================
858 unsigned char checkpvs[MAX_MAP_LEAFS/8];
860 int PF_newcheckclient (int check)
866 // cycle to the next one
868 check = bound(1, check, svs.maxclients);
869 if (check == svs.maxclients)
877 pr_xfunction->builtinsprofile++;
879 if (i == svs.maxclients+1)
881 // look up the client's edict
882 ent = PRVM_EDICT_NUM(i);
883 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
884 if (i != check && (ent->priv.server->free || ent->fields.server->health <= 0 || ((int)ent->fields.server->flags & FL_NOTARGET)))
886 // found a valid client (possibly the same one again)
890 // get the PVS for the entity
891 VectorAdd(ent->fields.server->origin, ent->fields.server->view_ofs, org);
893 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
894 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
903 Returns a client (or object that has a client enemy) that would be a
906 If there is more than one valid option, they are cycled each frame
908 If (self.origin + self.viewofs) is not in the PVS of the current target,
909 it is not returned at all.
914 int c_invis, c_notvis;
915 void PF_checkclient (void)
917 prvm_edict_t *ent, *self;
920 // find a new check if on a new frame
921 if (sv.time - sv.lastchecktime >= 0.1)
923 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
924 sv.lastchecktime = sv.time;
927 // return check if it might be visible
928 ent = PRVM_EDICT_NUM(sv.lastcheck);
929 if (ent->priv.server->free || ent->fields.server->health <= 0)
931 RETURN_EDICT(prog->edicts);
935 // if current entity can't possibly see the check entity, return 0
936 self = PRVM_PROG_TO_EDICT(prog->globals.server->self);
937 VectorAdd(self->fields.server->origin, self->fields.server->view_ofs, view);
938 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
941 RETURN_EDICT(prog->edicts);
945 // might be able to see it
950 //============================================================================
957 Sends text over to the client's execution buffer
959 stuffcmd (clientent, value, ...)
962 void PF_stuffcmd (void)
966 char string[VM_STRINGTEMP_LENGTH];
968 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
969 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
971 Con_Print("Can't stuffcmd to a non-client\n");
974 VM_VarString(1, string, sizeof(string));
977 host_client = svs.clients + entnum-1;
978 Host_ClientCommands ("%s", string);
986 Sends text to server console
988 localcmd (string, ...)
991 void PF_localcmd (void)
993 char string[VM_STRINGTEMP_LENGTH];
994 VM_VarString(0, string, sizeof(string));
995 Cbuf_AddText(string);
1007 PRVM_G_FLOAT(OFS_RETURN) = Cvar_VariableValue(PRVM_G_STRING(OFS_PARM0));
1017 void PF_cvar_set (void)
1019 Cvar_Set(PRVM_G_STRING(OFS_PARM0), PRVM_G_STRING(OFS_PARM1));
1026 Returns a chain of entities that have origins within a spherical area
1028 findradius (origin, radius)
1031 void PF_findradius (void)
1033 prvm_edict_t *ent, *chain;
1034 vec_t radius, radius2;
1035 vec3_t org, eorg, mins, maxs;
1038 prvm_edict_t *touchedicts[MAX_EDICTS];
1040 chain = (prvm_edict_t *)prog->edicts;
1042 VectorCopy(PRVM_G_VECTOR(OFS_PARM0), org);
1043 radius = PRVM_G_FLOAT(OFS_PARM1);
1044 radius2 = radius * radius;
1046 mins[0] = org[0] - (radius + 1);
1047 mins[1] = org[1] - (radius + 1);
1048 mins[2] = org[2] - (radius + 1);
1049 maxs[0] = org[0] + (radius + 1);
1050 maxs[1] = org[1] + (radius + 1);
1051 maxs[2] = org[2] + (radius + 1);
1052 numtouchedicts = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, touchedicts);
1053 if (numtouchedicts > MAX_EDICTS)
1055 // this never happens
1056 Con_Printf("SV_EntitiesInBox returned %i edicts, max was %i\n", numtouchedicts, MAX_EDICTS);
1057 numtouchedicts = MAX_EDICTS;
1059 for (i = 0;i < numtouchedicts;i++)
1061 ent = touchedicts[i];
1062 pr_xfunction->builtinsprofile++;
1063 // Quake did not return non-solid entities but darkplaces does
1064 // (note: this is the reason you can't blow up fallen zombies)
1065 if (ent->fields.server->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.integer)
1067 // LordHavoc: compare against bounding box rather than center so it
1068 // doesn't miss large objects, and use DotProduct instead of Length
1069 // for a major speedup
1070 VectorSubtract(org, ent->fields.server->origin, eorg);
1071 if (sv_gameplayfix_findradiusdistancetobox.integer)
1073 eorg[0] -= bound(ent->fields.server->mins[0], eorg[0], ent->fields.server->maxs[0]);
1074 eorg[1] -= bound(ent->fields.server->mins[1], eorg[1], ent->fields.server->maxs[1]);
1075 eorg[2] -= bound(ent->fields.server->mins[2], eorg[2], ent->fields.server->maxs[2]);
1078 VectorMAMAM(1, eorg, 0.5f, ent->fields.server->mins, 0.5f, ent->fields.server->maxs, eorg);
1079 if (DotProduct(eorg, eorg) < radius2)
1081 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1086 RETURN_EDICT(chain);
1095 void PF_dprint (void)
1097 char string[STRINGTEMP_LENGTH];
1098 if (developer.integer)
1100 PF_VarString(0, string, sizeof(string));
1109 v = PRVM_G_FLOAT(OFS_PARM0);
1111 s = PR_GetTempString();
1112 if ((float)((int)v) == v)
1113 sprintf(s, "%i", (int)v);
1115 sprintf(s, "%f", v);
1116 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1122 v = PRVM_G_FLOAT(OFS_PARM0);
1123 PRVM_G_FLOAT(OFS_RETURN) = fabs(v);
1129 s = PR_GetTempString();
1130 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]);
1131 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1137 s = PR_GetTempString();
1138 sprintf (s, "entity %i", PRVM_G_EDICTNUM(OFS_PARM0));
1139 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
1142 void PF_Spawn (void)
1145 pr_xfunction->builtinsprofile += 20;
1150 void PF_Remove (void)
1153 pr_xfunction->builtinsprofile += 20;
1155 ed = PRVM_G_EDICT(OFS_PARM0);
1156 if (ed == prog->edicts)
1157 PF_WARNING("remove: tried to remove world\n");
1158 if (PRVM_NUM_FOR_EDICT(ed) <= svs.maxclients)
1159 PF_WARNING("remove: tried to remove a client\n");
1160 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1161 if (ed->priv.server->free && developer.integer)
1162 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1167 // entity (entity start, .string field, string match) find = #5;
1175 e = PRVM_G_EDICTNUM(OFS_PARM0);
1176 f = PRVM_G_INT(OFS_PARM1);
1177 s = PRVM_G_STRING(OFS_PARM2);
1180 RETURN_EDICT(prog->edicts);
1184 for (e++ ; e < prog->num_edicts ; e++)
1186 pr_xfunction->builtinsprofile++;
1187 ed = PRVM_EDICT_NUM(e);
1188 if (ed->priv.server->free)
1200 RETURN_EDICT(prog->edicts);
1203 // LordHavoc: added this for searching float, int, and entity reference fields
1204 void PF_FindFloat (void)
1211 e = PRVM_G_EDICTNUM(OFS_PARM0);
1212 f = PRVM_G_INT(OFS_PARM1);
1213 s = PRVM_G_FLOAT(OFS_PARM2);
1215 for (e++ ; e < prog->num_edicts ; e++)
1217 pr_xfunction->builtinsprofile++;
1218 ed = PRVM_EDICT_NUM(e);
1219 if (ed->priv.server->free)
1221 if (E_FLOAT(ed,f) == s)
1228 RETURN_EDICT(prog->edicts);
1231 // chained search for strings in entity fields
1232 // entity(.string field, string match) findchain = #402;
1233 void PF_findchain (void)
1238 prvm_edict_t *ent, *chain;
1240 chain = (prvm_edict_t *)prog->edicts;
1242 f = PRVM_G_INT(OFS_PARM0);
1243 s = PRVM_G_STRING(OFS_PARM1);
1246 RETURN_EDICT(prog->edicts);
1250 ent = PRVM_NEXT_EDICT(prog->edicts);
1251 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1253 pr_xfunction->builtinsprofile++;
1254 if (ent->priv.server->free)
1256 t = E_STRING(ent,f);
1262 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1266 RETURN_EDICT(chain);
1269 // LordHavoc: chained search for float, int, and entity reference fields
1270 // entity(.string field, float match) findchainfloat = #403;
1271 void PF_findchainfloat (void)
1276 prvm_edict_t *ent, *chain;
1278 chain = (prvm_edict_t *)prog->edicts;
1280 f = PRVM_G_INT(OFS_PARM0);
1281 s = PRVM_G_FLOAT(OFS_PARM1);
1283 ent = PRVM_NEXT_EDICT(prog->edicts);
1284 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1286 pr_xfunction->builtinsprofile++;
1287 if (ent->priv.server->free)
1289 if (E_FLOAT(ent,f) != s)
1292 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1296 RETURN_EDICT(chain);
1299 // LordHavoc: search for flags in float fields
1300 void PF_findflags (void)
1307 e = PRVM_G_EDICTNUM(OFS_PARM0);
1308 f = PRVM_G_INT(OFS_PARM1);
1309 s = (int)PRVM_G_FLOAT(OFS_PARM2);
1311 for (e++ ; e < prog->num_edicts ; e++)
1313 pr_xfunction->builtinsprofile++;
1314 ed = PRVM_EDICT_NUM(e);
1315 if (ed->priv.server->free)
1317 if ((int)E_FLOAT(ed,f) & s)
1324 RETURN_EDICT(prog->edicts);
1327 // LordHavoc: chained search for flags in float fields
1328 void PF_findchainflags (void)
1333 prvm_edict_t *ent, *chain;
1335 chain = (prvm_edict_t *)prog->edicts;
1337 f = PRVM_G_INT(OFS_PARM0);
1338 s = (int)PRVM_G_FLOAT(OFS_PARM1);
1340 ent = PRVM_NEXT_EDICT(prog->edicts);
1341 for (i = 1;i < prog->num_edicts;i++, ent = PRVM_NEXT_EDICT(ent))
1343 pr_xfunction->builtinsprofile++;
1344 if (ent->priv.server->free)
1346 if (!((int)E_FLOAT(ent,f) & s))
1349 ent->fields.server->chain = PRVM_EDICT_TO_PROG(chain);
1353 RETURN_EDICT(chain);
1356 void PF_precache_file (void)
1357 { // precache_file is only used to copy files with qcc, it does nothing
1358 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1362 void PF_precache_sound (void)
1364 SV_SoundIndex(PRVM_G_STRING(OFS_PARM0), 2);
1365 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1368 void PF_precache_model (void)
1370 SV_ModelIndex(PRVM_G_STRING(OFS_PARM0), 2);
1371 PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0);
1375 void PF_coredump (void)
1380 void PF_traceon (void)
1385 void PF_traceoff (void)
1390 void PF_eprint (void)
1392 ED_PrintNum (PRVM_G_EDICTNUM(OFS_PARM0));
1399 float(float yaw, float dist) walkmove
1402 void PF_walkmove (void)
1410 // assume failure if it returns early
1411 PRVM_G_FLOAT(OFS_RETURN) = 0;
1413 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1414 if (ent == prog->edicts)
1415 PF_WARNING("walkmove: can not modify world entity\n");
1416 if (ent->priv.server->free)
1417 PF_WARNING("walkmove: can not modify free entity\n");
1418 yaw = PRVM_G_FLOAT(OFS_PARM0);
1419 dist = PRVM_G_FLOAT(OFS_PARM1);
1421 if ( !( (int)ent->fields.server->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1424 yaw = yaw*M_PI*2 / 360;
1426 move[0] = cos(yaw)*dist;
1427 move[1] = sin(yaw)*dist;
1430 // save program state, because SV_movestep may call other progs
1431 oldf = pr_xfunction;
1432 oldself = prog->globals.server->self;
1434 PRVM_G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1437 // restore program state
1438 pr_xfunction = oldf;
1439 prog->globals.server->self = oldself;
1449 void PF_droptofloor (void)
1455 // assume failure if it returns early
1456 PRVM_G_FLOAT(OFS_RETURN) = 0;
1458 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1459 if (ent == prog->edicts)
1460 PF_WARNING("droptofloor: can not modify world entity\n");
1461 if (ent->priv.server->free)
1462 PF_WARNING("droptofloor: can not modify free entity\n");
1464 VectorCopy (ent->fields.server->origin, end);
1467 trace = SV_Move (ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, MOVE_NORMAL, ent);
1469 if (trace.fraction != 1)
1471 VectorCopy (trace.endpos, ent->fields.server->origin);
1472 SV_LinkEdict (ent, false);
1473 ent->fields.server->flags = (int)ent->fields.server->flags | FL_ONGROUND;
1474 ent->fields.server->groundentity = PRVM_EDICT_TO_PROG(trace.ent);
1475 PRVM_G_FLOAT(OFS_RETURN) = 1;
1476 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1477 ent->priv.server->suspendedinairflag = true;
1485 void(float style, string value) lightstyle
1488 void PF_lightstyle (void)
1495 style = PRVM_G_FLOAT(OFS_PARM0);
1496 val = PRVM_G_STRING(OFS_PARM1);
1498 // change the string in sv
1499 strlcpy(sv.lightstyles[style], val, sizeof(sv.lightstyles[style]));
1501 // send message to all clients on this server
1502 if (sv.state != ss_active)
1505 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1509 MSG_WriteChar (&client->message, svc_lightstyle);
1510 MSG_WriteChar (&client->message,style);
1511 MSG_WriteString (&client->message, val);
1519 f = PRVM_G_FLOAT(OFS_PARM0);
1521 PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1523 PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1525 void PF_floor (void)
1527 PRVM_G_FLOAT(OFS_RETURN) = floor(PRVM_G_FLOAT(OFS_PARM0));
1531 PRVM_G_FLOAT(OFS_RETURN) = ceil(PRVM_G_FLOAT(OFS_PARM0));
1540 void PF_checkbottom (void)
1542 PRVM_G_FLOAT(OFS_RETURN) = SV_CheckBottom (PRVM_G_EDICT(OFS_PARM0));
1550 void PF_pointcontents (void)
1552 PRVM_G_FLOAT(OFS_RETURN) = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, SV_PointSuperContents(PRVM_G_VECTOR(OFS_PARM0)));
1559 entity nextent(entity)
1562 void PF_nextent (void)
1567 i = PRVM_G_EDICTNUM(OFS_PARM0);
1570 pr_xfunction->builtinsprofile++;
1572 if (i == prog->num_edicts)
1574 RETURN_EDICT(prog->edicts);
1577 ent = PRVM_EDICT_NUM(i);
1578 if (!ent->priv.server->free)
1590 Pick a vector for the player to shoot along
1591 vector aim(entity, missilespeed)
1596 prvm_edict_t *ent, *check, *bestent;
1597 vec3_t start, dir, end, bestdir;
1600 float dist, bestdist;
1603 // assume failure if it returns early
1604 VectorCopy(prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1605 // if sv_aim is so high it can't possibly accept anything, skip out early
1606 if (sv_aim.value >= 1)
1609 ent = PRVM_G_EDICT(OFS_PARM0);
1610 if (ent == prog->edicts)
1611 PF_WARNING("aim: can not use world entity\n");
1612 if (ent->priv.server->free)
1613 PF_WARNING("aim: can not use free entity\n");
1614 speed = PRVM_G_FLOAT(OFS_PARM1);
1616 VectorCopy (ent->fields.server->origin, start);
1619 // try sending a trace straight
1620 VectorCopy (prog->globals.server->v_forward, dir);
1621 VectorMA (start, 2048, dir, end);
1622 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1623 if (tr.ent && ((prvm_edict_t *)tr.ent)->fields.server->takedamage == DAMAGE_AIM
1624 && (!teamplay.integer || ent->fields.server->team <=0 || ent->fields.server->team != ((prvm_edict_t *)tr.ent)->fields.server->team) )
1626 VectorCopy (prog->globals.server->v_forward, PRVM_G_VECTOR(OFS_RETURN));
1631 // try all possible entities
1632 VectorCopy (dir, bestdir);
1633 bestdist = sv_aim.value;
1636 check = PRVM_NEXT_EDICT(prog->edicts);
1637 for (i=1 ; i<prog->num_edicts ; i++, check = PRVM_NEXT_EDICT(check) )
1639 pr_xfunction->builtinsprofile++;
1640 if (check->fields.server->takedamage != DAMAGE_AIM)
1644 if (teamplay.integer && ent->fields.server->team > 0 && ent->fields.server->team == check->fields.server->team)
1645 continue; // don't aim at teammate
1646 for (j=0 ; j<3 ; j++)
1647 end[j] = check->fields.server->origin[j]
1648 + 0.5*(check->fields.server->mins[j] + check->fields.server->maxs[j]);
1649 VectorSubtract (end, start, dir);
1650 VectorNormalize (dir);
1651 dist = DotProduct (dir, prog->globals.server->v_forward);
1652 if (dist < bestdist)
1653 continue; // to far to turn
1654 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1655 if (tr.ent == check)
1656 { // can shoot at this one
1664 VectorSubtract (bestent->fields.server->origin, ent->fields.server->origin, dir);
1665 dist = DotProduct (dir, prog->globals.server->v_forward);
1666 VectorScale (prog->globals.server->v_forward, dist, end);
1668 VectorNormalize (end);
1669 VectorCopy (end, PRVM_G_VECTOR(OFS_RETURN));
1673 VectorCopy (bestdir, PRVM_G_VECTOR(OFS_RETURN));
1681 This was a major timewaster in progs, so it was converted to C
1684 void PF_changeyaw (void)
1687 float ideal, current, move, speed;
1689 ent = PRVM_PROG_TO_EDICT(prog->globals.server->self);
1690 if (ent == prog->edicts)
1691 PF_WARNING("changeyaw: can not modify world entity\n");
1692 if (ent->priv.server->free)
1693 PF_WARNING("changeyaw: can not modify free entity\n");
1694 current = ANGLEMOD(ent->fields.server->angles[1]);
1695 ideal = ent->fields.server->ideal_yaw;
1696 speed = ent->fields.server->yaw_speed;
1698 if (current == ideal)
1700 move = ideal - current;
1701 if (ideal > current)
1722 ent->fields.server->angles[1] = ANGLEMOD (current + move);
1730 void PF_changepitch (void)
1733 float ideal, current, move, speed;
1736 ent = PRVM_G_EDICT(OFS_PARM0);
1737 if (ent == prog->edicts)
1738 PF_WARNING("changepitch: can not modify world entity\n");
1739 if (ent->priv.server->free)
1740 PF_WARNING("changepitch: can not modify free entity\n");
1741 current = ANGLEMOD( ent->fields.server->angles[0] );
1742 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1743 ideal = val->_float;
1746 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1749 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1750 speed = val->_float;
1753 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1757 if (current == ideal)
1759 move = ideal - current;
1760 if (ideal > current)
1781 ent->fields.server->angles[0] = ANGLEMOD (current + move);
1785 ===============================================================================
1789 ===============================================================================
1792 #define MSG_BROADCAST 0 // unreliable to all
1793 #define MSG_ONE 1 // reliable to one (msg_entity)
1794 #define MSG_ALL 2 // reliable to all
1795 #define MSG_INIT 3 // write to the init string
1797 sizebuf_t *WriteDest (void)
1803 dest = PRVM_G_FLOAT(OFS_PARM0);
1807 return &sv.datagram;
1810 ent = PRVM_PROG_TO_EDICT(prog->globals.server->msg_entity);
1811 entnum = PRVM_NUM_FOR_EDICT(ent);
1812 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1813 Host_Error("WriteDest: tried to write to non-client");
1814 return &svs.clients[entnum-1].message;
1817 return &sv.reliable_datagram;
1823 Host_Error("WriteDest: bad destination");
1830 void PF_WriteByte (void)
1832 MSG_WriteByte (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1835 void PF_WriteChar (void)
1837 MSG_WriteChar (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1840 void PF_WriteShort (void)
1842 MSG_WriteShort (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1845 void PF_WriteLong (void)
1847 MSG_WriteLong (WriteDest(), PRVM_G_FLOAT(OFS_PARM1));
1850 void PF_WriteAngle (void)
1852 MSG_WriteAngle (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1855 void PF_WriteCoord (void)
1857 MSG_WriteCoord (WriteDest(), PRVM_G_FLOAT(OFS_PARM1), sv.protocol);
1860 void PF_WriteString (void)
1862 MSG_WriteString (WriteDest(), PRVM_G_STRING(OFS_PARM1));
1866 void PF_WriteEntity (void)
1868 MSG_WriteShort (WriteDest(), PRVM_G_EDICTNUM(OFS_PARM1));
1871 //=============================================================================
1873 void PF_makestatic (void)
1878 ent = PRVM_G_EDICT(OFS_PARM0);
1879 if (ent == prog->edicts)
1880 PF_WARNING("makestatic: can not modify world entity\n");
1881 if (ent->priv.server->free)
1882 PF_WARNING("makestatic: can not modify free entity\n");
1885 if (ent->fields.server->modelindex >= 256 || ent->fields.server->frame >= 256)
1890 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1891 MSG_WriteShort (&sv.signon, ent->fields.server->modelindex);
1892 MSG_WriteShort (&sv.signon, ent->fields.server->frame);
1896 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1897 MSG_WriteByte (&sv.signon, ent->fields.server->modelindex);
1898 MSG_WriteByte (&sv.signon, ent->fields.server->frame);
1901 MSG_WriteByte (&sv.signon, ent->fields.server->colormap);
1902 MSG_WriteByte (&sv.signon, ent->fields.server->skin);
1903 for (i=0 ; i<3 ; i++)
1905 MSG_WriteCoord(&sv.signon, ent->fields.server->origin[i], sv.protocol);
1906 MSG_WriteAngle(&sv.signon, ent->fields.server->angles[i], sv.protocol);
1909 // throw the entity away now
1913 //=============================================================================
1920 void PF_setspawnparms (void)
1926 ent = PRVM_G_EDICT(OFS_PARM0);
1927 i = PRVM_NUM_FOR_EDICT(ent);
1928 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1930 Con_Print("tried to setspawnparms on a non-client\n");
1934 // copy spawn parms out of the client_t
1935 client = svs.clients + i-1;
1936 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1937 (&prog->globals.server->parm1)[i] = client->spawn_parms[i];
1945 void PF_changelevel (void)
1949 // make sure we don't issue two changelevels
1950 if (svs.changelevel_issued)
1952 svs.changelevel_issued = true;
1954 s = PRVM_G_STRING(OFS_PARM0);
1955 Cbuf_AddText (va("changelevel %s\n",s));
1960 PRVM_G_FLOAT(OFS_RETURN) = sin(PRVM_G_FLOAT(OFS_PARM0));
1965 PRVM_G_FLOAT(OFS_RETURN) = cos(PRVM_G_FLOAT(OFS_PARM0));
1970 PRVM_G_FLOAT(OFS_RETURN) = sqrt(PRVM_G_FLOAT(OFS_PARM0));
1977 Returns a vector of length < 1
1982 void PF_randomvec (void)
1987 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1988 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1989 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1991 while (DotProduct(temp, temp) >= 1);
1992 VectorCopy (temp, PRVM_G_VECTOR(OFS_RETURN));
1999 Returns a color vector indicating the lighting at the requested point.
2001 (Internal Operation note: actually measures the light beneath the point, just like
2002 the model lighting on the client)
2007 void PF_GetLight (void)
2009 vec3_t ambientcolor, diffusecolor, diffusenormal;
2011 p = PRVM_G_VECTOR(OFS_PARM0);
2012 VectorClear(ambientcolor);
2013 VectorClear(diffusecolor);
2014 VectorClear(diffusenormal);
2015 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
2016 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
2017 VectorMA(ambientcolor, 0.5, diffusecolor, PRVM_G_VECTOR(OFS_RETURN));
2020 void PF_registercvar (void)
2022 const char *name, *value;
2023 name = PRVM_G_STRING(OFS_PARM0);
2024 value = PRVM_G_STRING(OFS_PARM1);
2025 PRVM_G_FLOAT(OFS_RETURN) = 0;
2027 // first check to see if it has already been defined
2028 if (Cvar_FindVar (name))
2031 // check for overlap with a command
2032 if (Cmd_Exists (name))
2034 Con_Printf("PF_registercvar: %s is a command\n", name);
2038 Cvar_Get(name, value, 0);
2040 PRVM_G_FLOAT(OFS_RETURN) = 1; // success
2047 returns the minimum of two supplied floats
2054 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2056 PRVM_G_FLOAT(OFS_RETURN) = min(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2057 else if (pr_argc >= 3)
2060 float f = PRVM_G_FLOAT(OFS_PARM0);
2061 for (i = 1;i < pr_argc;i++)
2062 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) < f)
2063 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
2064 PRVM_G_FLOAT(OFS_RETURN) = f;
2068 PRVM_G_FLOAT(OFS_RETURN) = 0;
2069 PF_WARNING("min: must supply at least 2 floats\n");
2077 returns the maximum of two supplied floats
2084 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2086 PRVM_G_FLOAT(OFS_RETURN) = max(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2087 else if (pr_argc >= 3)
2090 float f = PRVM_G_FLOAT(OFS_PARM0);
2091 for (i = 1;i < pr_argc;i++)
2092 if (PRVM_G_FLOAT((OFS_PARM0+i*3)) > f)
2093 f = PRVM_G_FLOAT((OFS_PARM0+i*3));
2094 PRVM_G_FLOAT(OFS_RETURN) = f;
2098 PRVM_G_FLOAT(OFS_RETURN) = 0;
2099 PF_WARNING("max: must supply at least 2 floats\n");
2107 returns number bounded by supplied range
2109 min(min, value, max)
2112 void PF_bound (void)
2114 PRVM_G_FLOAT(OFS_RETURN) = bound(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1), PRVM_G_FLOAT(OFS_PARM2));
2121 returns a raised to power b
2128 PRVM_G_FLOAT(OFS_RETURN) = pow(PRVM_G_FLOAT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1));
2135 copies data from one entity to another
2137 copyentity(src, dst)
2140 void PF_copyentity (void)
2142 prvm_edict_t *in, *out;
2143 in = PRVM_G_EDICT(OFS_PARM0);
2144 if (in == prog->edicts)
2145 PF_WARNING("copyentity: can not read world entity\n");
2146 if (in->priv.server->free)
2147 PF_WARNING("copyentity: can not read free entity\n");
2148 out = PRVM_G_EDICT(OFS_PARM1);
2149 if (out == prog->edicts)
2150 PF_WARNING("copyentity: can not modify world entity\n");
2151 if (out->priv.server->free)
2152 PF_WARNING("copyentity: can not modify free entity\n");
2153 memcpy(out->v, in->v, progs->entityfields * 4);
2160 sets the color of a client and broadcasts the update to all connected clients
2162 setcolor(clientent, value)
2165 void PF_setcolor (void)
2171 entnum = PRVM_G_EDICTNUM(OFS_PARM0);
2172 i = PRVM_G_FLOAT(OFS_PARM1);
2174 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2176 Con_Print("tried to setcolor a non-client\n");
2180 client = svs.clients + entnum-1;
2183 if ((val = PRVM_GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2185 client->edict->fields.server->team = (i & 15) + 1;
2188 if (client->old_colors != client->colors)
2190 client->old_colors = client->colors;
2191 // send notification to all clients
2192 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2193 MSG_WriteByte (&sv.reliable_datagram, client - svs.clients);
2194 MSG_WriteByte (&sv.reliable_datagram, client->colors);
2202 effect(origin, modelname, startframe, framecount, framerate)
2205 void PF_effect (void)
2209 s = PRVM_G_STRING(OFS_PARM1);
2211 PF_WARNING("effect: no model specified\n");
2213 i = SV_ModelIndex(s, 1);
2215 PF_WARNING("effect: model not precached\n");
2216 SV_StartEffect(PRVM_G_VECTOR(OFS_PARM0), i, PRVM_G_FLOAT(OFS_PARM2), PRVM_G_FLOAT(OFS_PARM3), PRVM_G_FLOAT(OFS_PARM4));
2219 void PF_te_blood (void)
2221 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2223 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2224 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2226 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2227 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2228 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2230 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2231 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2232 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2234 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2237 void PF_te_bloodshower (void)
2239 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2244 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2245 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2246 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2248 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2249 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2250 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2252 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol);
2254 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2257 void PF_te_explosionrgb (void)
2259 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2260 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2262 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2263 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2264 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2266 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255));
2267 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255));
2268 MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255));
2271 void PF_te_particlecube (void)
2273 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2275 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2276 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2278 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2279 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2280 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2282 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2283 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2284 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2286 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2287 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2288 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2290 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2292 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2293 // gravity true/false
2294 MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0);
2296 MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol);
2299 void PF_te_particlerain (void)
2301 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2303 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2304 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2306 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2307 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2308 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2310 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2311 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2312 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2314 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2315 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2316 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2318 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2320 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2323 void PF_te_particlesnow (void)
2325 if (PRVM_G_FLOAT(OFS_PARM3) < 1)
2327 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2328 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2330 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2331 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2332 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2334 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2335 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2336 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2338 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2339 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2340 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2342 MSG_WriteShort(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535));
2344 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM4));
2347 void PF_te_spark (void)
2349 if (PRVM_G_FLOAT(OFS_PARM2) < 1)
2351 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2352 MSG_WriteByte(&sv.datagram, TE_SPARK);
2354 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2355 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2356 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2358 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[0], 127));
2359 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[1], 127));
2360 MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127));
2362 MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255));
2365 void PF_te_gunshotquad (void)
2367 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2368 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2370 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2371 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2372 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2375 void PF_te_spikequad (void)
2377 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2378 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2380 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2381 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2382 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2385 void PF_te_superspikequad (void)
2387 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2388 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2390 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2391 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2392 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2395 void PF_te_explosionquad (void)
2397 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2398 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2400 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2401 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2402 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2405 void PF_te_smallflash (void)
2407 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2408 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2410 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2411 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2412 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2415 void PF_te_customflash (void)
2417 if (PRVM_G_FLOAT(OFS_PARM1) < 8 || PRVM_G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2419 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2420 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2422 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2423 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2424 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2426 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2428 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_FLOAT(OFS_PARM2) * 256 - 1, 255));
2430 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255));
2431 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255));
2432 MSG_WriteByte(&sv.datagram, bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255));
2435 void PF_te_gunshot (void)
2437 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2438 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2440 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2441 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2442 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2445 void PF_te_spike (void)
2447 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2448 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2450 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2451 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2452 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2455 void PF_te_superspike (void)
2457 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2458 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2460 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2461 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2462 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2465 void PF_te_explosion (void)
2467 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2468 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2470 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2471 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2472 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2475 void PF_te_tarexplosion (void)
2477 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2478 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2480 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2481 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2482 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2485 void PF_te_wizspike (void)
2487 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2488 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2490 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2491 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2492 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2495 void PF_te_knightspike (void)
2497 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2498 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2500 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2501 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2502 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2505 void PF_te_lavasplash (void)
2507 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2508 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2510 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2511 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2512 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2515 void PF_te_teleport (void)
2517 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2518 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2520 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2521 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2522 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2525 void PF_te_explosion2 (void)
2527 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2528 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2530 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2531 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2532 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2534 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM1));
2535 MSG_WriteByte(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2));
2538 void PF_te_lightning1 (void)
2540 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2541 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2543 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2545 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2546 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2547 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2549 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2550 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2551 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2554 void PF_te_lightning2 (void)
2556 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2557 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2559 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2561 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2562 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2563 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2565 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2566 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2567 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2570 void PF_te_lightning3 (void)
2572 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2573 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2575 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2577 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2578 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2579 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2581 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2582 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2583 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2586 void PF_te_beam (void)
2588 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2589 MSG_WriteByte(&sv.datagram, TE_BEAM);
2591 MSG_WriteShort(&sv.datagram, PRVM_G_EDICTNUM(OFS_PARM0));
2593 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[0], sv.protocol);
2594 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[1], sv.protocol);
2595 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol);
2597 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol);
2598 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol);
2599 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol);
2602 void PF_te_plasmaburn (void)
2604 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2605 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2606 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol);
2607 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol);
2608 MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol);
2611 static void clippointtosurface(msurface_t *surface, vec3_t p, vec3_t out)
2614 float *v[3], facenormal[3], edgenormal[3], sidenormal[3], temp[3], offsetdist, dist, bestdist;
2616 bestdist = 1000000000;
2618 for (i = 0, e = (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle);i < surface->num_triangles;i++, e += 3)
2620 // clip original point to each triangle of the surface and find the
2621 // triangle that is closest
2622 v[0] = surface->groupmesh->data_vertex3f + e[0] * 3;
2623 v[1] = surface->groupmesh->data_vertex3f + e[1] * 3;
2624 v[2] = surface->groupmesh->data_vertex3f + e[2] * 3;
2625 TriangleNormal(v[0], v[1], v[2], facenormal);
2626 VectorNormalize(facenormal);
2627 offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal);
2628 VectorMA(p, offsetdist, facenormal, temp);
2629 for (j = 0, k = 2;j < 3;k = j, j++)
2631 VectorSubtract(v[k], v[j], edgenormal);
2632 CrossProduct(edgenormal, facenormal, sidenormal);
2633 VectorNormalize(sidenormal);
2634 offsetdist = DotProduct(v[k], sidenormal) - DotProduct(temp, sidenormal);
2636 VectorMA(temp, offsetdist, sidenormal, temp);
2638 dist = VectorDistance2(temp, p);
2639 if (bestdist > dist)
2642 VectorCopy(temp, out);
2647 static msurface_t *getsurface(prvm_edict_t *ed, int surfacenum)
2651 if (!ed || ed->priv.server->free)
2653 modelindex = ed->fields.server->modelindex;
2654 if (modelindex < 1 || modelindex >= MAX_MODELS)
2656 model = sv.models[modelindex];
2657 if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces)
2659 return model->data_surfaces + surfacenum + model->firstmodelsurface;
2663 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2664 void PF_getsurfacenumpoints(void)
2666 msurface_t *surface;
2667 // return 0 if no such surface
2668 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2670 PRVM_G_FLOAT(OFS_RETURN) = 0;
2674 // note: this (incorrectly) assumes it is a simple polygon
2675 PRVM_G_FLOAT(OFS_RETURN) = surface->num_vertices;
2677 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2678 void PF_getsurfacepoint(void)
2681 msurface_t *surface;
2683 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2684 ed = PRVM_G_EDICT(OFS_PARM0);
2685 if (!ed || ed->priv.server->free)
2687 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2689 // note: this (incorrectly) assumes it is a simple polygon
2690 pointnum = PRVM_G_FLOAT(OFS_PARM2);
2691 if (pointnum < 0 || pointnum >= surface->num_vertices)
2693 // FIXME: implement rotation/scaling
2694 VectorAdd(&(surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2696 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2697 void PF_getsurfacenormal(void)
2699 msurface_t *surface;
2701 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2702 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2704 // FIXME: implement rotation/scaling
2705 // note: this (incorrectly) assumes it is a simple polygon
2706 // note: this only returns the first triangle, so it doesn't work very
2707 // well for curved surfaces or arbitrary meshes
2708 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);
2709 VectorNormalize(normal);
2710 VectorCopy(normal, PRVM_G_VECTOR(OFS_RETURN));
2712 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2713 void PF_getsurfacetexture(void)
2715 msurface_t *surface;
2716 PRVM_G_INT(OFS_RETURN) = 0;
2717 if (!(surface = getsurface(PRVM_G_EDICT(OFS_PARM0), PRVM_G_FLOAT(OFS_PARM1))))
2719 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(surface->texture->name);
2721 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2722 void PF_getsurfacenearpoint(void)
2724 int surfacenum, best, modelindex;
2726 vec_t dist, bestdist;
2729 msurface_t *surface;
2731 PRVM_G_FLOAT(OFS_RETURN) = -1;
2732 ed = PRVM_G_EDICT(OFS_PARM0);
2733 point = PRVM_G_VECTOR(OFS_PARM1);
2735 if (!ed || ed->priv.server->free)
2737 modelindex = ed->fields.server->modelindex;
2738 if (modelindex < 1 || modelindex >= MAX_MODELS)
2740 model = sv.models[modelindex];
2741 if (!model->num_surfaces)
2744 // FIXME: implement rotation/scaling
2745 VectorSubtract(point, ed->fields.server->origin, p);
2747 bestdist = 1000000000;
2748 for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++)
2750 surface = model->data_surfaces + surfacenum + model->firstmodelsurface;
2751 // first see if the nearest point on the surface's box is closer than the previous match
2752 clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0];
2753 clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1];
2754 clipped[2] = bound(surface->mins[2], p[2], surface->maxs[2]) - p[2];
2755 dist = VectorLength2(clipped);
2756 if (dist < bestdist)
2758 // it is, check the nearest point on the actual geometry
2759 clippointtosurface(surface, p, clipped);
2760 VectorSubtract(clipped, p, clipped);
2761 dist += VectorLength2(clipped);
2762 if (dist < bestdist)
2764 // that's closer too, store it as the best match
2770 PRVM_G_FLOAT(OFS_RETURN) = best;
2772 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2773 void PF_getsurfaceclippedpoint(void)
2776 msurface_t *surface;
2778 VectorClear(PRVM_G_VECTOR(OFS_RETURN));
2779 ed = PRVM_G_EDICT(OFS_PARM0);
2780 if (!ed || ed->priv.server->free)
2782 if (!(surface = getsurface(ed, PRVM_G_FLOAT(OFS_PARM1))))
2784 // FIXME: implement rotation/scaling
2785 VectorSubtract(PRVM_G_VECTOR(OFS_PARM2), ed->fields.server->origin, p);
2786 clippointtosurface(surface, p, out);
2787 // FIXME: implement rotation/scaling
2788 VectorAdd(out, ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN));
2791 #define MAX_PRFILES 256
2793 qfile_t *pr_files[MAX_PRFILES];
2795 void PR_Files_Init(void)
2797 memset(pr_files, 0, sizeof(pr_files));
2800 void PR_Files_CloseAll(void)
2803 for (i = 0;i < MAX_PRFILES;i++)
2806 FS_Close(pr_files[i]);
2811 //float(string s) stof = #81; // get numerical value from a string
2814 char string[STRINGTEMP_LENGTH];
2815 PF_VarString(0, string, sizeof(string));
2816 PRVM_G_FLOAT(OFS_RETURN) = atof(string);
2819 //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
2823 const char *modestring, *filename;
2824 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2825 if (pr_files[filenum] == NULL)
2827 if (filenum >= MAX_PRFILES)
2829 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2830 PRVM_G_FLOAT(OFS_RETURN) = -2;
2833 mode = PRVM_G_FLOAT(OFS_PARM1);
2836 case 0: // FILE_READ
2839 case 1: // FILE_APPEND
2842 case 2: // FILE_WRITE
2846 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2847 PRVM_G_FLOAT(OFS_RETURN) = -3;
2850 filename = PRVM_G_STRING(OFS_PARM0);
2851 // -4 failure (dangerous/non-portable filename) removed, FS_Open checks
2852 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
2854 if (pr_files[filenum] == NULL && modestring == "rb")
2855 pr_files[filenum] = FS_Open(filename, modestring, false, false);
2857 if (pr_files[filenum] == NULL)
2858 PRVM_G_FLOAT(OFS_RETURN) = -1;
2860 PRVM_G_FLOAT(OFS_RETURN) = filenum;
2863 //void(float fhandle) fclose = #111; // closes a file
2864 void PF_fclose(void)
2866 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2867 if (filenum < 0 || filenum >= MAX_PRFILES)
2869 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2872 if (pr_files[filenum] == NULL)
2874 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2877 FS_Close(pr_files[filenum]);
2878 pr_files[filenum] = NULL;
2881 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2885 static char string[STRINGTEMP_LENGTH];
2886 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2887 if (filenum < 0 || filenum >= MAX_PRFILES)
2889 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2892 if (pr_files[filenum] == NULL)
2894 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2900 c = FS_Getc(pr_files[filenum]);
2901 if (c == '\r' || c == '\n' || c < 0)
2903 if (end < STRINGTEMP_LENGTH - 1)
2907 // remove \n following \r
2910 c = FS_Getc(pr_files[filenum]);
2912 FS_UnGetc(pr_files[filenum], (unsigned char)c);
2914 if (developer.integer)
2915 Con_Printf("fgets: %s\n", string);
2917 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
2919 PRVM_G_INT(OFS_RETURN) = 0;
2922 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2926 char string[STRINGTEMP_LENGTH];
2927 int filenum = PRVM_G_FLOAT(OFS_PARM0);
2928 if (filenum < 0 || filenum >= MAX_PRFILES)
2930 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2933 if (pr_files[filenum] == NULL)
2935 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2938 PF_VarString(1, string, sizeof(string));
2939 if ((stringlength = strlen(string)))
2940 FS_Write(pr_files[filenum], string, stringlength);
2941 if (developer.integer)
2942 Con_Printf("fputs: %s\n", string);
2945 //float(string s) strlen = #114; // returns how many characters are in a string
2946 void PF_strlen(void)
2949 s = PRVM_G_STRING(OFS_PARM0);
2951 PRVM_G_FLOAT(OFS_RETURN) = strlen(s);
2953 PRVM_G_FLOAT(OFS_RETURN) = 0;
2956 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2957 void PF_strcat(void)
2959 char *s = PR_GetTempString();
2960 PF_VarString(0, s, STRINGTEMP_LENGTH);
2961 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(s);
2964 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2965 void PF_substring(void)
2967 int i, start, length;
2969 char *string = PR_GetTempString();
2970 s = PRVM_G_STRING(OFS_PARM0);
2971 start = PRVM_G_FLOAT(OFS_PARM1);
2972 length = PRVM_G_FLOAT(OFS_PARM2);
2975 for (i = 0;i < start && *s;i++, s++);
2976 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2979 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(string);
2982 //vector(string s) stov = #117; // returns vector value from a string
2985 char string[STRINGTEMP_LENGTH];
2986 PF_VarString(0, string, sizeof(string));
2987 Math_atov(string, PRVM_G_VECTOR(OFS_RETURN));
2990 //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)
2991 void PF_strzone(void)
2995 in = PRVM_G_STRING(OFS_PARM0);
2996 out = PR_AllocString(strlen(in) + 1);
2998 PRVM_G_INT(OFS_RETURN) = PR_SetQCString(out);
3001 //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!!!)
3002 void PF_strunzone(void)
3004 PR_FreeString((char *)PRVM_G_STRING(OFS_PARM0));
3007 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
3008 //this function originally written by KrimZon, made shorter by LordHavoc
3009 void PF_clientcommand (void)
3011 client_t *temp_client;
3014 //find client for this entity
3015 i = (PRVM_NUM_FOR_EDICT(PRVM_G_EDICT(OFS_PARM0)) - 1);
3016 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
3018 Con_Print("PF_clientcommand: entity is not a client\n");
3022 temp_client = host_client;
3023 host_client = svs.clients + i;
3024 Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client);
3025 host_client = temp_client;
3028 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
3029 //this function originally written by KrimZon, made shorter by LordHavoc
3030 //20040203: rewritten by LordHavoc (no longer uses allocations)
3032 char *tokens[256], tokenbuf[MAX_INPUTLINE];
3033 void PF_tokenize (void)
3037 p = PRVM_G_STRING(OFS_PARM0);
3041 while(COM_ParseToken(&p, false))
3043 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
3045 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
3047 tokens[num_tokens++] = tokenbuf + pos;
3048 strcpy(tokenbuf + pos, com_token);
3049 pos += strlen(com_token) + 1;
3052 PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
3055 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
3056 //this function originally written by KrimZon, made shorter by LordHavoc
3059 int token_num = PRVM_G_FLOAT(OFS_PARM0);
3060 if (token_num >= 0 && token_num < num_tokens)
3061 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tokens[token_num]);
3063 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(NULL);
3066 //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)
3067 void PF_setattachment (void)
3069 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
3070 prvm_edict_t *tagentity = PRVM_G_EDICT(OFS_PARM1);
3071 const char *tagname = PRVM_G_STRING(OFS_PARM2);
3076 if (e == prog->edicts)
3077 PF_WARNING("setattachment: can not modify world entity\n");
3078 if (e->priv.server->free)
3079 PF_WARNING("setattachment: can not modify free entity\n");
3081 if (tagentity == NULL)
3082 tagentity = prog->edicts;
3084 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_entity);
3086 fields.server->edict = PRVM_EDICT_TO_PROG(tagentity);
3088 v = PRVM_GETEDICTFIELDVALUE(e, eval_tag_index);
3090 fields.server->_float = 0;
3091 if (tagentity != NULL && tagentity != prog->edicts && tagname && tagname[0])
3093 modelindex = (int)tagentity->fields.server->modelindex;
3094 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3096 fields.server->_float = Mod_Alias_GetTagIndexForName(model, tagentity->fields.server->skin, tagname);
3097 if (fields.server->_float == 0)
3098 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);
3101 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));
3105 /////////////////////////////////////////
3106 // DP_MD3_TAGINFO extension coded by VorteX
3108 int SV_GetTagIndex (prvm_edict_t *e, const char *tagname)
3113 i = e->fields.server->modelindex;
3114 if (i < 1 || i >= MAX_MODELS)
3116 model = sv.models[i];
3118 return Mod_Alias_GetTagIndexForName(model, e->fields.server->skin, tagname);
3121 // Warnings/errors code:
3122 // 0 - normal (everything all-right)
3125 // 3 - null or non-precached model
3126 // 4 - no tags with requested index
3127 // 5 - runaway loop at attachment chain
3128 extern cvar_t cl_bob;
3129 extern cvar_t cl_bobcycle;
3130 extern cvar_t cl_bobup;
3131 int SV_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex)
3134 int modelindex, reqframe, attachloop;
3135 matrix4x4_t entitymatrix, tagmatrix, attachmatrix;
3136 prvm_edict_t *attachent;
3139 Matrix4x4_CreateIdentity(out); // warnings and errors return identical matrix
3141 if (ent == prog->edicts)
3143 if (ent->priv.server->free)
3146 modelindex = (int)ent->fields.server->modelindex;
3147 if (modelindex <= 0 || modelindex > MAX_MODELS)
3150 model = sv.models[modelindex];
3152 if (ent->fields.server->frame >= 0 && ent->fields.server->frame < model->numframes && model->animscenes)
3153 reqframe = model->animscenes[(int)ent->fields.server->frame].firstframe;
3155 reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame
3157 // get initial tag matrix
3160 int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix);
3165 Matrix4x4_CreateIdentity(&tagmatrix);
3167 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict)
3168 { // DP_GFX_QUAKE3MODELTAGS, scan all chain and stop on unattached entity
3172 attachent = PRVM_EDICT_NUM(val->edict); // to this it entity our entity is attached
3173 val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_index);
3174 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)
3175 Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->fields.server->frame].firstframe, val->_float - 1, &attachmatrix);
3177 Matrix4x4_CreateIdentity(&attachmatrix);
3179 // apply transformation by child entity matrix
3180 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3181 if (val->_float == 0)
3183 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);
3184 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3185 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]);
3186 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]);
3187 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]);
3188 Matrix4x4_Copy(&tagmatrix, out);
3190 // finally transformate by matrix of tag on parent entity
3191 Matrix4x4_Concat(out, &attachmatrix, &tagmatrix);
3192 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];
3193 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];
3194 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];
3195 Matrix4x4_Copy(&tagmatrix, out);
3199 if (attachloop > 255) // prevent runaway looping
3202 while ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_tag_entity)) && val->edict);
3205 // normal or RENDER_VIEWMODEL entity (or main parent entity on attach chain)
3206 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3207 if (val->_float == 0)
3209 // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype...
3210 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);
3211 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3212 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]);
3213 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]);
3214 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]);
3216 if ((val = PRVM_GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict)
3217 {// RENDER_VIEWMODEL magic
3218 Matrix4x4_Copy(&tagmatrix, out);
3219 ent = PRVM_EDICT_NUM(val->edict);
3221 val = PRVM_GETEDICTFIELDVALUE(ent, eval_scale);
3222 if (val->_float == 0)
3225 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);
3226 Matrix4x4_Concat(out, &entitymatrix, &tagmatrix);
3227 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]);
3228 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]);
3229 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]);
3232 // Cl_bob, ported from rendering code
3233 if (ent->fields.server->health > 0 && cl_bob.value && cl_bobcycle.value)
3236 // LordHavoc: this code is *weird*, but not replacable (I think it
3237 // should be done in QC on the server, but oh well, quake is quake)
3238 // LordHavoc: figured out bobup: the time at which the sin is at 180
3239 // degrees (which allows lengthening or squishing the peak or valley)
3240 cycle = sv.time/cl_bobcycle.value;
3241 cycle -= (int)cycle;
3242 if (cycle < cl_bobup.value)
3243 cycle = sin(M_PI * cycle / cl_bobup.value);
3245 cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value));
3246 // bob is proportional to velocity in the xy plane
3247 // (don't count Z, or jumping messes it up)
3248 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;
3249 bob = bob*0.3 + bob*0.7*cycle;
3250 out->m[2][3] += bound(-7, bob, 4);
3257 //float(entity ent, string tagname) gettagindex;
3259 void PF_gettagindex (void)
3261 prvm_edict_t *ent = PRVM_G_EDICT(OFS_PARM0);
3262 const char *tag_name = PRVM_G_STRING(OFS_PARM1);
3263 int modelindex, tag_index;
3265 if (ent == prog->edicts)
3266 PF_WARNING("gettagindex: can't affect world entity\n");
3267 if (ent->priv.server->free)
3268 PF_WARNING("gettagindex: can't affect free entity\n");
3270 modelindex = (int)ent->fields.server->modelindex;
3272 if (modelindex <= 0 || modelindex > MAX_MODELS)
3273 Con_DPrintf("gettagindex(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(ent));
3276 tag_index = SV_GetTagIndex(ent, tag_name);
3278 Con_DPrintf("gettagindex(entity #%i): tag \"%s\" not found\n", PRVM_NUM_FOR_EDICT(ent), tag_name);
3280 PRVM_G_FLOAT(OFS_RETURN) = tag_index;
3283 //vector(entity ent, float tagindex) gettaginfo;
3284 void PF_gettaginfo (void)
3286 prvm_edict_t *e = PRVM_G_EDICT(OFS_PARM0);
3287 int tagindex = (int)PRVM_G_FLOAT(OFS_PARM1);
3288 matrix4x4_t tag_matrix;
3291 returncode = SV_GetTagMatrix(&tag_matrix, e, tagindex);
3292 Matrix4x4_ToVectors(&tag_matrix, prog->globals.server->v_forward, prog->globals.server->v_right, prog->globals.server->v_up, PRVM_G_VECTOR(OFS_RETURN));
3297 PF_WARNING("gettagindex: can't affect world entity\n");
3300 PF_WARNING("gettagindex: can't affect free entity\n");
3303 Con_DPrintf("SV_GetTagMatrix(entity #%i): null or non-precached model\n", PRVM_NUM_FOR_EDICT(e));
3306 Con_DPrintf("SV_GetTagMatrix(entity #%i): model has no tag with requested index %i\n", PRVM_NUM_FOR_EDICT(e), tagindex);
3309 Con_DPrintf("SV_GetTagMatrix(entity #%i): runaway loop at attachment chain\n", PRVM_NUM_FOR_EDICT(e));
3315 /////////////////////////////////////////
3316 // DP_QC_FS_SEARCH extension
3318 // qc fs search handling
3319 #define MAX_SEARCHES 128
3321 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3323 void PR_Search_Init(void)
3325 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3328 void PR_Search_Reset(void)
3331 // reset the fssearch list
3332 for(i = 0; i < MAX_SEARCHES; i++)
3333 if(pr_fssearchlist[i])
3334 FS_FreeSearch(pr_fssearchlist[i]);
3335 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3342 float search_begin(string pattern, float caseinsensitive, float quiet)
3345 void PF_search_begin(void)
3348 const char *pattern;
3349 int caseinsens, quiet;
3351 pattern = PRVM_G_STRING(OFS_PARM0);
3352 if (!pattern || pattern[0] <= ' ')
3353 PF_ERROR("PF_search_begin: Bad string");
3355 caseinsens = PRVM_G_FLOAT(OFS_PARM1);
3356 quiet = PRVM_G_FLOAT(OFS_PARM2);
3358 for(handle = 0; handle < MAX_SEARCHES; handle++)
3359 if(!pr_fssearchlist[handle])
3362 if(handle >= MAX_SEARCHES)
3364 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3365 PRVM_G_FLOAT(OFS_RETURN) = -2;
3369 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3370 PRVM_G_FLOAT(OFS_RETURN) = -1;
3372 PRVM_G_FLOAT(OFS_RETURN) = handle;
3379 void search_end(float handle)
3382 void PF_search_end(void)
3386 handle = PRVM_G_FLOAT(OFS_PARM0);
3388 if(handle < 0 || handle >= MAX_SEARCHES)
3390 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3393 if(pr_fssearchlist[handle] == NULL)
3395 Con_Printf("PF_search_end: no such handle %i\n", handle);
3399 FS_FreeSearch(pr_fssearchlist[handle]);
3400 pr_fssearchlist[handle] = NULL;
3407 float search_getsize(float handle)
3410 void PF_search_getsize(void)
3414 handle = PRVM_G_FLOAT(OFS_PARM0);
3416 if(handle < 0 || handle >= MAX_SEARCHES)
3418 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3421 if(pr_fssearchlist[handle] == NULL)
3423 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3427 PRVM_G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3432 VM_search_getfilename
3434 string search_getfilename(float handle, float num)
3437 void PF_search_getfilename(void)
3439 int handle, filenum;
3442 handle = PRVM_G_FLOAT(OFS_PARM0);
3443 filenum = PRVM_G_FLOAT(OFS_PARM1);
3445 if(handle < 0 || handle >= MAX_SEARCHES)
3447 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3450 if(pr_fssearchlist[handle] == NULL)
3452 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3455 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3457 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3461 tmp = PR_GetTempString();
3462 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3464 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3467 void PF_cvar_string (void)
3473 str = PRVM_G_STRING(OFS_PARM0);
3474 var = Cvar_FindVar (str);
3477 tmp = PR_GetTempString();
3478 strcpy(tmp, var->string);
3482 PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(tmp);
3485 //void(entity clent) dropclient (DP_SV_DROPCLIENT)
3486 void PF_dropclient (void)
3489 client_t *oldhostclient;
3490 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
3491 if (clientnum < 0 || clientnum >= svs.maxclients)
3492 PF_WARNING("dropclient: not a client\n");
3493 if (!svs.clients[clientnum].active)
3494 PF_WARNING("dropclient: that client slot is not connected\n");
3495 oldhostclient = host_client;
3496 host_client = svs.clients + clientnum;
3497 SV_DropClient(false);
3498 host_client = oldhostclient;
3501 //entity() spawnclient (DP_SV_BOTCLIENT)
3502 void PF_spawnclient (void)
3506 pr_xfunction->builtinsprofile += 2;
3508 for (i = 0;i < svs.maxclients;i++)
3510 if (!svs.clients[i].active)
3512 pr_xfunction->builtinsprofile += 100;
3513 SV_ConnectClient (i, NULL);
3514 ed = PRVM_EDICT_NUM(i + 1);
3521 //float(entity clent) clienttype (DP_SV_BOTCLIENT)
3522 void PF_clienttype (void)
3525 clientnum = PRVM_G_EDICTNUM(OFS_PARM0) - 1;
3526 if (clientnum < 0 || clientnum >= svs.maxclients)
3527 PRVM_G_FLOAT(OFS_RETURN) = 3;
3528 else if (!svs.clients[clientnum].active)
3529 PRVM_G_FLOAT(OFS_RETURN) = 0;
3530 else if (svs.clients[clientnum].netconnection)
3531 PRVM_G_FLOAT(OFS_RETURN) = 1;
3533 PRVM_G_FLOAT(OFS_RETURN) = 2;
3536 builtin_t pr_builtin[] =
3539 PF_makevectors, // #1 void(entity e) makevectors
3540 PF_setorigin, // #2 void(entity e, vector o) setorigin
3541 PF_setmodel, // #3 void(entity e, string m) setmodel
3542 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3543 NULL, // #5 void(entity e, vector min, vector max) setabssize
3544 PF_break, // #6 void() break
3545 PF_random, // #7 float() random
3546 PF_sound, // #8 void(entity e, float chan, string samp) sound
3547 PF_normalize, // #9 vector(vector v) normalize
3548 PF_error, // #10 void(string e) error
3549 PF_objerror, // #11 void(string e) objerror
3550 PF_vlen, // #12 float(vector v) vlen
3551 PF_vectoyaw, // #13 float(vector v) vectoyaw
3552 PF_Spawn, // #14 entity() spawn
3553 PF_Remove, // #15 void(entity e) remove
3554 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3555 PF_checkclient, // #17 entity() clientlist
3556 PF_Find, // #18 entity(entity start, .string fld, string match) find
3557 PF_precache_sound, // #19 void(string s) precache_sound
3558 PF_precache_model, // #20 void(string s) precache_model
3559 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3560 PF_findradius, // #22 entity(vector org, float rad) findradius
3561 PF_bprint, // #23 void(string s) bprint
3562 PF_sprint, // #24 void(entity client, string s) sprint
3563 PF_dprint, // #25 void(string s) dprint
3564 PF_ftos, // #26 void(string s) ftos
3565 PF_vtos, // #27 void(string s) vtos
3566 PF_coredump, // #28 void() coredump
3567 PF_traceon, // #29 void() traceon
3568 PF_traceoff, // #30 void() traceoff
3569 PF_eprint, // #31 void(entity e) eprint
3570 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3572 PF_droptofloor, // #34 float() droptofloor
3573 PF_lightstyle, // #35 void(float style, string value) lightstyle
3574 PF_rint, // #36 float(float v) rint
3575 PF_floor, // #37 float(float v) floor
3576 PF_ceil, // #38 float(float v) ceil
3578 PF_checkbottom, // #40 float(entity e) checkbottom
3579 PF_pointcontents, // #41 float(vector v) pointcontents
3581 PF_fabs, // #43 float(float f) fabs
3582 PF_aim, // #44 vector(entity e, float speed) aim
3583 PF_cvar, // #45 float(string s) cvar
3584 PF_localcmd, // #46 void(string s) localcmd
3585 PF_nextent, // #47 entity(entity e) nextent
3586 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3587 PF_changeyaw, // #49 void() ChangeYaw
3589 PF_vectoangles, // #51 vector(vector v) vectoangles
3590 PF_WriteByte, // #52 void(float to, float f) WriteByte
3591 PF_WriteChar, // #53 void(float to, float f) WriteChar
3592 PF_WriteShort, // #54 void(float to, float f) WriteShort
3593 PF_WriteLong, // #55 void(float to, float f) WriteLong
3594 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3595 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3596 PF_WriteString, // #58 void(float to, string s) WriteString
3597 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3598 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3599 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3600 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3601 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3602 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3603 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3605 SV_MoveToGoal, // #67 void(float step) movetogoal
3606 PF_precache_file, // #68 string(string s) precache_file
3607 PF_makestatic, // #69 void(entity e) makestatic
3608 PF_changelevel, // #70 void(string s) changelevel
3610 PF_cvar_set, // #72 void(string var, string val) cvar_set
3611 PF_centerprint, // #73 void(entity client, strings) centerprint
3612 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3613 PF_precache_model, // #75 string(string s) precache_model2
3614 PF_precache_sound, // #76 string(string s) precache_sound2
3615 PF_precache_file, // #77 string(string s) precache_file2
3616 PF_setspawnparms, // #78 void(entity e) setspawnparms
3619 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3628 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3629 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3630 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3631 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3632 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3633 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3634 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3635 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3636 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3637 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3648 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3649 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3650 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3651 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3652 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3653 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3654 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3655 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3656 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3657 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3658 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3659 a a a a a a a a // #120-199
3660 a a a a a a a a a a // #200-299
3661 a a a a a a a a a a // #300-399
3662 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3663 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3664 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3665 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3666 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3667 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3668 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3669 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3670 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3671 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3672 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3673 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3674 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3675 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3676 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3677 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3678 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3679 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3680 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3681 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3682 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3683 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3684 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3685 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3686 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3687 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3688 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3689 PF_te_explosion2, // #427 void(vector org, float colorstart, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3690 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3691 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3692 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3693 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3694 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3695 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3696 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3697 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3698 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3699 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3700 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3701 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3702 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3703 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3704 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3705 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3706 PF_search_begin, // #444 float(string pattern, float caseinsensitive, float quiet) search_begin (DP_FS_SEARCH)
3707 PF_search_end, // #445 void(float handle) search_end (DP_FS_SEARCH)
3708 PF_search_getsize, // #446 float(float handle) search_getsize (DP_FS_SEARCH)
3709 PF_search_getfilename, // #447 string(float handle, float num) search_getfilename (DP_FS_SEARCH)
3710 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3711 PF_findflags, // #449 entity(entity start, .float fld, float match) findflags (DP_QC_FINDFLAGS)
3712 PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
3713 PF_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_QC_GETTAGINFO)
3714 PF_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_QC_GETTAGINFO)
3715 PF_dropclient, // #453 void(entity clent) dropclient (DP_SV_DROPCLIENT)
3716 PF_spawnclient, // #454 entity() spawnclient (DP_SV_BOTCLIENT)
3717 PF_clienttype, // #455 float(entity clent) clienttype (DP_SV_BOTCLIENT)
3722 a a a a // #460-499 (LordHavoc)
3725 builtin_t *pr_builtins = pr_builtin;
3726 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3728 void PR_Cmd_Init(void)
3734 void PR_Cmd_Shutdown(void)
3738 void PR_Cmd_Reset(void)
3741 PR_Files_CloseAll();