2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 cvar_t sv_aim = {CVAR_SAVE, "sv_aim", "2"}; //"0.93"}; // LordHavoc: disabled autoaim by default
24 cvar_t pr_zone_min_strings = {0, "pr_zone_min_strings", "64"};
26 mempool_t *pr_strings_mempool;
28 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
29 #define STRINGTEMP_BUFFERS 16
30 #define STRINGTEMP_LENGTH 4096
31 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
32 static int pr_string_tempindex = 0;
34 static char *PR_GetTempString(void)
37 s = pr_string_temp[pr_string_tempindex];
38 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
42 #define RETURN_EDICT(e) (G_INT(OFS_RETURN) = EDICT_TO_PROG(e))
43 #define PF_WARNING(s) do{Con_Printf(s);PR_PrintState();return;}while(0)
44 #define PF_ERROR(s) do{Host_Error(s);return;}while(0)
48 ===============================================================================
52 ===============================================================================
56 void PF_VarString(int first, char *out, int outlength)
62 outend = out + outlength - 1;
63 for (i = first;i < pr_argc && out < outend;i++)
65 s = G_STRING((OFS_PARM0+i*3));
66 while (out < outend && *s)
72 char *ENGINE_EXTENSIONS =
82 "DP_ENT_CUSTOMCOLORMAP "
83 "DP_ENT_EXTERIORMODELTOCLIENT "
85 "DP_ENT_LOWPRECISION "
88 "DP_GFX_EXTERNALTEXTURES "
90 "DP_GFX_QUAKE3MODELTAGS "
94 "DP_HALFLIFE_MAP_CVAR "
98 "DP_MOVETYPEBOUNCEMISSILE "
105 "DP_QC_FINDCHAINFLOAT "
107 "DP_QC_FS_SEARCH " // Black: same as in the menu qc
112 "DP_QC_SINCOSSQRTPOW "
115 "DP_QC_TRACE_MOVETYPE_HITMODEL "
116 "DP_QC_TRACE_MOVETYPE_WORLDONLY "
117 "DP_QC_VECTORVECTORS "
123 "DP_SV_DRAWONLYTOCLIENT "
125 "DP_SV_EXTERIORMODELTOCLIENT "
126 "DP_SV_NODRAWTOCLIENT "
127 "DP_SV_PLAYERPHYSICS "
133 "DP_TE_EXPLOSIONRGB "
135 "DP_TE_PARTICLECUBE "
136 "DP_TE_PARTICLERAIN "
137 "DP_TE_PARTICLESNOW "
139 "DP_TE_QUADEFFECTS1 "
142 "DP_TE_STANDARDEFFECTBUILTINS "
145 "KRIMZON_SV_PARSECLIENTCOMMAND "
148 "TENEBRAE_GFX_DLIGHTS "
152 qboolean checkextension(char *name)
157 for (e = ENGINE_EXTENSIONS;*e;e++)
164 while (*e && *e != ' ')
166 if (e - start == len)
167 if (!strncasecmp(start, name, len))
177 returns true if the extension is supported by the server
179 checkextension(extensionname)
182 void PF_checkextension (void)
184 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
191 This is a TERMINAL error, which will kill off the entire server.
200 char string[STRINGTEMP_LENGTH];
202 PF_VarString(0, string, sizeof(string));
203 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
204 ed = PROG_TO_EDICT(pr_global_struct->self);
207 PF_ERROR("Program error");
214 Dumps out self, then an error message. The program is aborted and self is
215 removed, but the level can continue.
220 void PF_objerror (void)
223 char string[STRINGTEMP_LENGTH];
225 PF_VarString(0, string, sizeof(string));
226 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), string);
227 ed = PROG_TO_EDICT(pr_global_struct->self);
237 Writes new values for v_forward, v_up, and v_right based on angles
241 void PF_makevectors (void)
243 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
250 Writes new values for v_forward, v_up, and v_right based on the given forward vector
251 vectorvectors(vector, vector)
254 void PF_vectorvectors (void)
256 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
257 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
264 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.
266 setorigin (entity, origin)
269 void PF_setorigin (void)
274 e = G_EDICT(OFS_PARM0);
276 PF_WARNING("setorigin: can not modify world entity\n");
278 PF_WARNING("setorigin: can not modify free entity\n");
279 org = G_VECTOR(OFS_PARM1);
280 VectorCopy (org, e->v->origin);
281 SV_LinkEdict (e, false);
285 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
289 for (i=0 ; i<3 ; i++)
291 PF_ERROR("SetMinMaxSize: backwards mins/maxs\n");
293 // set derived values
294 VectorCopy (min, e->v->mins);
295 VectorCopy (max, e->v->maxs);
296 VectorSubtract (max, min, e->v->size);
298 SV_LinkEdict (e, false);
305 the size box is rotated by the current angle
306 LordHavoc: no it isn't...
308 setsize (entity, minvector, maxvector)
311 void PF_setsize (void)
316 e = G_EDICT(OFS_PARM0);
318 PF_WARNING("setsize: can not modify world entity\n");
320 PF_WARNING("setsize: can not modify free entity\n");
321 min = G_VECTOR(OFS_PARM1);
322 max = G_VECTOR(OFS_PARM2);
323 SetMinMaxSize (e, min, max, false);
331 setmodel(entity, model)
334 void PF_setmodel (void)
341 e = G_EDICT(OFS_PARM0);
343 PF_WARNING("setmodel: can not modify world entity\n");
345 PF_WARNING("setmodel: can not modify free entity\n");
346 m = G_STRING(OFS_PARM1);
348 // check to see if model was properly precached
349 for (i=0, check = sv.model_precache ; *check ; i++, check++)
350 if (!strcmp(*check, m))
354 PF_WARNING("setmodel: no precache\n");
357 e->v->model = PR_SetString(*check);
358 e->v->modelindex = i;
360 mod = sv.models[ (int)e->v->modelindex];
363 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
365 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
372 broadcast print to everyone on server
377 void PF_bprint (void)
379 char string[STRINGTEMP_LENGTH];
380 PF_VarString(0, string, sizeof(string));
381 SV_BroadcastPrintf("%s", string);
388 single print to a specific client
390 sprint(clientent, value)
393 void PF_sprint (void)
397 char string[STRINGTEMP_LENGTH];
399 entnum = G_EDICTNUM(OFS_PARM0);
401 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
403 Con_Printf ("tried to sprint to a non-client\n");
407 client = svs.clients + entnum-1;
408 if (!client->netconnection)
410 PF_VarString(1, string, sizeof(string));
411 MSG_WriteChar(&client->message,svc_print);
412 MSG_WriteString(&client->message, string);
420 single print to a specific client
422 centerprint(clientent, value)
425 void PF_centerprint (void)
429 char string[STRINGTEMP_LENGTH];
431 entnum = G_EDICTNUM(OFS_PARM0);
433 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
435 Con_Printf ("tried to sprint to a non-client\n");
439 client = svs.clients + entnum-1;
440 if (!client->netconnection)
442 PF_VarString(1, string, sizeof(string));
443 MSG_WriteChar(&client->message,svc_centerprint);
444 MSG_WriteString(&client->message, string);
452 vector normalize(vector)
455 void PF_normalize (void)
461 value1 = G_VECTOR(OFS_PARM0);
463 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
467 newvalue[0] = newvalue[1] = newvalue[2] = 0;
471 newvalue[0] = value1[0] * new;
472 newvalue[1] = value1[1] * new;
473 newvalue[2] = value1[2] * new;
476 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
491 value1 = G_VECTOR(OFS_PARM0);
493 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
496 G_FLOAT(OFS_RETURN) = new;
503 float vectoyaw(vector)
506 void PF_vectoyaw (void)
511 value1 = G_VECTOR(OFS_PARM0);
513 if (value1[1] == 0 && value1[0] == 0)
517 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
522 G_FLOAT(OFS_RETURN) = yaw;
530 vector vectoangles(vector)
533 void PF_vectoangles (void)
539 value1 = G_VECTOR(OFS_PARM0);
541 if (value1[1] == 0 && value1[0] == 0)
551 // LordHavoc: optimized a bit
554 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
558 else if (value1[1] > 0)
563 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
564 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
569 G_FLOAT(OFS_RETURN+0) = pitch;
570 G_FLOAT(OFS_RETURN+1) = yaw;
571 G_FLOAT(OFS_RETURN+2) = 0;
578 Returns a number from 0<= num < 1
583 void PF_random (void)
587 num = (rand ()&0x7fff) / ((float)0x7fff);
589 G_FLOAT(OFS_RETURN) = num;
596 particle(origin, color, count)
599 void PF_particle (void)
605 org = G_VECTOR(OFS_PARM0);
606 dir = G_VECTOR(OFS_PARM1);
607 color = G_FLOAT(OFS_PARM2);
608 count = G_FLOAT(OFS_PARM3);
609 SV_StartParticle (org, dir, color, count);
619 void PF_ambientsound (void)
624 float vol, attenuation;
625 int i, soundnum, large;
627 pos = G_VECTOR (OFS_PARM0);
628 samp = G_STRING(OFS_PARM1);
629 vol = G_FLOAT(OFS_PARM2);
630 attenuation = G_FLOAT(OFS_PARM3);
632 // check to see if samp was properly precached
633 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
634 if (!strcmp(*check,samp))
639 Con_Printf ("no precache: %s\n", samp);
647 // add an svc_spawnambient command to the level signon packet
650 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
652 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
654 for (i=0 ; i<3 ; i++)
655 MSG_WriteDPCoord(&sv.signon, pos[i]);
658 MSG_WriteShort (&sv.signon, soundnum);
660 MSG_WriteByte (&sv.signon, soundnum);
662 MSG_WriteByte (&sv.signon, vol*255);
663 MSG_WriteByte (&sv.signon, attenuation*64);
671 Each entity can have eight independant sound sources, like voice,
674 Channel 0 is an auto-allocate channel, the others override anything
675 already running on that entity/channel pair.
677 An attenuation of 0 will play full volume everywhere in the level.
678 Larger attenuations will drop off.
690 entity = G_EDICT(OFS_PARM0);
691 channel = G_FLOAT(OFS_PARM1);
692 sample = G_STRING(OFS_PARM2);
693 volume = G_FLOAT(OFS_PARM3) * 255;
694 attenuation = G_FLOAT(OFS_PARM4);
696 if (volume < 0 || volume > 255)
697 PF_WARNING("SV_StartSound: volume must be in range 0-1\n");
699 if (attenuation < 0 || attenuation > 4)
700 PF_WARNING("SV_StartSound: attenuation must be in range 0-4\n");
702 if (channel < 0 || channel > 7)
703 PF_WARNING("SV_StartSound: channel must be in range 0-7\n");
705 SV_StartSound (entity, channel, sample, volume, attenuation);
717 PF_ERROR("break: break statement\n");
724 Used for use tracing and shot targeting
725 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
726 if the tryents flag is set.
728 traceline (vector1, vector2, tryents)
731 void PF_traceline (void)
738 pr_xfunction->builtinsprofile += 30;
740 v1 = G_VECTOR(OFS_PARM0);
741 v2 = G_VECTOR(OFS_PARM1);
742 move = G_FLOAT(OFS_PARM2);
743 ent = G_EDICT(OFS_PARM3);
745 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, move, ent);
747 pr_global_struct->trace_allsolid = trace.allsolid;
748 pr_global_struct->trace_startsolid = trace.startsolid;
749 pr_global_struct->trace_fraction = trace.fraction;
750 pr_global_struct->trace_inwater = trace.inwater;
751 pr_global_struct->trace_inopen = trace.inopen;
752 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
753 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
754 pr_global_struct->trace_plane_dist = trace.plane.dist;
756 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
758 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
759 // FIXME: add trace_endcontents
767 Used for use tracing and shot targeting
768 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
769 if the tryents flag is set.
771 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
774 // LordHavoc: added this for my own use, VERY useful, similar to traceline
775 void PF_tracebox (void)
777 float *v1, *v2, *m1, *m2;
782 pr_xfunction->builtinsprofile += 30;
784 v1 = G_VECTOR(OFS_PARM0);
785 m1 = G_VECTOR(OFS_PARM1);
786 m2 = G_VECTOR(OFS_PARM2);
787 v2 = G_VECTOR(OFS_PARM3);
788 move = G_FLOAT(OFS_PARM4);
789 ent = G_EDICT(OFS_PARM5);
791 trace = SV_Move (v1, m1, m2, v2, move, ent);
793 pr_global_struct->trace_allsolid = trace.allsolid;
794 pr_global_struct->trace_startsolid = trace.startsolid;
795 pr_global_struct->trace_fraction = trace.fraction;
796 pr_global_struct->trace_inwater = trace.inwater;
797 pr_global_struct->trace_inopen = trace.inopen;
798 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
799 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
800 pr_global_struct->trace_plane_dist = trace.plane.dist;
802 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
804 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
807 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
808 void PF_TraceToss (void)
814 pr_xfunction->builtinsprofile += 600;
816 ent = G_EDICT(OFS_PARM0);
817 if (ent == sv.edicts)
818 PF_WARNING("tracetoss: can not use world entity\n");
819 ignore = G_EDICT(OFS_PARM1);
821 trace = SV_Trace_Toss (ent, ignore);
823 pr_global_struct->trace_allsolid = trace.allsolid;
824 pr_global_struct->trace_startsolid = trace.startsolid;
825 pr_global_struct->trace_fraction = trace.fraction;
826 pr_global_struct->trace_inwater = trace.inwater;
827 pr_global_struct->trace_inopen = trace.inopen;
828 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
829 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
830 pr_global_struct->trace_plane_dist = trace.plane.dist;
832 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
834 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
842 Returns true if the given entity can move to the given position from it's
843 current position by walking or rolling.
845 scalar checkpos (entity, vector)
848 void PF_checkpos (void)
852 //============================================================================
855 qbyte checkpvs[MAX_MAP_LEAFS/8];
857 int PF_newcheckclient (int check)
863 // cycle to the next one
865 check = bound(1, check, svs.maxclients);
866 if (check == svs.maxclients)
874 pr_xfunction->builtinsprofile++;
876 if (i == svs.maxclients+1)
878 // look up the client's edict
880 // check if it is to be ignored, but never ignore the one we started on (prevent infinite loop)
881 if (i != check && (ent->e->free || ent->v->health <= 0 || ((int)ent->v->flags & FL_NOTARGET)))
883 // found a valid client (possibly the same one again)
887 // get the PVS for the entity
888 VectorAdd(ent->v->origin, ent->v->view_ofs, org);
890 if (sv.worldmodel && sv.worldmodel->brush.FatPVS)
891 checkpvsbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, org, 0, checkpvs, sizeof(checkpvs));
900 Returns a client (or object that has a client enemy) that would be a
903 If there is more than one valid option, they are cycled each frame
905 If (self.origin + self.viewofs) is not in the PVS of the current target,
906 it is not returned at all.
911 int c_invis, c_notvis;
912 void PF_checkclient (void)
917 // find a new check if on a new frame
918 if (sv.time - sv.lastchecktime >= 0.1)
920 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
921 sv.lastchecktime = sv.time;
924 // return check if it might be visible
925 ent = EDICT_NUM(sv.lastcheck);
926 if (ent->e->free || ent->v->health <= 0)
928 RETURN_EDICT(sv.edicts);
932 // if current entity can't possibly see the check entity, return 0
933 self = PROG_TO_EDICT(pr_global_struct->self);
934 VectorAdd(self->v->origin, self->v->view_ofs, view);
935 if (sv.worldmodel && checkpvsbytes && !sv.worldmodel->brush.BoxTouchingPVS(sv.worldmodel, checkpvs, view, view))
938 RETURN_EDICT(sv.edicts);
942 // might be able to see it
947 //============================================================================
954 Sends text over to the client's execution buffer
956 stuffcmd (clientent, value)
959 void PF_stuffcmd (void)
965 entnum = G_EDICTNUM(OFS_PARM0);
966 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
968 Con_Printf("Can't stuffcmd to a non-client");
971 str = G_STRING(OFS_PARM1);
974 if ((host_client = svs.clients + entnum-1) && host_client->netconnection)
975 Host_ClientCommands ("%s", str);
983 Sends text to server console
988 void PF_localcmd (void)
990 Cbuf_AddText(G_STRING(OFS_PARM0));
1002 G_FLOAT(OFS_RETURN) = Cvar_VariableValue(G_STRING(OFS_PARM0));
1012 void PF_cvar_set (void)
1014 Cvar_Set(G_STRING(OFS_PARM0), G_STRING(OFS_PARM1));
1021 Returns a chain of entities that have origins within a spherical area
1023 findradius (origin, radius)
1026 void PF_findradius (void)
1028 edict_t *ent, *chain;
1035 chain = (edict_t *)sv.edicts;
1037 org = G_VECTOR(OFS_PARM0);
1038 radius = G_FLOAT(OFS_PARM1);
1039 radius2 = radius * radius;
1041 ent = NEXT_EDICT(sv.edicts);
1042 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1044 pr_xfunction->builtinsprofile++;
1047 if (ent->v->solid == SOLID_NOT)
1050 // LordHavoc: compare against bounding box rather than center,
1051 // and use DotProduct instead of Length, major speedup
1052 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1053 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1054 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1055 if (DotProduct(eorg, eorg) > radius2)
1058 ent->v->chain = EDICT_TO_PROG(chain);
1062 RETURN_EDICT(chain);
1071 void PF_dprint (void)
1073 char string[STRINGTEMP_LENGTH];
1074 if (developer.integer)
1076 PF_VarString(0, string, sizeof(string));
1077 Con_Printf("%s",string);
1085 v = G_FLOAT(OFS_PARM0);
1087 s = PR_GetTempString();
1088 if ((float)((int)v) == v)
1089 sprintf(s, "%i", (int)v);
1091 sprintf(s, "%f", v);
1092 G_INT(OFS_RETURN) = PR_SetString(s);
1098 v = G_FLOAT(OFS_PARM0);
1099 G_FLOAT(OFS_RETURN) = fabs(v);
1105 s = PR_GetTempString();
1106 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1107 G_INT(OFS_RETURN) = PR_SetString(s);
1113 s = PR_GetTempString();
1114 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1115 G_INT(OFS_RETURN) = PR_SetString(s);
1118 void PF_Spawn (void)
1121 pr_xfunction->builtinsprofile += 20;
1126 void PF_Remove (void)
1129 pr_xfunction->builtinsprofile += 20;
1131 ed = G_EDICT(OFS_PARM0);
1132 if (ed == sv.edicts)
1133 PF_WARNING("remove: tried to remove world\n");
1134 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1135 PF_WARNING("remove: tried to remove a client\n");
1136 // LordHavoc: not an error because id1 progs did this in some cases (killtarget removes entities, even if they are already removed in some cases...)
1137 if (ed->e->free && developer.integer)
1138 PF_WARNING("remove: tried to remove an entity that was already removed\n");
1143 // entity (entity start, .string field, string match) find = #5;
1151 e = G_EDICTNUM(OFS_PARM0);
1152 f = G_INT(OFS_PARM1);
1153 s = G_STRING(OFS_PARM2);
1156 RETURN_EDICT(sv.edicts);
1160 for (e++ ; e < sv.num_edicts ; e++)
1162 pr_xfunction->builtinsprofile++;
1176 RETURN_EDICT(sv.edicts);
1179 // LordHavoc: added this for searching float, int, and entity reference fields
1180 void PF_FindFloat (void)
1187 e = G_EDICTNUM(OFS_PARM0);
1188 f = G_INT(OFS_PARM1);
1189 s = G_FLOAT(OFS_PARM2);
1191 for (e++ ; e < sv.num_edicts ; e++)
1193 pr_xfunction->builtinsprofile++;
1197 if (E_FLOAT(ed,f) == s)
1204 RETURN_EDICT(sv.edicts);
1207 // chained search for strings in entity fields
1208 // entity(.string field, string match) findchain = #402;
1209 void PF_findchain (void)
1214 edict_t *ent, *chain;
1216 chain = (edict_t *)sv.edicts;
1218 f = G_INT(OFS_PARM0);
1219 s = G_STRING(OFS_PARM1);
1222 RETURN_EDICT(sv.edicts);
1226 ent = NEXT_EDICT(sv.edicts);
1227 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1229 pr_xfunction->builtinsprofile++;
1232 t = E_STRING(ent,f);
1238 ent->v->chain = EDICT_TO_PROG(chain);
1242 RETURN_EDICT(chain);
1245 // LordHavoc: chained search for float, int, and entity reference fields
1246 // entity(.string field, float match) findchainfloat = #403;
1247 void PF_findchainfloat (void)
1252 edict_t *ent, *chain;
1254 chain = (edict_t *)sv.edicts;
1256 f = G_INT(OFS_PARM0);
1257 s = G_FLOAT(OFS_PARM1);
1259 ent = NEXT_EDICT(sv.edicts);
1260 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1262 pr_xfunction->builtinsprofile++;
1265 if (E_FLOAT(ent,f) != s)
1268 ent->v->chain = EDICT_TO_PROG(chain);
1272 RETURN_EDICT(chain);
1275 void PR_CheckEmptyString (char *s)
1278 PF_ERROR("Bad string");
1281 void PF_precache_file (void)
1282 { // precache_file is only used to copy files with qcc, it does nothing
1283 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1286 void PF_precache_sound (void)
1291 if (sv.state != ss_loading)
1292 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1294 s = G_STRING(OFS_PARM0);
1295 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1296 PR_CheckEmptyString (s);
1298 for (i=0 ; i<MAX_SOUNDS ; i++)
1300 if (!sv.sound_precache[i])
1302 sv.sound_precache[i] = s;
1305 if (!strcmp(sv.sound_precache[i], s))
1308 PF_ERROR("PF_precache_sound: overflow");
1311 void PF_precache_model (void)
1316 if (sv.state != ss_loading)
1317 PF_ERROR("PF_Precache_*: Precache can only be done in spawn functions");
1319 s = G_STRING(OFS_PARM0);
1320 if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
1322 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1323 PR_CheckEmptyString (s);
1325 for (i=0 ; i<MAX_MODELS ; i++)
1327 if (!sv.model_precache[i])
1329 sv.model_precache[i] = s;
1330 sv.models[i] = Mod_ForName (s, true, false, false);
1333 if (!strcmp(sv.model_precache[i], s))
1336 PF_ERROR("PF_precache_model: overflow");
1340 void PF_coredump (void)
1345 void PF_traceon (void)
1350 void PF_traceoff (void)
1355 void PF_eprint (void)
1357 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1364 float(float yaw, float dist) walkmove
1367 void PF_walkmove (void)
1375 // assume failure if it returns early
1376 G_FLOAT(OFS_RETURN) = 0;
1378 ent = PROG_TO_EDICT(pr_global_struct->self);
1379 if (ent == sv.edicts)
1380 PF_WARNING("walkmove: can not modify world entity\n");
1382 PF_WARNING("walkmove: can not modify free entity\n");
1383 yaw = G_FLOAT(OFS_PARM0);
1384 dist = G_FLOAT(OFS_PARM1);
1386 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1389 yaw = yaw*M_PI*2 / 360;
1391 move[0] = cos(yaw)*dist;
1392 move[1] = sin(yaw)*dist;
1395 // save program state, because SV_movestep may call other progs
1396 oldf = pr_xfunction;
1397 oldself = pr_global_struct->self;
1399 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1402 // restore program state
1403 pr_xfunction = oldf;
1404 pr_global_struct->self = oldself;
1414 void PF_droptofloor (void)
1420 // assume failure if it returns early
1421 G_FLOAT(OFS_RETURN) = 0;
1423 ent = PROG_TO_EDICT(pr_global_struct->self);
1424 if (ent == sv.edicts)
1425 PF_WARNING("droptofloor: can not modify world entity\n");
1427 PF_WARNING("droptofloor: can not modify free entity\n");
1429 VectorCopy (ent->v->origin, end);
1432 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1434 if (trace.fraction != 1)
1436 VectorCopy (trace.endpos, ent->v->origin);
1437 SV_LinkEdict (ent, false);
1438 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1439 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1440 G_FLOAT(OFS_RETURN) = 1;
1441 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1442 ent->e->suspendedinairflag = true;
1450 void(float style, string value) lightstyle
1453 void PF_lightstyle (void)
1460 style = G_FLOAT(OFS_PARM0);
1461 val = G_STRING(OFS_PARM1);
1463 // change the string in sv
1464 sv.lightstyles[style] = val;
1466 // send message to all clients on this server
1467 if (sv.state != ss_active)
1470 for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
1472 if (client->netconnection)
1474 MSG_WriteChar (&client->message, svc_lightstyle);
1475 MSG_WriteChar (&client->message,style);
1476 MSG_WriteString (&client->message, val);
1484 f = G_FLOAT(OFS_PARM0);
1486 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1488 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1490 void PF_floor (void)
1492 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1496 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1505 void PF_checkbottom (void)
1507 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1515 void PF_pointcontents (void)
1517 G_FLOAT(OFS_RETURN) = SV_PointQ1Contents(G_VECTOR(OFS_PARM0));
1524 entity nextent(entity)
1527 void PF_nextent (void)
1532 i = G_EDICTNUM(OFS_PARM0);
1535 pr_xfunction->builtinsprofile++;
1537 if (i == sv.num_edicts)
1539 RETURN_EDICT(sv.edicts);
1555 Pick a vector for the player to shoot along
1556 vector aim(entity, missilespeed)
1561 edict_t *ent, *check, *bestent;
1562 vec3_t start, dir, end, bestdir;
1565 float dist, bestdist;
1568 // assume failure if it returns early
1569 VectorClear(G_VECTOR(OFS_RETURN));
1571 ent = G_EDICT(OFS_PARM0);
1572 if (ent == sv.edicts)
1573 PF_WARNING("aim: can not use world entity\n");
1575 PF_WARNING("aim: can not use free entity\n");
1576 speed = G_FLOAT(OFS_PARM1);
1578 VectorCopy (ent->v->origin, start);
1581 // try sending a trace straight
1582 VectorCopy (pr_global_struct->v_forward, dir);
1583 VectorMA (start, 2048, dir, end);
1584 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1585 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1586 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1588 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1593 // try all possible entities
1594 VectorCopy (dir, bestdir);
1595 bestdist = sv_aim.value;
1598 check = NEXT_EDICT(sv.edicts);
1599 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1601 pr_xfunction->builtinsprofile++;
1602 if (check->v->takedamage != DAMAGE_AIM)
1606 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1607 continue; // don't aim at teammate
1608 for (j=0 ; j<3 ; j++)
1609 end[j] = check->v->origin[j]
1610 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1611 VectorSubtract (end, start, dir);
1612 VectorNormalize (dir);
1613 dist = DotProduct (dir, pr_global_struct->v_forward);
1614 if (dist < bestdist)
1615 continue; // to far to turn
1616 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1617 if (tr.ent == check)
1618 { // can shoot at this one
1626 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1627 dist = DotProduct (dir, pr_global_struct->v_forward);
1628 VectorScale (pr_global_struct->v_forward, dist, end);
1630 VectorNormalize (end);
1631 VectorCopy (end, G_VECTOR(OFS_RETURN));
1635 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1643 This was a major timewaster in progs, so it was converted to C
1646 void PF_changeyaw (void)
1649 float ideal, current, move, speed;
1651 ent = PROG_TO_EDICT(pr_global_struct->self);
1652 if (ent == sv.edicts)
1653 PF_WARNING("changeyaw: can not modify world entity\n");
1655 PF_WARNING("changeyaw: can not modify free entity\n");
1656 current = ANGLEMOD(ent->v->angles[1]);
1657 ideal = ent->v->ideal_yaw;
1658 speed = ent->v->yaw_speed;
1660 if (current == ideal)
1662 move = ideal - current;
1663 if (ideal > current)
1684 ent->v->angles[1] = ANGLEMOD (current + move);
1692 void PF_changepitch (void)
1695 float ideal, current, move, speed;
1698 ent = G_EDICT(OFS_PARM0);
1699 if (ent == sv.edicts)
1700 PF_WARNING("changepitch: can not modify world entity\n");
1702 PF_WARNING("changepitch: can not modify free entity\n");
1703 current = ANGLEMOD( ent->v->angles[0] );
1704 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1705 ideal = val->_float;
1708 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1711 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1712 speed = val->_float;
1715 PF_WARNING("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch\n");
1719 if (current == ideal)
1721 move = ideal - current;
1722 if (ideal > current)
1743 ent->v->angles[0] = ANGLEMOD (current + move);
1747 ===============================================================================
1751 ===============================================================================
1754 #define MSG_BROADCAST 0 // unreliable to all
1755 #define MSG_ONE 1 // reliable to one (msg_entity)
1756 #define MSG_ALL 2 // reliable to all
1757 #define MSG_INIT 3 // write to the init string
1759 sizebuf_t *WriteDest (void)
1765 dest = G_FLOAT(OFS_PARM0);
1769 return &sv.datagram;
1772 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1773 entnum = NUM_FOR_EDICT(ent);
1774 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
1775 Host_Error("WriteDest: tried to write to non-client\n");
1776 return &svs.clients[entnum-1].message;
1779 return &sv.reliable_datagram;
1785 Host_Error("WriteDest: bad destination");
1792 void PF_WriteByte (void)
1794 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1797 void PF_WriteChar (void)
1799 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1802 void PF_WriteShort (void)
1804 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1807 void PF_WriteLong (void)
1809 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1812 void PF_WriteAngle (void)
1814 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1817 void PF_WriteCoord (void)
1819 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1822 void PF_WriteString (void)
1824 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1828 void PF_WriteEntity (void)
1830 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1833 //=============================================================================
1835 void PF_makestatic (void)
1840 ent = G_EDICT(OFS_PARM0);
1841 if (ent == sv.edicts)
1842 PF_WARNING("makestatic: can not modify world entity\n");
1844 PF_WARNING("makestatic: can not modify free entity\n");
1847 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1852 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1853 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1854 MSG_WriteShort (&sv.signon, ent->v->frame);
1858 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1859 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1860 MSG_WriteByte (&sv.signon, ent->v->frame);
1863 MSG_WriteByte (&sv.signon, ent->v->colormap);
1864 MSG_WriteByte (&sv.signon, ent->v->skin);
1865 for (i=0 ; i<3 ; i++)
1867 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1868 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1871 // throw the entity away now
1875 //=============================================================================
1882 void PF_setspawnparms (void)
1888 ent = G_EDICT(OFS_PARM0);
1889 i = NUM_FOR_EDICT(ent);
1890 if (i < 1 || i > svs.maxclients || !svs.clients[i-1].active)
1892 Con_Printf("tried to setspawnparms on a non-client\n");
1896 // copy spawn parms out of the client_t
1897 client = svs.clients + i-1;
1898 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1899 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1907 void PF_changelevel (void)
1911 // make sure we don't issue two changelevels
1912 if (svs.changelevel_issued)
1914 svs.changelevel_issued = true;
1916 s = G_STRING(OFS_PARM0);
1917 Cbuf_AddText (va("changelevel %s\n",s));
1922 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1927 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1932 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1939 Returns a vector of length < 1
1944 void PF_randomvec (void)
1949 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1950 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1951 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1953 while (DotProduct(temp, temp) >= 1);
1954 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1961 Returns a color vector indicating the lighting at the requested point.
1963 (Internal Operation note: actually measures the light beneath the point, just like
1964 the model lighting on the client)
1969 void PF_GetLight (void)
1971 vec3_t ambientcolor, diffusecolor, diffusenormal;
1973 p = G_VECTOR(OFS_PARM0);
1974 VectorClear(ambientcolor);
1975 VectorClear(diffusecolor);
1976 VectorClear(diffusenormal);
1977 if (sv.worldmodel && sv.worldmodel->brush.LightPoint)
1978 sv.worldmodel->brush.LightPoint(sv.worldmodel, p, ambientcolor, diffusecolor, diffusenormal);
1979 VectorMA(ambientcolor, 0.5, diffusecolor, G_VECTOR(OFS_RETURN));
1982 #define MAX_QC_CVARS 128
1983 cvar_t qc_cvar[MAX_QC_CVARS];
1986 void PF_registercvar (void)
1990 name = G_STRING(OFS_PARM0);
1991 value = G_STRING(OFS_PARM1);
1992 G_FLOAT(OFS_RETURN) = 0;
1993 // first check to see if it has already been defined
1994 if (Cvar_FindVar (name))
1997 // check for overlap with a command
1998 if (Cmd_Exists (name))
2000 Con_Printf ("PF_registercvar: %s is a command\n", name);
2004 if (currentqc_cvar >= MAX_QC_CVARS)
2005 PF_ERROR("PF_registercvar: ran out of cvar slots\n");
2007 // copy the name and value
2008 variable = &qc_cvar[currentqc_cvar++];
2009 variable->name = Z_Malloc (strlen(name)+1);
2010 strcpy (variable->name, name);
2011 variable->string = Z_Malloc (strlen(value)+1);
2012 strcpy (variable->string, value);
2013 variable->value = atof (value);
2015 Cvar_RegisterVariable(variable);
2016 G_FLOAT(OFS_RETURN) = 1; // success
2023 returns the minimum of two supplied floats
2030 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2032 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2033 else if (pr_argc >= 3)
2036 float f = G_FLOAT(OFS_PARM0);
2037 for (i = 1;i < pr_argc;i++)
2038 if (G_FLOAT((OFS_PARM0+i*3)) < f)
2039 f = G_FLOAT((OFS_PARM0+i*3));
2040 G_FLOAT(OFS_RETURN) = f;
2044 G_FLOAT(OFS_RETURN) = 0;
2045 PF_WARNING("min: must supply at least 2 floats\n");
2053 returns the maximum of two supplied floats
2060 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2062 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2063 else if (pr_argc >= 3)
2066 float f = G_FLOAT(OFS_PARM0);
2067 for (i = 1;i < pr_argc;i++)
2068 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2069 f = G_FLOAT((OFS_PARM0+i*3));
2070 G_FLOAT(OFS_RETURN) = f;
2074 G_FLOAT(OFS_RETURN) = 0;
2075 PF_WARNING("max: must supply at least 2 floats\n");
2083 returns number bounded by supplied range
2085 min(min, value, max)
2088 void PF_bound (void)
2090 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2097 returns a raised to power b
2104 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2111 copies data from one entity to another
2113 copyentity(src, dst)
2116 void PF_copyentity (void)
2119 in = G_EDICT(OFS_PARM0);
2120 if (in == sv.edicts)
2121 PF_WARNING("copyentity: can not read world entity\n");
2123 PF_WARNING("copyentity: can not read free entity\n");
2124 out = G_EDICT(OFS_PARM1);
2125 if (out == sv.edicts)
2126 PF_WARNING("copyentity: can not modify world entity\n");
2128 PF_WARNING("copyentity: can not modify free entity\n");
2129 memcpy(out->v, in->v, progs->entityfields * 4);
2136 sets the color of a client and broadcasts the update to all connected clients
2138 setcolor(clientent, value)
2141 void PF_setcolor (void)
2147 entnum = G_EDICTNUM(OFS_PARM0);
2148 i = G_FLOAT(OFS_PARM1);
2150 if (entnum < 1 || entnum > svs.maxclients || !svs.clients[entnum-1].active)
2152 Con_Printf ("tried to setcolor a non-client\n");
2156 client = svs.clients + entnum-1;
2157 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2160 client->old_colors = i;
2161 client->edict->v->team = (i & 15) + 1;
2163 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2164 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2165 MSG_WriteByte (&sv.reliable_datagram, i);
2172 effect(origin, modelname, startframe, framecount, framerate)
2175 void PF_effect (void)
2178 s = G_STRING(OFS_PARM1);
2180 PF_WARNING("effect: no model specified\n");
2182 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2185 void PF_te_blood (void)
2187 if (G_FLOAT(OFS_PARM2) < 1)
2189 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2190 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2192 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2193 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2194 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2196 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2197 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2198 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2200 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2203 void PF_te_bloodshower (void)
2205 if (G_FLOAT(OFS_PARM3) < 1)
2207 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2208 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2210 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2211 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2212 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2214 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2215 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2216 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2218 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2220 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2223 void PF_te_explosionrgb (void)
2225 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2226 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2228 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2229 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2230 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2232 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2233 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2234 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2237 void PF_te_particlecube (void)
2239 if (G_FLOAT(OFS_PARM3) < 1)
2241 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2242 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2244 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2245 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2246 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2248 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2249 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2250 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2252 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2253 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2254 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2256 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2258 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2259 // gravity true/false
2260 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2262 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2265 void PF_te_particlerain (void)
2267 if (G_FLOAT(OFS_PARM3) < 1)
2269 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2270 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2272 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2273 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2274 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2276 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2277 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2278 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2280 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2284 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2286 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2289 void PF_te_particlesnow (void)
2291 if (G_FLOAT(OFS_PARM3) < 1)
2293 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2294 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2296 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2297 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2298 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2300 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2301 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2304 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2305 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2306 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2308 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2310 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2313 void PF_te_spark (void)
2315 if (G_FLOAT(OFS_PARM2) < 1)
2317 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2318 MSG_WriteByte(&sv.datagram, TE_SPARK);
2320 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2321 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2322 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2324 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2325 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2326 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2328 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2331 void PF_te_gunshotquad (void)
2333 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2334 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2336 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2337 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2338 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2341 void PF_te_spikequad (void)
2343 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2344 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2346 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2347 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2348 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2351 void PF_te_superspikequad (void)
2353 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2354 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2356 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2357 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2358 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2361 void PF_te_explosionquad (void)
2363 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2364 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2366 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2367 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2368 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2371 void PF_te_smallflash (void)
2373 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2374 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2376 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2377 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2378 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2381 void PF_te_customflash (void)
2383 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2385 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2386 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2388 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2389 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2390 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2392 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2394 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2396 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2397 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2398 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2401 void PF_te_gunshot (void)
2403 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2404 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2406 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2407 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2408 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2411 void PF_te_spike (void)
2413 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2414 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2416 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2417 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2418 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2421 void PF_te_superspike (void)
2423 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2424 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2426 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2427 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2428 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2431 void PF_te_explosion (void)
2433 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2434 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2436 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2437 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2438 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2441 void PF_te_tarexplosion (void)
2443 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2444 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2446 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2447 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2448 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2451 void PF_te_wizspike (void)
2453 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2454 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2456 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2457 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2458 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2461 void PF_te_knightspike (void)
2463 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2464 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2466 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2467 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2468 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2471 void PF_te_lavasplash (void)
2473 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2474 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2476 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2477 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2478 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2481 void PF_te_teleport (void)
2483 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2484 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2486 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2487 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2488 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2491 void PF_te_explosion2 (void)
2493 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2494 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2496 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2497 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2498 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2500 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2503 void PF_te_lightning1 (void)
2505 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2506 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2508 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2510 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2511 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2512 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2514 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2515 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2519 void PF_te_lightning2 (void)
2521 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2522 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2524 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2526 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2527 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2528 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2530 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2531 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2532 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2535 void PF_te_lightning3 (void)
2537 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2538 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2540 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2542 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2543 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2544 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2546 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2547 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2548 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2551 void PF_te_beam (void)
2553 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2554 MSG_WriteByte(&sv.datagram, TE_BEAM);
2556 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2558 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2559 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2560 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2562 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2563 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2564 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2567 void PF_te_plasmaburn (void)
2569 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2570 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2571 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2572 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2573 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2576 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2579 vec3_t v1, clipplanenormal, normal;
2580 vec_t clipplanedist, clipdist;
2582 if (surf->flags & SURF_PLANEBACK)
2583 VectorNegate(surf->plane->normal, normal);
2585 VectorCopy(surf->plane->normal, normal);
2586 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2588 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2589 VectorNormalizeFast(v1);
2590 CrossProduct(v1, normal, clipplanenormal);
2591 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2592 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2595 clipdist = -clipdist;
2596 VectorMA(out, clipdist, clipplanenormal, out);
2601 static msurface_t *getsurface(edict_t *ed, int surfnum)
2605 if (!ed || ed->e->free)
2607 modelindex = ed->v->modelindex;
2608 if (modelindex < 1 || modelindex >= MAX_MODELS)
2610 model = sv.models[modelindex];
2611 if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
2613 return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2617 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2618 void PF_getsurfacenumpoints(void)
2621 // return 0 if no such surface
2622 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2624 G_FLOAT(OFS_RETURN) = 0;
2628 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2630 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2631 void PF_getsurfacepoint(void)
2636 VectorClear(G_VECTOR(OFS_RETURN));
2637 ed = G_EDICT(OFS_PARM0);
2638 if (!ed || ed->e->free)
2640 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2642 pointnum = G_FLOAT(OFS_PARM2);
2643 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2645 // FIXME: implement rotation/scaling
2646 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2648 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2649 void PF_getsurfacenormal(void)
2652 VectorClear(G_VECTOR(OFS_RETURN));
2653 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2655 // FIXME: implement rotation/scaling
2656 if (surf->flags & SURF_PLANEBACK)
2657 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2659 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2661 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2662 void PF_getsurfacetexture(void)
2665 G_INT(OFS_RETURN) = 0;
2666 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2668 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2670 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2671 void PF_getsurfacenearpoint(void)
2673 int surfnum, best, modelindex;
2675 vec_t dist, bestdist;
2680 G_FLOAT(OFS_RETURN) = -1;
2681 ed = G_EDICT(OFS_PARM0);
2682 point = G_VECTOR(OFS_PARM1);
2684 if (!ed || ed->e->free)
2686 modelindex = ed->v->modelindex;
2687 if (modelindex < 1 || modelindex >= MAX_MODELS)
2689 model = sv.models[modelindex];
2690 if (!model->brushq1.numsurfaces)
2693 // FIXME: implement rotation/scaling
2694 VectorSubtract(point, ed->v->origin, p);
2696 bestdist = 1000000000;
2697 for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++)
2699 surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2700 dist = PlaneDiff(p, surf->plane);
2702 if (dist < bestdist)
2704 clippointtosurface(surf, p, clipped);
2705 VectorSubtract(clipped, p, clipped);
2706 dist += DotProduct(clipped, clipped);
2707 if (dist < bestdist)
2714 G_FLOAT(OFS_RETURN) = best;
2716 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2717 void PF_getsurfaceclippedpoint(void)
2722 VectorClear(G_VECTOR(OFS_RETURN));
2723 ed = G_EDICT(OFS_PARM0);
2724 if (!ed || ed->e->free)
2726 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2728 // FIXME: implement rotation/scaling
2729 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2730 clippointtosurface(surf, p, out);
2731 // FIXME: implement rotation/scaling
2732 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2735 #define MAX_PRFILES 256
2737 qfile_t *pr_files[MAX_PRFILES];
2739 void PR_Files_Init(void)
2741 memset(pr_files, 0, sizeof(pr_files));
2744 void PR_Files_CloseAll(void)
2747 for (i = 0;i < MAX_PRFILES;i++)
2750 FS_Close(pr_files[i]);
2755 //float(string s) stof = #81; // get numerical value from a string
2758 char string[STRINGTEMP_LENGTH];
2759 PF_VarString(0, string, sizeof(string));
2760 G_FLOAT(OFS_RETURN) = atof(string);
2763 //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
2767 char *modestring, *filename;
2768 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2769 if (pr_files[filenum] == NULL)
2771 if (filenum >= MAX_PRFILES)
2773 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2774 G_FLOAT(OFS_RETURN) = -2;
2777 mode = G_FLOAT(OFS_PARM1);
2780 case 0: // FILE_READ
2783 case 1: // FILE_APPEND
2786 case 2: // FILE_WRITE
2790 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2791 G_FLOAT(OFS_RETURN) = -3;
2794 filename = G_STRING(OFS_PARM0);
2795 // .. is parent directory on many platforms
2796 // / is parent directory on Amiga
2797 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2798 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2799 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2801 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2802 G_FLOAT(OFS_RETURN) = -4;
2805 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2806 if (pr_files[filenum] == NULL)
2807 G_FLOAT(OFS_RETURN) = -1;
2809 G_FLOAT(OFS_RETURN) = filenum;
2812 //void(float fhandle) fclose = #111; // closes a file
2813 void PF_fclose(void)
2815 int filenum = G_FLOAT(OFS_PARM0);
2816 if (filenum < 0 || filenum >= MAX_PRFILES)
2818 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2821 if (pr_files[filenum] == NULL)
2823 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2826 FS_Close(pr_files[filenum]);
2827 pr_files[filenum] = NULL;
2830 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2834 static char string[STRINGTEMP_LENGTH];
2835 int filenum = G_FLOAT(OFS_PARM0);
2836 if (filenum < 0 || filenum >= MAX_PRFILES)
2838 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2841 if (pr_files[filenum] == NULL)
2843 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2849 c = FS_Getc(pr_files[filenum]);
2850 if (c == '\r' || c == '\n' || c < 0)
2852 if (end < STRINGTEMP_LENGTH - 1)
2856 // remove \n following \r
2858 c = FS_Getc(pr_files[filenum]);
2859 if (developer.integer)
2860 Con_Printf("fgets: %s\n", string);
2862 G_INT(OFS_RETURN) = PR_SetString(string);
2864 G_INT(OFS_RETURN) = 0;
2867 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2871 char string[STRINGTEMP_LENGTH];
2872 int filenum = G_FLOAT(OFS_PARM0);
2873 if (filenum < 0 || filenum >= MAX_PRFILES)
2875 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2878 if (pr_files[filenum] == NULL)
2880 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2883 PF_VarString(1, string, sizeof(string));
2884 if ((stringlength = strlen(string)))
2885 FS_Write(pr_files[filenum], string, stringlength);
2886 if (developer.integer)
2887 Con_Printf("fputs: %s\n", string);
2890 //float(string s) strlen = #114; // returns how many characters are in a string
2891 void PF_strlen(void)
2894 s = G_STRING(OFS_PARM0);
2896 G_FLOAT(OFS_RETURN) = strlen(s);
2898 G_FLOAT(OFS_RETURN) = 0;
2901 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2902 void PF_strcat(void)
2904 char *s = PR_GetTempString();
2905 PF_VarString(0, s, STRINGTEMP_LENGTH);
2906 G_INT(OFS_RETURN) = PR_SetString(s);
2909 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2910 void PF_substring(void)
2912 int i, start, length;
2913 char *s, *string = PR_GetTempString();
2914 s = G_STRING(OFS_PARM0);
2915 start = G_FLOAT(OFS_PARM1);
2916 length = G_FLOAT(OFS_PARM2);
2919 for (i = 0;i < start && *s;i++, s++);
2920 for (i = 0;i < STRINGTEMP_LENGTH - 1 && *s && i < length;i++, s++)
2923 G_INT(OFS_RETURN) = PR_SetString(string);
2926 //vector(string s) stov = #117; // returns vector value from a string
2929 char string[STRINGTEMP_LENGTH];
2930 PF_VarString(0, string, sizeof(string));
2931 Math_atov(string, G_VECTOR(OFS_RETURN));
2934 //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)
2935 void PF_strzone(void)
2938 in = G_STRING(OFS_PARM0);
2939 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2941 G_INT(OFS_RETURN) = PR_SetString(out);
2944 //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!!!)
2945 void PF_strunzone(void)
2947 Mem_Free(G_STRING(OFS_PARM0));
2950 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2951 //this function originally written by KrimZon, made shorter by LordHavoc
2952 void PF_clientcommand (void)
2954 client_t *temp_client;
2957 //find client for this entity
2958 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2959 if (i < 0 || i >= svs.maxclients || !svs.clients[i].active)
2961 Con_Printf("PF_clientcommand: entity is not a client");
2965 temp_client = host_client;
2966 host_client = svs.clients + i;
2967 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2968 host_client = temp_client;
2971 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2972 //this function originally written by KrimZon, made shorter by LordHavoc
2973 //20040203: rewritten by LordHavoc (no longer uses allocations)
2975 char *tokens[256], tokenbuf[4096];
2976 void PF_tokenize (void)
2980 p = G_STRING(OFS_PARM0);
2984 while(COM_ParseToken(&p, false))
2986 if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
2988 if (pos + strlen(com_token) + 1 > sizeof(tokenbuf))
2990 tokens[num_tokens++] = tokenbuf + pos;
2991 strcpy(tokenbuf + pos, com_token);
2992 pos += strlen(com_token) + 1;
2995 G_FLOAT(OFS_RETURN) = num_tokens;
2998 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
2999 //this function originally written by KrimZon, made shorter by LordHavoc
3002 int token_num = G_FLOAT(OFS_PARM0);
3003 if (token_num >= 0 && token_num < num_tokens)
3004 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
3006 G_INT(OFS_RETURN) = PR_SetString("");
3009 //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)
3010 void PF_setattachment (void)
3012 edict_t *e = G_EDICT(OFS_PARM0);
3013 edict_t *tagentity = G_EDICT(OFS_PARM1);
3014 char *tagname = G_STRING(OFS_PARM2);
3020 PF_WARNING("setattachment: can not modify world entity\n");
3022 PF_WARNING("setattachment: can not modify free entity\n");
3024 if (tagentity == NULL)
3025 tagentity = sv.edicts;
3027 v = GETEDICTFIELDVALUE(e, eval_tag_entity);
3029 v->edict = EDICT_TO_PROG(tagentity);
3031 v = GETEDICTFIELDVALUE(e, eval_tag_index);
3034 if (tagentity != NULL && tagentity != sv.edicts && tagname && tagname[0])
3036 modelindex = (int)tagentity->v->modelindex;
3037 if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
3039 if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames)
3040 for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++)
3041 if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name))
3043 if (v->_float == 0 && model->alias.aliasnum_tags)
3044 for (i = 0;i < model->alias.aliasnum_tags;i++)
3045 if (!strcmp(tagname, model->alias.aliasdata_tags[i].name))
3048 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name);
3051 Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i but it has no model\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity));
3056 /////////////////////////////////////////
3057 // DP_QC_FS_SEARCH extension
3059 // qc fs search handling
3060 #define MAX_SEARCHES 128
3062 fssearch_t *pr_fssearchlist[MAX_SEARCHES];
3064 void PR_Search_Init(void)
3066 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3069 void PR_Search_Reset(void)
3072 // reset the fssearch list
3073 for(i = 0; i < MAX_SEARCHES; i++)
3074 if(pr_fssearchlist[i])
3075 FS_FreeSearch(pr_fssearchlist[i]);
3076 memset(pr_fssearchlist,0,sizeof(pr_fssearchlist));
3083 float search_begin(string pattern, float caseinsensitive, float quiet)
3086 void PF_search_begin(void)
3090 int caseinsens, quiet;
3092 pattern = G_STRING(OFS_PARM0);
3094 PR_CheckEmptyString(pattern);
3096 caseinsens = G_FLOAT(OFS_PARM1);
3097 quiet = G_FLOAT(OFS_PARM2);
3099 for(handle = 0; handle < MAX_SEARCHES; handle++)
3100 if(!pr_fssearchlist[handle])
3103 if(handle >= MAX_SEARCHES)
3105 Con_Printf("PR_search_begin: ran out of search handles (%i)\n", MAX_SEARCHES);
3106 G_FLOAT(OFS_RETURN) = -2;
3110 if(!(pr_fssearchlist[handle] = FS_Search(pattern,caseinsens, quiet)))
3111 G_FLOAT(OFS_RETURN) = -1;
3113 G_FLOAT(OFS_RETURN) = handle;
3120 void search_end(float handle)
3123 void PF_search_end(void)
3127 handle = G_FLOAT(OFS_PARM0);
3129 if(handle < 0 || handle >= MAX_SEARCHES)
3131 Con_Printf("PF_search_end: invalid handle %i\n", handle);
3134 if(pr_fssearchlist[handle] == NULL)
3136 Con_Printf("PF_search_end: no such handle %i\n", handle);
3140 FS_FreeSearch(pr_fssearchlist[handle]);
3141 pr_fssearchlist[handle] = NULL;
3148 float search_getsize(float handle)
3151 void PF_search_getsize(void)
3155 handle = G_FLOAT(OFS_PARM0);
3157 if(handle < 0 || handle >= MAX_SEARCHES)
3159 Con_Printf("PF_search_getsize: invalid handle %i\n", handle);
3162 if(pr_fssearchlist[handle] == NULL)
3164 Con_Printf("PF_search_getsize: no such handle %i\n", handle);
3168 G_FLOAT(OFS_RETURN) = pr_fssearchlist[handle]->numfilenames;
3173 VM_search_getfilename
3175 string search_getfilename(float handle, float num)
3178 void PF_search_getfilename(void)
3180 int handle, filenum;
3183 handle = G_FLOAT(OFS_PARM0);
3184 filenum = G_FLOAT(OFS_PARM1);
3186 if(handle < 0 || handle >= MAX_SEARCHES)
3188 Con_Printf("PF_search_getfilename: invalid handle %i\n", handle);
3191 if(pr_fssearchlist[handle] == NULL)
3193 Con_Printf("PF_search_getfilename: no such handle %i\n", handle);
3196 if(filenum < 0 || filenum >= pr_fssearchlist[handle]->numfilenames)
3198 Con_Printf("PF_search_getfilename: invalid filenum %i\n", filenum);
3202 tmp = PR_GetTempString();
3203 strcpy(tmp, pr_fssearchlist[handle]->filenames[filenum]);
3205 G_INT(OFS_RETURN) = PR_SetString(tmp);
3208 void PF_cvar_string (void)
3214 str = G_STRING(OFS_PARM0);
3215 var = Cvar_FindVar (str);
3217 tmp = PR_GetTempString();
3218 strcpy(tmp, var->string);
3220 G_INT(OFS_RETURN) = PR_SetString(tmp);
3225 builtin_t pr_builtin[] =
3228 PF_makevectors, // #1 void(entity e) makevectors
3229 PF_setorigin, // #2 void(entity e, vector o) setorigin
3230 PF_setmodel, // #3 void(entity e, string m) setmodel
3231 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
3232 NULL, // #5 void(entity e, vector min, vector max) setabssize
3233 PF_break, // #6 void() break
3234 PF_random, // #7 float() random
3235 PF_sound, // #8 void(entity e, float chan, string samp) sound
3236 PF_normalize, // #9 vector(vector v) normalize
3237 PF_error, // #10 void(string e) error
3238 PF_objerror, // #11 void(string e) objerror
3239 PF_vlen, // #12 float(vector v) vlen
3240 PF_vectoyaw, // #13 float(vector v) vectoyaw
3241 PF_Spawn, // #14 entity() spawn
3242 PF_Remove, // #15 void(entity e) remove
3243 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
3244 PF_checkclient, // #17 entity() clientlist
3245 PF_Find, // #18 entity(entity start, .string fld, string match) find
3246 PF_precache_sound, // #19 void(string s) precache_sound
3247 PF_precache_model, // #20 void(string s) precache_model
3248 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
3249 PF_findradius, // #22 entity(vector org, float rad) findradius
3250 PF_bprint, // #23 void(string s) bprint
3251 PF_sprint, // #24 void(entity client, string s) sprint
3252 PF_dprint, // #25 void(string s) dprint
3253 PF_ftos, // #26 void(string s) ftos
3254 PF_vtos, // #27 void(string s) vtos
3255 PF_coredump, // #28 void() coredump
3256 PF_traceon, // #29 void() traceon
3257 PF_traceoff, // #30 void() traceoff
3258 PF_eprint, // #31 void(entity e) eprint
3259 PF_walkmove, // #32 float(float yaw, float dist) walkmove
3261 PF_droptofloor, // #34 float() droptofloor
3262 PF_lightstyle, // #35 void(float style, string value) lightstyle
3263 PF_rint, // #36 float(float v) rint
3264 PF_floor, // #37 float(float v) floor
3265 PF_ceil, // #38 float(float v) ceil
3267 PF_checkbottom, // #40 float(entity e) checkbottom
3268 PF_pointcontents , // #41 float(vector v) pointcontents
3270 PF_fabs, // #43 float(float f) fabs
3271 PF_aim, // #44 vector(entity e, float speed) aim
3272 PF_cvar, // #45 float(string s) cvar
3273 PF_localcmd, // #46 void(string s) localcmd
3274 PF_nextent, // #47 entity(entity e) nextent
3275 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3276 PF_changeyaw, // #49 void() ChangeYaw
3278 PF_vectoangles, // #51 vector(vector v) vectoangles
3279 PF_WriteByte, // #52 void(float to, float f) WriteByte
3280 PF_WriteChar, // #53 void(float to, float f) WriteChar
3281 PF_WriteShort, // #54 void(float to, float f) WriteShort
3282 PF_WriteLong, // #55 void(float to, float f) WriteLong
3283 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3284 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3285 PF_WriteString, // #58 void(float to, string s) WriteString
3286 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3287 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3288 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3289 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3290 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3291 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3292 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3294 SV_MoveToGoal, // #67 void(float step) movetogoal
3295 PF_precache_file, // #68 string(string s) precache_file
3296 PF_makestatic, // #69 void(entity e) makestatic
3297 PF_changelevel, // #70 void(string s) changelevel
3299 PF_cvar_set, // #72 void(string var, string val) cvar_set
3300 PF_centerprint, // #73 void(entity client, strings) centerprint
3301 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3302 PF_precache_model, // #75 string(string s) precache_model2
3303 PF_precache_sound, // #76 string(string s) precache_sound2
3304 PF_precache_file, // #77 string(string s) precache_file2
3305 PF_setspawnparms, // #78 void(entity e) setspawnparms
3308 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3317 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3318 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3319 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3320 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3321 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3322 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3323 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3324 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3325 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3326 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3337 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3338 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3339 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3340 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3341 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3342 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3343 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3344 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3345 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3346 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3347 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3348 a a a a a a a a // #120-199
3349 a a a a a a a a a a // #200-299
3350 a a a a a a a a a a // #300-399
3351 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3352 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3353 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3354 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3355 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3356 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3357 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3358 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3359 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3360 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3361 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3362 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3363 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3364 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3365 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3366 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3367 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3368 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3369 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3370 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3371 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3372 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3373 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3374 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3375 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3376 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3377 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3378 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3379 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3380 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3381 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3382 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3383 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3384 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3385 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3386 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3387 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3388 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3389 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3390 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3391 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3392 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3393 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3394 PF_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
3395 PF_search_begin, // #444
3396 PF_search_end, // #445
3397 PF_search_getsize, // #446
3398 PF_search_getfilename, // #447
3399 PF_cvar_string, // #448 string(string s) cvar_string (DP_QC_CVAR_STRING)
3401 a a a a a // #450-499 (LordHavoc)
3404 builtin_t *pr_builtins = pr_builtin;
3405 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3407 void PR_Cmd_Init(void)
3409 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3414 void PR_Cmd_Reset(void)
3416 Mem_EmptyPool(pr_strings_mempool);
3418 PR_Files_CloseAll();