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 #define MAX_VARSTRING 4096
30 char pr_varstring_temp[MAX_VARSTRING];
32 #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
36 ===============================================================================
40 ===============================================================================
44 char *PF_VarString (int first)
50 out = pr_varstring_temp;
51 outend = pr_varstring_temp + sizeof(pr_varstring_temp) - 1;
52 for (i = first;i < pr_argc && out < outend;i++)
54 s = G_STRING((OFS_PARM0+i*3));
55 while (out < outend && *s)
59 return pr_varstring_temp;
62 char *ENGINE_EXTENSIONS =
72 "DP_ENT_CUSTOMCOLORMAP "
73 "DP_ENT_EXTERIORMODELTOCLIENT "
74 "DP_ENT_LOWPRECISION "
80 "DP_GFX_EXTERNALTEXTURES "
82 "DP_HALFLIFE_MAP_CVAR "
85 "DP_MOVETYPEBOUNCEMISSILE "
91 "DP_QC_FINDCHAINFLOAT "
97 "DP_QC_SINCOSSQRTPOW "
100 "DP_QC_VECTORVECTORS "
106 "DP_SV_DRAWONLYTOCLIENT "
108 "DP_SV_EXTERIORMODELTOCLIENT "
109 "DP_SV_NODRAWTOCLIENT "
110 "DP_SV_PLAYERPHYSICS "
116 "DP_TE_EXPLOSIONRGB "
118 "DP_TE_PARTICLECUBE "
119 "DP_TE_PARTICLERAIN "
120 "DP_TE_PARTICLESNOW "
122 "DP_TE_QUADEFFECTS1 "
125 "DP_TE_STANDARDEFFECTBUILTINS "
128 "KRIMZON_SV_PARSECLIENTCOMMAND "
134 qboolean checkextension(char *name)
139 for (e = ENGINE_EXTENSIONS;*e;e++)
146 while (*e && *e != ' ')
148 if (e - start == len)
149 if (!strncasecmp(start, name, len))
159 returns true if the extension is supported by the server
161 checkextension(extensionname)
164 void PF_checkextension (void)
166 G_FLOAT(OFS_RETURN) = checkextension(G_STRING(OFS_PARM0));
173 This is a TERMINAL error, which will kill off the entire server.
185 Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
186 ed = PROG_TO_EDICT(pr_global_struct->self);
189 Host_Error ("Program error");
196 Dumps out self, then an error message. The program is aborted and self is
197 removed, but the level can continue.
202 void PF_objerror (void)
208 Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name), s);
209 ed = PROG_TO_EDICT(pr_global_struct->self);
219 Writes new values for v_forward, v_up, and v_right based on angles
223 void PF_makevectors (void)
225 AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
232 Writes new values for v_forward, v_up, and v_right based on the given forward vector
233 vectorvectors(vector, vector)
236 void PF_vectorvectors (void)
238 VectorNormalize2(G_VECTOR(OFS_PARM0), pr_global_struct->v_forward);
239 VectorVectors(pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
246 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.
248 setorigin (entity, origin)
251 void PF_setorigin (void)
256 e = G_EDICT(OFS_PARM0);
257 org = G_VECTOR(OFS_PARM1);
258 VectorCopy (org, e->v->origin);
259 SV_LinkEdict (e, false);
263 void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
267 for (i=0 ; i<3 ; i++)
269 Host_Error ("backwards mins/maxs");
271 // set derived values
272 VectorCopy (min, e->v->mins);
273 VectorCopy (max, e->v->maxs);
274 VectorSubtract (max, min, e->v->size);
276 SV_LinkEdict (e, false);
283 the size box is rotated by the current angle
284 LordHavoc: no it isn't...
286 setsize (entity, minvector, maxvector)
289 void PF_setsize (void)
294 e = G_EDICT(OFS_PARM0);
295 min = G_VECTOR(OFS_PARM1);
296 max = G_VECTOR(OFS_PARM2);
297 SetMinMaxSize (e, min, max, false);
305 setmodel(entity, model)
308 void PF_setmodel (void)
315 e = G_EDICT(OFS_PARM0);
316 m = G_STRING(OFS_PARM1);
318 // check to see if model was properly precached
319 for (i=0, check = sv.model_precache ; *check ; i++, check++)
320 if (!strcmp(*check, m))
324 Host_Error ("no precache: %s\n", m);
327 e->v->model = PR_SetString(*check);
328 e->v->modelindex = i;
330 mod = sv.models[ (int)e->v->modelindex];
333 SetMinMaxSize (e, mod->normalmins, mod->normalmaxs, true);
335 SetMinMaxSize (e, vec3_origin, vec3_origin, true);
342 broadcast print to everyone on server
347 void PF_bprint (void)
352 SV_BroadcastPrintf ("%s", s);
359 single print to a specific client
361 sprint(clientent, value)
364 void PF_sprint (void)
370 entnum = G_EDICTNUM(OFS_PARM0);
373 if (entnum < 1 || entnum > svs.maxclients)
375 Con_Printf ("tried to sprint to a non-client\n");
379 client = &svs.clients[entnum-1];
381 MSG_WriteChar (&client->message,svc_print);
382 MSG_WriteString (&client->message, s );
390 single print to a specific client
392 centerprint(clientent, value)
395 void PF_centerprint (void)
401 entnum = G_EDICTNUM(OFS_PARM0);
404 if (entnum < 1 || entnum > svs.maxclients)
406 Con_Printf ("tried to sprint to a non-client\n");
410 client = &svs.clients[entnum-1];
412 MSG_WriteChar (&client->message,svc_centerprint);
413 MSG_WriteString (&client->message, s );
421 vector normalize(vector)
424 void PF_normalize (void)
430 value1 = G_VECTOR(OFS_PARM0);
432 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
436 newvalue[0] = newvalue[1] = newvalue[2] = 0;
440 newvalue[0] = value1[0] * new;
441 newvalue[1] = value1[1] * new;
442 newvalue[2] = value1[2] * new;
445 VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
460 value1 = G_VECTOR(OFS_PARM0);
462 new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
465 G_FLOAT(OFS_RETURN) = new;
472 float vectoyaw(vector)
475 void PF_vectoyaw (void)
480 value1 = G_VECTOR(OFS_PARM0);
482 if (value1[1] == 0 && value1[0] == 0)
486 yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
491 G_FLOAT(OFS_RETURN) = yaw;
499 vector vectoangles(vector)
502 void PF_vectoangles (void)
508 value1 = G_VECTOR(OFS_PARM0);
510 if (value1[1] == 0 && value1[0] == 0)
520 // LordHavoc: optimized a bit
523 yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
527 else if (value1[1] > 0)
532 forward = sqrt(value1[0]*value1[0] + value1[1]*value1[1]);
533 pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
538 G_FLOAT(OFS_RETURN+0) = pitch;
539 G_FLOAT(OFS_RETURN+1) = yaw;
540 G_FLOAT(OFS_RETURN+2) = 0;
547 Returns a number from 0<= num < 1
552 void PF_random (void)
556 num = (rand ()&0x7fff) / ((float)0x7fff);
558 G_FLOAT(OFS_RETURN) = num;
565 particle(origin, color, count)
568 void PF_particle (void)
574 org = G_VECTOR(OFS_PARM0);
575 dir = G_VECTOR(OFS_PARM1);
576 color = G_FLOAT(OFS_PARM2);
577 count = G_FLOAT(OFS_PARM3);
578 SV_StartParticle (org, dir, color, count);
588 void PF_ambientsound (void)
593 float vol, attenuation;
594 int i, soundnum, large;
596 pos = G_VECTOR (OFS_PARM0);
597 samp = G_STRING(OFS_PARM1);
598 vol = G_FLOAT(OFS_PARM2);
599 attenuation = G_FLOAT(OFS_PARM3);
601 // check to see if samp was properly precached
602 for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
603 if (!strcmp(*check,samp))
608 Con_Printf ("no precache: %s\n", samp);
616 // add an svc_spawnambient command to the level signon packet
619 MSG_WriteByte (&sv.signon, svc_spawnstaticsound2);
621 MSG_WriteByte (&sv.signon, svc_spawnstaticsound);
623 for (i=0 ; i<3 ; i++)
624 MSG_WriteDPCoord(&sv.signon, pos[i]);
627 MSG_WriteShort (&sv.signon, soundnum);
629 MSG_WriteByte (&sv.signon, soundnum);
631 MSG_WriteByte (&sv.signon, vol*255);
632 MSG_WriteByte (&sv.signon, attenuation*64);
640 Each entity can have eight independant sound sources, like voice,
643 Channel 0 is an auto-allocate channel, the others override anything
644 already running on that entity/channel pair.
646 An attenuation of 0 will play full volume everywhere in the level.
647 Larger attenuations will drop off.
659 entity = G_EDICT(OFS_PARM0);
660 channel = G_FLOAT(OFS_PARM1);
661 sample = G_STRING(OFS_PARM2);
662 volume = G_FLOAT(OFS_PARM3) * 255;
663 attenuation = G_FLOAT(OFS_PARM4);
665 if (volume < 0 || volume > 255)
666 Host_Error ("SV_StartSound: volume = %i", volume);
668 if (attenuation < 0 || attenuation > 4)
669 Host_Error ("SV_StartSound: attenuation = %f", attenuation);
671 if (channel < 0 || channel > 7)
672 Host_Error ("SV_StartSound: channel = %i", channel);
674 SV_StartSound (entity, channel, sample, volume, attenuation);
686 Host_Error ("break statement");
693 Used for use tracing and shot targeting
694 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
695 if the tryents flag is set.
697 traceline (vector1, vector2, tryents)
700 void PF_traceline (void)
707 pr_xfunction->builtinsprofile += 30;
709 v1 = G_VECTOR(OFS_PARM0);
710 v2 = G_VECTOR(OFS_PARM1);
711 nomonsters = G_FLOAT(OFS_PARM2);
712 ent = G_EDICT(OFS_PARM3);
714 trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
716 pr_global_struct->trace_allsolid = trace.allsolid;
717 pr_global_struct->trace_startsolid = trace.startsolid;
718 pr_global_struct->trace_fraction = trace.fraction;
719 pr_global_struct->trace_inwater = trace.inwater;
720 pr_global_struct->trace_inopen = trace.inopen;
721 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
722 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
723 pr_global_struct->trace_plane_dist = trace.plane.dist;
725 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
727 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
728 // FIXME: add trace_endcontents
736 Used for use tracing and shot targeting
737 Traces are blocked by bbox and exact bsp entityes, and also slide box entities
738 if the tryents flag is set.
740 tracebox (vector1, vector mins, vector maxs, vector2, tryents)
743 // LordHavoc: added this for my own use, VERY useful, similar to traceline
744 void PF_tracebox (void)
746 float *v1, *v2, *m1, *m2;
751 pr_xfunction->builtinsprofile += 30;
753 v1 = G_VECTOR(OFS_PARM0);
754 m1 = G_VECTOR(OFS_PARM1);
755 m2 = G_VECTOR(OFS_PARM2);
756 v2 = G_VECTOR(OFS_PARM3);
757 nomonsters = G_FLOAT(OFS_PARM4);
758 ent = G_EDICT(OFS_PARM5);
760 trace = SV_Move (v1, m1, m2, v2, nomonsters ? MOVE_NOMONSTERS : MOVE_NORMAL, ent);
762 pr_global_struct->trace_allsolid = trace.allsolid;
763 pr_global_struct->trace_startsolid = trace.startsolid;
764 pr_global_struct->trace_fraction = trace.fraction;
765 pr_global_struct->trace_inwater = trace.inwater;
766 pr_global_struct->trace_inopen = trace.inopen;
767 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
768 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
769 pr_global_struct->trace_plane_dist = trace.plane.dist;
771 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
773 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
776 extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore);
777 void PF_TraceToss (void)
783 pr_xfunction->builtinsprofile += 600;
785 ent = G_EDICT(OFS_PARM0);
786 ignore = G_EDICT(OFS_PARM1);
788 trace = SV_Trace_Toss (ent, ignore);
790 pr_global_struct->trace_allsolid = trace.allsolid;
791 pr_global_struct->trace_startsolid = trace.startsolid;
792 pr_global_struct->trace_fraction = trace.fraction;
793 pr_global_struct->trace_inwater = trace.inwater;
794 pr_global_struct->trace_inopen = trace.inopen;
795 VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
796 VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
797 pr_global_struct->trace_plane_dist = trace.plane.dist;
799 pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
801 pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
809 Returns true if the given entity can move to the given position from it's
810 current position by walking or rolling.
812 scalar checkpos (entity, vector)
815 void PF_checkpos (void)
819 //============================================================================
821 qbyte checkpvs[MAX_MAP_LEAFS/8];
823 int PF_newcheckclient (int check)
829 // cycle to the next one
833 if (check > svs.maxclients)
834 check = svs.maxclients;
836 if (check == svs.maxclients)
843 pr_xfunction->builtinsprofile++;
844 if (i == svs.maxclients+1)
850 break; // didn't find anything else
854 if (ent->v->health <= 0)
856 if ((int)ent->v->flags & FL_NOTARGET)
859 // anything that is a client, or has a client as an enemy
863 // get the PVS for the entity
864 VectorAdd (ent->v->origin, ent->v->view_ofs, org);
865 memcpy (checkpvs, sv.worldmodel->brushq1.LeafPVS(sv.worldmodel, sv.worldmodel->brushq1.PointInLeaf(sv.worldmodel, org)), (sv.worldmodel->brushq1.numleafs+7)>>3 );
874 Returns a client (or object that has a client enemy) that would be a
877 If there is more than one valid option, they are cycled each frame
879 If (self.origin + self.viewofs) is not in the PVS of the current target,
880 it is not returned at all.
885 int c_invis, c_notvis;
886 void PF_checkclient (void)
893 // find a new check if on a new frame
894 if (sv.time - sv.lastchecktime >= 0.1)
896 sv.lastcheck = PF_newcheckclient (sv.lastcheck);
897 sv.lastchecktime = sv.time;
900 // return check if it might be visible
901 ent = EDICT_NUM(sv.lastcheck);
902 if (ent->e->free || ent->v->health <= 0)
904 RETURN_EDICT(sv.edicts);
908 // if current entity can't possibly see the check entity, return 0
909 self = PROG_TO_EDICT(pr_global_struct->self);
910 VectorAdd (self->v->origin, self->v->view_ofs, view);
911 leaf = sv.worldmodel->brushq1.PointInLeaf(sv.worldmodel, view);
914 l = (leaf - sv.worldmodel->brushq1.leafs) - 1;
915 if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
918 RETURN_EDICT(sv.edicts);
923 // might be able to see it
928 //============================================================================
935 Sends text over to the client's execution buffer
937 stuffcmd (clientent, value)
940 void PF_stuffcmd (void)
946 entnum = G_EDICTNUM(OFS_PARM0);
947 if (entnum < 1 || entnum > svs.maxclients)
948 Host_Error ("Parm 0 not a client");
949 str = G_STRING(OFS_PARM1);
952 host_client = &svs.clients[entnum-1];
953 Host_ClientCommands ("%s", str);
961 Sends text over to the client's execution buffer
966 void PF_localcmd (void)
970 str = G_STRING(OFS_PARM0);
985 str = G_STRING(OFS_PARM0);
987 G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
997 void PF_cvar_set (void)
1001 var = G_STRING(OFS_PARM0);
1002 val = G_STRING(OFS_PARM1);
1004 Cvar_Set (var, val);
1011 Returns a chain of entities that have origins within a spherical area
1013 findradius (origin, radius)
1016 void PF_findradius (void)
1018 edict_t *ent, *chain;
1025 chain = (edict_t *)sv.edicts;
1027 org = G_VECTOR(OFS_PARM0);
1028 radius = G_FLOAT(OFS_PARM1);
1029 radius2 = radius * radius;
1031 ent = NEXT_EDICT(sv.edicts);
1032 for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
1034 pr_xfunction->builtinsprofile++;
1037 if (ent->v->solid == SOLID_NOT)
1040 // LordHavoc: compare against bounding box rather than center,
1041 // and use DotProduct instead of Length, major speedup
1042 eorg[0] = (org[0] - ent->v->origin[0]) - bound(ent->v->mins[0], (org[0] - ent->v->origin[0]), ent->v->maxs[0]);
1043 eorg[1] = (org[1] - ent->v->origin[1]) - bound(ent->v->mins[1], (org[1] - ent->v->origin[1]), ent->v->maxs[1]);
1044 eorg[2] = (org[2] - ent->v->origin[2]) - bound(ent->v->mins[2], (org[2] - ent->v->origin[2]), ent->v->maxs[2]);
1045 if (DotProduct(eorg, eorg) > radius2)
1048 ent->v->chain = EDICT_TO_PROG(chain);
1052 RETURN_EDICT(chain);
1061 void PF_dprint (void)
1063 Con_DPrintf ("%s",PF_VarString(0));
1066 // LordHavoc: added this to semi-fix the problem of using many ftos calls in a print
1067 #define STRINGTEMP_BUFFERS 16
1068 #define STRINGTEMP_LENGTH 128
1069 static char pr_string_temp[STRINGTEMP_BUFFERS][STRINGTEMP_LENGTH];
1070 static int pr_string_tempindex = 0;
1072 static char *PR_GetTempString(void)
1075 s = pr_string_temp[pr_string_tempindex];
1076 pr_string_tempindex = (pr_string_tempindex + 1) % STRINGTEMP_BUFFERS;
1084 v = G_FLOAT(OFS_PARM0);
1086 s = PR_GetTempString();
1087 // LordHavoc: ftos improvement
1088 sprintf (s, "%g", v);
1089 G_INT(OFS_RETURN) = PR_SetString(s);
1095 v = G_FLOAT(OFS_PARM0);
1096 G_FLOAT(OFS_RETURN) = fabs(v);
1102 s = PR_GetTempString();
1103 sprintf (s, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
1104 G_INT(OFS_RETURN) = PR_SetString(s);
1110 s = PR_GetTempString();
1111 sprintf (s, "entity %i", G_EDICTNUM(OFS_PARM0));
1112 G_INT(OFS_RETURN) = PR_SetString(s);
1115 void PF_Spawn (void)
1118 pr_xfunction->builtinsprofile += 20;
1123 void PF_Remove (void)
1126 pr_xfunction->builtinsprofile += 20;
1128 ed = G_EDICT(OFS_PARM0);
1129 if (ed == sv.edicts)
1130 Host_Error("remove: tried to remove world\n");
1131 if (NUM_FOR_EDICT(ed) <= svs.maxclients)
1132 Host_Error("remove: tried to remove a client\n");
1137 // entity (entity start, .string field, string match) find = #5;
1145 e = G_EDICTNUM(OFS_PARM0);
1146 f = G_INT(OFS_PARM1);
1147 s = G_STRING(OFS_PARM2);
1150 RETURN_EDICT(sv.edicts);
1154 for (e++ ; e < sv.num_edicts ; e++)
1156 pr_xfunction->builtinsprofile++;
1170 RETURN_EDICT(sv.edicts);
1173 // LordHavoc: added this for searching float, int, and entity reference fields
1174 void PF_FindFloat (void)
1181 e = G_EDICTNUM(OFS_PARM0);
1182 f = G_INT(OFS_PARM1);
1183 s = G_FLOAT(OFS_PARM2);
1185 for (e++ ; e < sv.num_edicts ; e++)
1187 pr_xfunction->builtinsprofile++;
1191 if (E_FLOAT(ed,f) == s)
1198 RETURN_EDICT(sv.edicts);
1201 // chained search for strings in entity fields
1202 // entity(.string field, string match) findchain = #402;
1203 void PF_findchain (void)
1208 edict_t *ent, *chain;
1210 chain = (edict_t *)sv.edicts;
1212 f = G_INT(OFS_PARM0);
1213 s = G_STRING(OFS_PARM1);
1216 RETURN_EDICT(sv.edicts);
1220 ent = NEXT_EDICT(sv.edicts);
1221 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1223 pr_xfunction->builtinsprofile++;
1226 t = E_STRING(ent,f);
1232 ent->v->chain = EDICT_TO_PROG(chain);
1236 RETURN_EDICT(chain);
1239 // LordHavoc: chained search for float, int, and entity reference fields
1240 // entity(.string field, float match) findchainfloat = #403;
1241 void PF_findchainfloat (void)
1246 edict_t *ent, *chain;
1248 chain = (edict_t *)sv.edicts;
1250 f = G_INT(OFS_PARM0);
1251 s = G_FLOAT(OFS_PARM1);
1253 ent = NEXT_EDICT(sv.edicts);
1254 for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
1256 pr_xfunction->builtinsprofile++;
1259 if (E_FLOAT(ent,f) != s)
1262 ent->v->chain = EDICT_TO_PROG(chain);
1266 RETURN_EDICT(chain);
1269 void PR_CheckEmptyString (char *s)
1272 Host_Error ("Bad string");
1275 void PF_precache_file (void)
1276 { // precache_file is only used to copy files with qcc, it does nothing
1277 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1280 void PF_precache_sound (void)
1285 if (sv.state != ss_loading)
1286 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1288 s = G_STRING(OFS_PARM0);
1289 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1290 PR_CheckEmptyString (s);
1292 for (i=0 ; i<MAX_SOUNDS ; i++)
1294 if (!sv.sound_precache[i])
1296 sv.sound_precache[i] = s;
1299 if (!strcmp(sv.sound_precache[i], s))
1302 Host_Error ("PF_precache_sound: overflow");
1305 void PF_precache_model (void)
1310 if (sv.state != ss_loading)
1311 Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
1313 s = G_STRING(OFS_PARM0);
1314 if (sv.worldmodel->brushq1.ishlbsp && ((!s) || (!s[0])))
1316 G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
1317 PR_CheckEmptyString (s);
1319 for (i=0 ; i<MAX_MODELS ; i++)
1321 if (!sv.model_precache[i])
1323 sv.model_precache[i] = s;
1324 sv.models[i] = Mod_ForName (s, true, false, false);
1327 if (!strcmp(sv.model_precache[i], s))
1330 Host_Error ("PF_precache_model: overflow");
1334 void PF_coredump (void)
1339 void PF_traceon (void)
1344 void PF_traceoff (void)
1349 void PF_eprint (void)
1351 ED_PrintNum (G_EDICTNUM(OFS_PARM0));
1358 float(float yaw, float dist) walkmove
1361 void PF_walkmove (void)
1369 ent = PROG_TO_EDICT(pr_global_struct->self);
1370 yaw = G_FLOAT(OFS_PARM0);
1371 dist = G_FLOAT(OFS_PARM1);
1373 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
1375 G_FLOAT(OFS_RETURN) = 0;
1379 yaw = yaw*M_PI*2 / 360;
1381 move[0] = cos(yaw)*dist;
1382 move[1] = sin(yaw)*dist;
1385 // save program state, because SV_movestep may call other progs
1386 oldf = pr_xfunction;
1387 oldself = pr_global_struct->self;
1389 G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
1392 // restore program state
1393 pr_xfunction = oldf;
1394 pr_global_struct->self = oldself;
1404 void PF_droptofloor (void)
1410 ent = PROG_TO_EDICT(pr_global_struct->self);
1412 VectorCopy (ent->v->origin, end);
1415 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
1417 if (trace.fraction == 1)
1418 G_FLOAT(OFS_RETURN) = 0;
1421 VectorCopy (trace.endpos, ent->v->origin);
1422 SV_LinkEdict (ent, false);
1423 ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
1424 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
1425 G_FLOAT(OFS_RETURN) = 1;
1426 // if support is destroyed, keep suspended (gross hack for floating items in various maps)
1427 ent->e->suspendedinairflag = true;
1435 void(float style, string value) lightstyle
1438 void PF_lightstyle (void)
1445 style = G_FLOAT(OFS_PARM0);
1446 val = G_STRING(OFS_PARM1);
1448 // change the string in sv
1449 sv.lightstyles[style] = val;
1451 // send message to all clients on this server
1452 if (sv.state != ss_active)
1455 for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
1456 if (client->active || client->spawned)
1458 MSG_WriteChar (&client->message, svc_lightstyle);
1459 MSG_WriteChar (&client->message,style);
1460 MSG_WriteString (&client->message, val);
1467 f = G_FLOAT(OFS_PARM0);
1469 G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
1471 G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
1473 void PF_floor (void)
1475 G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
1479 G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
1488 void PF_checkbottom (void)
1490 G_FLOAT(OFS_RETURN) = SV_CheckBottom (G_EDICT(OFS_PARM0));
1498 void PF_pointcontents (void)
1500 G_FLOAT(OFS_RETURN) = SV_PointContents(G_VECTOR(OFS_PARM0));
1507 entity nextent(entity)
1510 void PF_nextent (void)
1515 i = G_EDICTNUM(OFS_PARM0);
1518 pr_xfunction->builtinsprofile++;
1520 if (i == sv.num_edicts)
1522 RETURN_EDICT(sv.edicts);
1538 Pick a vector for the player to shoot along
1539 vector aim(entity, missilespeed)
1544 edict_t *ent, *check, *bestent;
1545 vec3_t start, dir, end, bestdir;
1548 float dist, bestdist;
1551 ent = G_EDICT(OFS_PARM0);
1552 speed = G_FLOAT(OFS_PARM1);
1554 VectorCopy (ent->v->origin, start);
1557 // try sending a trace straight
1558 VectorCopy (pr_global_struct->v_forward, dir);
1559 VectorMA (start, 2048, dir, end);
1560 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1561 if (tr.ent && ((edict_t *)tr.ent)->v->takedamage == DAMAGE_AIM
1562 && (!teamplay.integer || ent->v->team <=0 || ent->v->team != ((edict_t *)tr.ent)->v->team) )
1564 VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
1569 // try all possible entities
1570 VectorCopy (dir, bestdir);
1571 bestdist = sv_aim.value;
1574 check = NEXT_EDICT(sv.edicts);
1575 for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
1577 pr_xfunction->builtinsprofile++;
1578 if (check->v->takedamage != DAMAGE_AIM)
1582 if (teamplay.integer && ent->v->team > 0 && ent->v->team == check->v->team)
1583 continue; // don't aim at teammate
1584 for (j=0 ; j<3 ; j++)
1585 end[j] = check->v->origin[j]
1586 + 0.5*(check->v->mins[j] + check->v->maxs[j]);
1587 VectorSubtract (end, start, dir);
1588 VectorNormalize (dir);
1589 dist = DotProduct (dir, pr_global_struct->v_forward);
1590 if (dist < bestdist)
1591 continue; // to far to turn
1592 tr = SV_Move (start, vec3_origin, vec3_origin, end, MOVE_NORMAL, ent);
1593 if (tr.ent == check)
1594 { // can shoot at this one
1602 VectorSubtract (bestent->v->origin, ent->v->origin, dir);
1603 dist = DotProduct (dir, pr_global_struct->v_forward);
1604 VectorScale (pr_global_struct->v_forward, dist, end);
1606 VectorNormalize (end);
1607 VectorCopy (end, G_VECTOR(OFS_RETURN));
1611 VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
1619 This was a major timewaster in progs, so it was converted to C
1622 void PF_changeyaw (void)
1625 float ideal, current, move, speed;
1627 ent = PROG_TO_EDICT(pr_global_struct->self);
1628 current = ANGLEMOD(ent->v->angles[1]);
1629 ideal = ent->v->ideal_yaw;
1630 speed = ent->v->yaw_speed;
1632 if (current == ideal)
1634 move = ideal - current;
1635 if (ideal > current)
1656 ent->v->angles[1] = ANGLEMOD (current + move);
1664 void PF_changepitch (void)
1667 float ideal, current, move, speed;
1670 ent = G_EDICT(OFS_PARM0);
1671 current = ANGLEMOD( ent->v->angles[0] );
1672 if ((val = GETEDICTFIELDVALUE(ent, eval_idealpitch)))
1673 ideal = val->_float;
1676 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1679 if ((val = GETEDICTFIELDVALUE(ent, eval_pitch_speed)))
1680 speed = val->_float;
1683 Host_Error ("PF_changepitch: .float idealpitch and .float pitch_speed must be defined to use changepitch");
1687 if (current == ideal)
1689 move = ideal - current;
1690 if (ideal > current)
1711 ent->v->angles[0] = ANGLEMOD (current + move);
1715 ===============================================================================
1719 ===============================================================================
1722 #define MSG_BROADCAST 0 // unreliable to all
1723 #define MSG_ONE 1 // reliable to one (msg_entity)
1724 #define MSG_ALL 2 // reliable to all
1725 #define MSG_INIT 3 // write to the init string
1727 sizebuf_t *WriteDest (void)
1733 dest = G_FLOAT(OFS_PARM0);
1737 return &sv.datagram;
1740 ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
1741 entnum = NUM_FOR_EDICT(ent);
1742 if (entnum < 1 || entnum > svs.maxclients)
1743 Host_Error ("WriteDest: not a client");
1744 return &svs.clients[entnum-1].message;
1747 return &sv.reliable_datagram;
1753 Host_Error ("WriteDest: bad destination");
1760 void PF_WriteByte (void)
1762 MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
1765 void PF_WriteChar (void)
1767 MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
1770 void PF_WriteShort (void)
1772 MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
1775 void PF_WriteLong (void)
1777 MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
1780 void PF_WriteAngle (void)
1782 MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
1785 void PF_WriteCoord (void)
1787 MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1));
1790 void PF_WriteString (void)
1792 MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
1796 void PF_WriteEntity (void)
1798 MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
1801 //=============================================================================
1803 void PF_makestatic (void)
1808 ent = G_EDICT(OFS_PARM0);
1811 if (ent->v->modelindex >= 256 || ent->v->frame >= 256)
1816 MSG_WriteByte (&sv.signon,svc_spawnstatic2);
1817 MSG_WriteShort (&sv.signon, ent->v->modelindex);
1818 MSG_WriteShort (&sv.signon, ent->v->frame);
1822 MSG_WriteByte (&sv.signon,svc_spawnstatic);
1823 MSG_WriteByte (&sv.signon, ent->v->modelindex);
1824 MSG_WriteByte (&sv.signon, ent->v->frame);
1827 MSG_WriteByte (&sv.signon, ent->v->colormap);
1828 MSG_WriteByte (&sv.signon, ent->v->skin);
1829 for (i=0 ; i<3 ; i++)
1831 MSG_WriteDPCoord(&sv.signon, ent->v->origin[i]);
1832 MSG_WriteAngle(&sv.signon, ent->v->angles[i]);
1835 // throw the entity away now
1839 //=============================================================================
1846 void PF_setspawnparms (void)
1852 ent = G_EDICT(OFS_PARM0);
1853 i = NUM_FOR_EDICT(ent);
1854 if (i < 1 || i > svs.maxclients)
1855 Host_Error ("Entity is not a client");
1857 // copy spawn parms out of the client_t
1858 client = svs.clients + (i-1);
1860 for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
1861 (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
1869 void PF_changelevel (void)
1873 // make sure we don't issue two changelevels
1874 if (svs.changelevel_issued)
1876 svs.changelevel_issued = true;
1878 s = G_STRING(OFS_PARM0);
1879 Cbuf_AddText (va("changelevel %s\n",s));
1884 G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0));
1889 G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0));
1894 G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0));
1901 Returns a vector of length < 1
1906 void PF_randomvec (void)
1911 temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1912 temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1913 temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
1915 while (DotProduct(temp, temp) >= 1);
1916 VectorCopy (temp, G_VECTOR(OFS_RETURN));
1919 void SV_LightPoint (vec3_t color, vec3_t p);
1924 Returns a color vector indicating the lighting at the requested point.
1926 (Internal Operation note: actually measures the light beneath the point, just like
1927 the model lighting on the client)
1932 void PF_GetLight (void)
1936 p = G_VECTOR(OFS_PARM0);
1937 SV_LightPoint (color, p);
1938 VectorCopy (color, G_VECTOR(OFS_RETURN));
1941 #define MAX_QC_CVARS 128
1942 cvar_t qc_cvar[MAX_QC_CVARS];
1945 void PF_registercvar (void)
1949 name = G_STRING(OFS_PARM0);
1950 value = G_STRING(OFS_PARM1);
1951 G_FLOAT(OFS_RETURN) = 0;
1952 // first check to see if it has already been defined
1953 if (Cvar_FindVar (name))
1956 // check for overlap with a command
1957 if (Cmd_Exists (name))
1959 Con_Printf ("PF_registercvar: %s is a command\n", name);
1963 if (currentqc_cvar >= MAX_QC_CVARS)
1964 Host_Error ("PF_registercvar: ran out of cvar slots (%i)\n", MAX_QC_CVARS);
1966 // copy the name and value
1967 variable = &qc_cvar[currentqc_cvar++];
1968 variable->name = Z_Malloc (strlen(name)+1);
1969 strcpy (variable->name, name);
1970 variable->string = Z_Malloc (strlen(value)+1);
1971 strcpy (variable->string, value);
1972 variable->value = atof (value);
1974 Cvar_RegisterVariable(variable);
1975 G_FLOAT(OFS_RETURN) = 1; // success
1982 returns the minimum of two supplied floats
1989 // LordHavoc: 3+ argument enhancement suggested by FrikaC
1991 G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
1992 else if (pr_argc >= 3)
1995 float f = G_FLOAT(OFS_PARM0);
1996 for (i = 1;i < pr_argc;i++)
1997 if (G_FLOAT((OFS_PARM0+i*3)) < f)
1998 f = G_FLOAT((OFS_PARM0+i*3));
1999 G_FLOAT(OFS_RETURN) = f;
2002 Host_Error("min: must supply at least 2 floats\n");
2009 returns the maximum of two supplied floats
2016 // LordHavoc: 3+ argument enhancement suggested by FrikaC
2018 G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2019 else if (pr_argc >= 3)
2022 float f = G_FLOAT(OFS_PARM0);
2023 for (i = 1;i < pr_argc;i++)
2024 if (G_FLOAT((OFS_PARM0+i*3)) > f)
2025 f = G_FLOAT((OFS_PARM0+i*3));
2026 G_FLOAT(OFS_RETURN) = f;
2029 Host_Error("max: must supply at least 2 floats\n");
2036 returns number bounded by supplied range
2038 min(min, value, max)
2041 void PF_bound (void)
2043 G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
2050 returns a raised to power b
2057 G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
2064 copies data from one entity to another
2066 copyentity(src, dst)
2069 void PF_copyentity (void)
2072 in = G_EDICT(OFS_PARM0);
2073 out = G_EDICT(OFS_PARM1);
2074 memcpy(out->v, in->v, progs->entityfields * 4);
2081 sets the color of a client and broadcasts the update to all connected clients
2083 setcolor(clientent, value)
2086 void PF_setcolor (void)
2092 entnum = G_EDICTNUM(OFS_PARM0);
2093 i = G_FLOAT(OFS_PARM1);
2095 if (entnum < 1 || entnum > svs.maxclients)
2097 Con_Printf ("tried to setcolor a non-client\n");
2101 client = &svs.clients[entnum-1];
2102 if ((val = GETEDICTFIELDVALUE(client->edict, eval_clientcolors)))
2105 client->old_colors = i;
2106 client->edict->v->team = (i & 15) + 1;
2108 MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
2109 MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
2110 MSG_WriteByte (&sv.reliable_datagram, i);
2117 effect(origin, modelname, startframe, framecount, framerate)
2120 void PF_effect (void)
2123 s = G_STRING(OFS_PARM1);
2125 Host_Error("effect: no model specified\n");
2127 SV_StartEffect(G_VECTOR(OFS_PARM0), SV_ModelIndex(s), G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), G_FLOAT(OFS_PARM4));
2130 void PF_te_blood (void)
2132 if (G_FLOAT(OFS_PARM2) < 1)
2134 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2135 MSG_WriteByte(&sv.datagram, TE_BLOOD);
2137 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2138 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2139 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2141 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2142 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2143 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2145 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2148 void PF_te_bloodshower (void)
2150 if (G_FLOAT(OFS_PARM3) < 1)
2152 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2153 MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER);
2155 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2156 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2157 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2159 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2160 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2161 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2163 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2));
2165 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2168 void PF_te_explosionrgb (void)
2170 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2171 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB);
2173 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2174 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2175 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2177 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255));
2178 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255));
2179 MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[2] * 255), 255));
2182 void PF_te_particlecube (void)
2184 if (G_FLOAT(OFS_PARM3) < 1)
2186 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2187 MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE);
2189 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2190 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2191 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2193 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2194 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2195 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2197 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2198 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2199 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2201 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2203 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2204 // gravity true/false
2205 MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0);
2207 MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6));
2210 void PF_te_particlerain (void)
2212 if (G_FLOAT(OFS_PARM3) < 1)
2214 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2215 MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN);
2217 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2218 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2219 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2221 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2222 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2223 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2225 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2226 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2227 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2229 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2231 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2234 void PF_te_particlesnow (void)
2236 if (G_FLOAT(OFS_PARM3) < 1)
2238 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2239 MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW);
2241 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2242 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2243 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2245 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2246 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2247 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2249 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2250 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2251 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2253 MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535));
2255 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM4));
2258 void PF_te_spark (void)
2260 if (G_FLOAT(OFS_PARM2) < 1)
2262 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2263 MSG_WriteByte(&sv.datagram, TE_SPARK);
2265 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2266 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2267 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2269 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127));
2270 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127));
2271 MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[2], 127));
2273 MSG_WriteByte(&sv.datagram, bound(0, (int) G_FLOAT(OFS_PARM2), 255));
2276 void PF_te_gunshotquad (void)
2278 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2279 MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD);
2281 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2282 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2283 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2286 void PF_te_spikequad (void)
2288 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2289 MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD);
2291 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2292 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2293 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2296 void PF_te_superspikequad (void)
2298 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2299 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD);
2301 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2302 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2303 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2306 void PF_te_explosionquad (void)
2308 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2309 MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD);
2311 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2312 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2313 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2316 void PF_te_smallflash (void)
2318 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2319 MSG_WriteByte(&sv.datagram, TE_SMALLFLASH);
2321 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2322 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2323 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2326 void PF_te_customflash (void)
2328 if (G_FLOAT(OFS_PARM1) < 8 || G_FLOAT(OFS_PARM2) < (1.0 / 256.0))
2330 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2331 MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH);
2333 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2334 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2335 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2337 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255));
2339 MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM2) / 256 - 1, 255));
2341 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[0] * 255, 255));
2342 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[1] * 255, 255));
2343 MSG_WriteByte(&sv.datagram, bound(0, G_VECTOR(OFS_PARM3)[2] * 255, 255));
2346 void PF_te_gunshot (void)
2348 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2349 MSG_WriteByte(&sv.datagram, TE_GUNSHOT);
2351 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2352 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2353 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2356 void PF_te_spike (void)
2358 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2359 MSG_WriteByte(&sv.datagram, TE_SPIKE);
2361 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2362 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2363 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2366 void PF_te_superspike (void)
2368 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2369 MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE);
2371 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2372 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2373 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2376 void PF_te_explosion (void)
2378 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2379 MSG_WriteByte(&sv.datagram, TE_EXPLOSION);
2381 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2382 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2383 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2386 void PF_te_tarexplosion (void)
2388 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2389 MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION);
2391 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2392 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2393 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2396 void PF_te_wizspike (void)
2398 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2399 MSG_WriteByte(&sv.datagram, TE_WIZSPIKE);
2401 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2402 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2403 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2406 void PF_te_knightspike (void)
2408 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2409 MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE);
2411 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2412 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2413 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2416 void PF_te_lavasplash (void)
2418 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2419 MSG_WriteByte(&sv.datagram, TE_LAVASPLASH);
2421 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2422 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2423 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2426 void PF_te_teleport (void)
2428 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2429 MSG_WriteByte(&sv.datagram, TE_TELEPORT);
2431 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2432 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2433 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2436 void PF_te_explosion2 (void)
2438 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2439 MSG_WriteByte(&sv.datagram, TE_EXPLOSION2);
2441 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2442 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2443 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2445 MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1));
2448 void PF_te_lightning1 (void)
2450 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2451 MSG_WriteByte(&sv.datagram, TE_LIGHTNING1);
2453 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2455 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2456 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2457 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2459 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2460 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2461 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2464 void PF_te_lightning2 (void)
2466 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2467 MSG_WriteByte(&sv.datagram, TE_LIGHTNING2);
2469 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2471 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2472 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2473 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2475 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2476 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2477 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2480 void PF_te_lightning3 (void)
2482 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2483 MSG_WriteByte(&sv.datagram, TE_LIGHTNING3);
2485 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2487 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2488 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2489 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2491 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2492 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2493 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2496 void PF_te_beam (void)
2498 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2499 MSG_WriteByte(&sv.datagram, TE_BEAM);
2501 MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0));
2503 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]);
2504 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]);
2505 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]);
2507 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]);
2508 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]);
2509 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]);
2512 void PF_te_plasmaburn (void)
2514 MSG_WriteByte(&sv.datagram, svc_temp_entity);
2515 MSG_WriteByte(&sv.datagram, TE_PLASMABURN);
2516 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]);
2517 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]);
2518 MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]);
2521 static void clippointtosurface(msurface_t *surf, vec3_t p, vec3_t out)
2524 vec3_t v1, clipplanenormal, normal;
2525 vec_t clipplanedist, clipdist;
2527 if (surf->flags & SURF_PLANEBACK)
2528 VectorNegate(surf->plane->normal, normal);
2530 VectorCopy(surf->plane->normal, normal);
2531 for (i = 0, j = surf->poly_numverts - 1;i < surf->poly_numverts;j = i, i++)
2533 VectorSubtract(&surf->poly_verts[j * 3], &surf->poly_verts[i * 3], v1);
2534 VectorNormalizeFast(v1);
2535 CrossProduct(v1, normal, clipplanenormal);
2536 clipplanedist = DotProduct(&surf->poly_verts[i * 3], clipplanenormal);
2537 clipdist = DotProduct(out, clipplanenormal) - clipplanedist;
2540 clipdist = -clipdist;
2541 VectorMA(out, clipdist, clipplanenormal, out);
2546 static msurface_t *getsurface(edict_t *ed, int surfnum)
2550 if (!ed || ed->e->free)
2552 modelindex = ed->v->modelindex;
2553 if (modelindex < 1 || modelindex >= MAX_MODELS)
2555 model = sv.models[modelindex];
2556 if (model->type != mod_brush)
2558 if (surfnum < 0 || surfnum >= model->brushq1.nummodelsurfaces)
2560 return model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2564 //PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints = #434;
2565 void PF_getsurfacenumpoints(void)
2568 // return 0 if no such surface
2569 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2571 G_FLOAT(OFS_RETURN) = 0;
2575 G_FLOAT(OFS_RETURN) = surf->poly_numverts;
2577 //PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint = #435;
2578 void PF_getsurfacepoint(void)
2583 VectorClear(G_VECTOR(OFS_RETURN));
2584 ed = G_EDICT(OFS_PARM0);
2585 if (!ed || ed->e->free)
2587 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2589 pointnum = G_FLOAT(OFS_PARM2);
2590 if (pointnum < 0 || pointnum >= surf->poly_numverts)
2592 // FIXME: implement rotation/scaling
2593 VectorAdd(&surf->poly_verts[pointnum * 3], ed->v->origin, G_VECTOR(OFS_RETURN));
2595 //PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal = #436;
2596 void PF_getsurfacenormal(void)
2599 VectorClear(G_VECTOR(OFS_RETURN));
2600 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2602 // FIXME: implement rotation/scaling
2603 if (surf->flags & SURF_PLANEBACK)
2604 VectorNegate(surf->plane->normal, G_VECTOR(OFS_RETURN));
2606 VectorCopy(surf->plane->normal, G_VECTOR(OFS_RETURN));
2608 //PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture = #437;
2609 void PF_getsurfacetexture(void)
2612 G_INT(OFS_RETURN) = 0;
2613 if (!(surf = getsurface(G_EDICT(OFS_PARM0), G_FLOAT(OFS_PARM1))))
2615 G_INT(OFS_RETURN) = PR_SetString(surf->texinfo->texture->name);
2617 //PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint = #438;
2618 void PF_getsurfacenearpoint(void)
2620 int surfnum, best, modelindex;
2622 vec_t dist, bestdist;
2627 G_FLOAT(OFS_RETURN) = -1;
2628 ed = G_EDICT(OFS_PARM0);
2629 point = G_VECTOR(OFS_PARM1);
2631 if (!ed || ed->e->free)
2633 modelindex = ed->v->modelindex;
2634 if (modelindex < 1 || modelindex >= MAX_MODELS)
2636 model = sv.models[modelindex];
2637 if (model->type != mod_brush)
2640 // FIXME: implement rotation/scaling
2641 VectorSubtract(point, ed->v->origin, p);
2643 bestdist = 1000000000;
2644 for (surfnum = 0;surfnum < model->brushq1.nummodelsurfaces;surfnum++)
2646 surf = model->brushq1.surfaces + surfnum + model->brushq1.firstmodelsurface;
2647 dist = PlaneDiff(p, surf->plane);
2649 if (dist < bestdist)
2651 clippointtosurface(surf, p, clipped);
2652 VectorSubtract(clipped, p, clipped);
2653 dist += DotProduct(clipped, clipped);
2654 if (dist < bestdist)
2661 G_FLOAT(OFS_RETURN) = best;
2663 //PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
2664 void PF_getsurfaceclippedpoint(void)
2669 VectorClear(G_VECTOR(OFS_RETURN));
2670 ed = G_EDICT(OFS_PARM0);
2671 if (!ed || ed->e->free)
2673 if (!(surf = getsurface(ed, G_FLOAT(OFS_PARM1))))
2675 // FIXME: implement rotation/scaling
2676 VectorSubtract(G_VECTOR(OFS_PARM2), ed->v->origin, p);
2677 clippointtosurface(surf, p, out);
2678 // FIXME: implement rotation/scaling
2679 VectorAdd(out, ed->v->origin, G_VECTOR(OFS_RETURN));
2682 #define MAX_PRFILES 256
2684 qfile_t *pr_files[MAX_PRFILES];
2686 void PR_Files_Init(void)
2688 memset(pr_files, 0, sizeof(pr_files));
2691 void PR_Files_CloseAll(void)
2694 for (i = 0;i < MAX_PRFILES;i++)
2697 FS_Close(pr_files[i]);
2702 //float(string s) stof = #81; // get numerical value from a string
2705 char *s = PF_VarString(0);
2706 G_FLOAT(OFS_RETURN) = atof(s);
2709 //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
2713 char *modestring, *filename;
2714 for (filenum = 0;filenum < MAX_PRFILES;filenum++)
2715 if (pr_files[filenum] == NULL)
2717 if (filenum >= MAX_PRFILES)
2719 Con_Printf("PF_fopen: ran out of file handles (%i)\n", MAX_PRFILES);
2720 G_FLOAT(OFS_RETURN) = -2;
2723 mode = G_FLOAT(OFS_PARM1);
2726 case 0: // FILE_READ
2729 case 1: // FILE_APPEND
2732 case 2: // FILE_WRITE
2736 Con_Printf("PF_fopen: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", mode);
2737 G_FLOAT(OFS_RETURN) = -3;
2740 filename = G_STRING(OFS_PARM0);
2741 // .. is parent directory on many platforms
2742 // / is parent directory on Amiga
2743 // : is root of drive on Amiga (also used as a directory separator on Mac, but / works there too, so that's a bad idea)
2744 // \ is a windows-ism (so it's naughty to use it, / works on all platforms)
2745 if ((filename[0] == '.' && filename[1] == '.') || filename[0] == '/' || strrchr(filename, ':') || strrchr(filename, '\\'))
2747 Con_Printf("PF_fopen: dangerous or non-portable filename \"%s\" not allowed. (contains : or \\ or begins with .. or /)\n", filename);
2748 G_FLOAT(OFS_RETURN) = -4;
2751 pr_files[filenum] = FS_Open(va("data/%s", filename), modestring, false);
2752 if (pr_files[filenum] == NULL)
2753 G_FLOAT(OFS_RETURN) = -1;
2755 G_FLOAT(OFS_RETURN) = filenum;
2758 //void(float fhandle) fclose = #111; // closes a file
2759 void PF_fclose(void)
2761 int filenum = G_FLOAT(OFS_PARM0);
2762 if (filenum < 0 || filenum >= MAX_PRFILES)
2764 Con_Printf("PF_fclose: invalid file handle %i\n", filenum);
2767 if (pr_files[filenum] == NULL)
2769 Con_Printf("PF_fclose: no such file handle %i (or file has been closed)\n", filenum);
2772 FS_Close(pr_files[filenum]);
2773 pr_files[filenum] = NULL;
2776 //string(float fhandle) fgets = #112; // reads a line of text from the file and returns as a tempstring
2780 static char string[MAX_VARSTRING];
2781 int filenum = G_FLOAT(OFS_PARM0);
2782 if (filenum < 0 || filenum >= MAX_PRFILES)
2784 Con_Printf("PF_fgets: invalid file handle %i\n", filenum);
2787 if (pr_files[filenum] == NULL)
2789 Con_Printf("PF_fgets: no such file handle %i (or file has been closed)\n", filenum);
2795 c = FS_Getc(pr_files[filenum]);
2796 if (c == '\r' || c == '\n' || c < 0)
2798 if (end < MAX_VARSTRING - 1)
2802 // remove \n following \r
2804 c = FS_Getc(pr_files[filenum]);
2805 if (developer.integer)
2806 Con_Printf("fgets: %s\n", string);
2808 G_INT(OFS_RETURN) = PR_SetString(string);
2810 G_INT(OFS_RETURN) = 0;
2813 //void(float fhandle, string s) fputs = #113; // writes a line of text to the end of the file
2817 char *s = PF_VarString(1);
2818 int filenum = G_FLOAT(OFS_PARM0);
2819 if (filenum < 0 || filenum >= MAX_PRFILES)
2821 Con_Printf("PF_fputs: invalid file handle %i\n", filenum);
2824 if (pr_files[filenum] == NULL)
2826 Con_Printf("PF_fputs: no such file handle %i (or file has been closed)\n", filenum);
2829 if ((stringlength = strlen(s)))
2830 FS_Write(pr_files[filenum], s, stringlength);
2831 if (developer.integer)
2832 Con_Printf("fputs: %s\n", s);
2835 //float(string s) strlen = #114; // returns how many characters are in a string
2836 void PF_strlen(void)
2839 s = G_STRING(OFS_PARM0);
2841 G_FLOAT(OFS_RETURN) = strlen(s);
2843 G_FLOAT(OFS_RETURN) = 0;
2846 //string(string s1, string s2) strcat = #115; // concatenates two strings (for example "abc", "def" would return "abcdef") and returns as a tempstring
2847 void PF_strcat(void)
2849 char *s = PF_VarString(0);
2850 G_INT(OFS_RETURN) = PR_SetString(s);
2853 //string(string s, float start, float length) substring = #116; // returns a section of a string as a tempstring
2854 void PF_substring(void)
2857 char *s, string[MAX_VARSTRING];
2858 s = G_STRING(OFS_PARM0);
2859 start = G_FLOAT(OFS_PARM1);
2860 end = G_FLOAT(OFS_PARM2) + start;
2863 for (i = 0;i < start && *s;i++, s++);
2864 for (i = 0;i < MAX_VARSTRING - 1 && *s && i < end;i++, s++)
2867 G_INT(OFS_RETURN) = PR_SetString(string);
2870 //vector(string s) stov = #117; // returns vector value from a string
2873 Math_atov(PF_VarString(0), G_VECTOR(OFS_RETURN));
2876 //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)
2877 void PF_strzone(void)
2880 in = G_STRING(OFS_PARM0);
2881 out = Mem_Alloc(pr_strings_mempool, strlen(in) + 1);
2883 G_INT(OFS_RETURN) = PR_SetString(out);
2886 //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!!!)
2887 void PF_strunzone(void)
2889 Mem_Free(G_STRING(OFS_PARM0));
2892 //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client
2893 //this function originally written by KrimZon, made shorter by LordHavoc
2894 void PF_clientcommand (void)
2896 client_t *temp_client;
2899 //find client for this entity
2900 i = (NUM_FOR_EDICT(G_EDICT(OFS_PARM0)) - 1);
2901 if (i < 0 || i >= svs.maxclients)
2902 Host_Error("PF_clientcommand: entity is not a client");
2904 temp_client = host_client;
2905 host_client = &svs.clients[i];
2906 Cmd_ExecuteString (G_STRING(OFS_PARM1), src_client);
2907 host_client = temp_client;
2910 //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
2911 //this function originally written by KrimZon, made shorter by LordHavoc
2912 char **tokens = NULL;
2913 int max_tokens, num_tokens = 0;
2914 void PF_tokenize (void)
2918 str = G_STRING(OFS_PARM0);
2923 for (i=0;i<num_tokens;i++)
2929 tokens = Z_Malloc(strlen(str) * sizeof(char *));
2930 max_tokens = strlen(str);
2932 for (p = str;COM_ParseToken(&p) && num_tokens < max_tokens;num_tokens++)
2934 tokens[num_tokens] = Z_Malloc(strlen(com_token) + 1);
2935 strcpy(tokens[num_tokens], com_token);
2938 G_FLOAT(OFS_RETURN) = num_tokens;
2941 //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index)
2942 //this function originally written by KrimZon, made shorter by LordHavoc
2945 int token_num = G_FLOAT(OFS_PARM0);
2946 if (token_num >= 0 && token_num < num_tokens)
2947 G_INT(OFS_RETURN) = PR_SetString(tokens[token_num]);
2949 G_INT(OFS_RETURN) = PR_SetString("");
2953 builtin_t pr_builtin[] =
2956 PF_makevectors, // #1 void(entity e) makevectors
2957 PF_setorigin, // #2 void(entity e, vector o) setorigin
2958 PF_setmodel, // #3 void(entity e, string m) setmodel
2959 PF_setsize, // #4 void(entity e, vector min, vector max) setsize
2960 NULL, // #5 void(entity e, vector min, vector max) setabssize
2961 PF_break, // #6 void() break
2962 PF_random, // #7 float() random
2963 PF_sound, // #8 void(entity e, float chan, string samp) sound
2964 PF_normalize, // #9 vector(vector v) normalize
2965 PF_error, // #10 void(string e) error
2966 PF_objerror, // #11 void(string e) objerror
2967 PF_vlen, // #12 float(vector v) vlen
2968 PF_vectoyaw, // #13 float(vector v) vectoyaw
2969 PF_Spawn, // #14 entity() spawn
2970 PF_Remove, // #15 void(entity e) remove
2971 PF_traceline, // #16 float(vector v1, vector v2, float tryents) traceline
2972 PF_checkclient, // #17 entity() clientlist
2973 PF_Find, // #18 entity(entity start, .string fld, string match) find
2974 PF_precache_sound, // #19 void(string s) precache_sound
2975 PF_precache_model, // #20 void(string s) precache_model
2976 PF_stuffcmd, // #21 void(entity client, string s)stuffcmd
2977 PF_findradius, // #22 entity(vector org, float rad) findradius
2978 PF_bprint, // #23 void(string s) bprint
2979 PF_sprint, // #24 void(entity client, string s) sprint
2980 PF_dprint, // #25 void(string s) dprint
2981 PF_ftos, // #26 void(string s) ftos
2982 PF_vtos, // #27 void(string s) vtos
2983 PF_coredump, // #28 void() coredump
2984 PF_traceon, // #29 void() traceon
2985 PF_traceoff, // #30 void() traceoff
2986 PF_eprint, // #31 void(entity e) eprint
2987 PF_walkmove, // #32 float(float yaw, float dist) walkmove
2989 PF_droptofloor, // #34 float() droptofloor
2990 PF_lightstyle, // #35 void(float style, string value) lightstyle
2991 PF_rint, // #36 float(float v) rint
2992 PF_floor, // #37 float(float v) floor
2993 PF_ceil, // #38 float(float v) ceil
2995 PF_checkbottom, // #40 float(entity e) checkbottom
2996 PF_pointcontents , // #41 float(vector v) pointcontents
2998 PF_fabs, // #43 float(float f) fabs
2999 PF_aim, // #44 vector(entity e, float speed) aim
3000 PF_cvar, // #45 float(string s) cvar
3001 PF_localcmd, // #46 void(string s) localcmd
3002 PF_nextent, // #47 entity(entity e) nextent
3003 PF_particle, // #48 void(vector o, vector d, float color, float count) particle
3004 PF_changeyaw, // #49 void() ChangeYaw
3006 PF_vectoangles, // #51 vector(vector v) vectoangles
3007 PF_WriteByte, // #52 void(float to, float f) WriteByte
3008 PF_WriteChar, // #53 void(float to, float f) WriteChar
3009 PF_WriteShort, // #54 void(float to, float f) WriteShort
3010 PF_WriteLong, // #55 void(float to, float f) WriteLong
3011 PF_WriteCoord, // #56 void(float to, float f) WriteCoord
3012 PF_WriteAngle, // #57 void(float to, float f) WriteAngle
3013 PF_WriteString, // #58 void(float to, string s) WriteString
3014 PF_WriteEntity, // #59 void(float to, entity e) WriteEntity
3015 PF_sin, // #60 float(float f) sin (DP_QC_SINCOSSQRTPOW)
3016 PF_cos, // #61 float(float f) cos (DP_QC_SINCOSSQRTPOW)
3017 PF_sqrt, // #62 float(float f) sqrt (DP_QC_SINCOSSQRTPOW)
3018 PF_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH)
3019 PF_TraceToss, // #64 void(entity e, entity ignore) tracetoss (DP_QC_TRACETOSS)
3020 PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS)
3022 SV_MoveToGoal, // #67 void(float step) movetogoal
3023 PF_precache_file, // #68 string(string s) precache_file
3024 PF_makestatic, // #69 void(entity e) makestatic
3025 PF_changelevel, // #70 void(string s) changelevel
3027 PF_cvar_set, // #72 void(string var, string val) cvar_set
3028 PF_centerprint, // #73 void(entity client, strings) centerprint
3029 PF_ambientsound, // #74 void(vector pos, string samp, float vol, float atten) ambientsound
3030 PF_precache_model, // #75 string(string s) precache_model2
3031 PF_precache_sound, // #76 string(string s) precache_sound2
3032 PF_precache_file, // #77 string(string s) precache_file2
3033 PF_setspawnparms, // #78 void(entity e) setspawnparms
3036 PF_stof, // #81 float(string s) stof (FRIK_FILE)
3045 PF_tracebox, // #90 void(vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox (DP_QC_TRACEBOX)
3046 PF_randomvec, // #91 vector() randomvec (DP_QC_RANDOMVEC)
3047 PF_GetLight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT)
3048 PF_registercvar, // #93 float(string name, string value) registercvar (DP_REGISTERCVAR)
3049 PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND)
3050 PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND)
3051 PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND)
3052 PF_pow, // #97 float(float f, float f) pow (DP_QC_SINCOSSQRTPOW)
3053 PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT)
3054 PF_checkextension, // #99 float(string s) checkextension (the basis of the extension system)
3065 PF_fopen, // #110 float(string filename, float mode) fopen (FRIK_FILE)
3066 PF_fclose, // #111 void(float fhandle) fclose (FRIK_FILE)
3067 PF_fgets, // #112 string(float fhandle) fgets (FRIK_FILE)
3068 PF_fputs, // #113 void(float fhandle, string s) fputs (FRIK_FILE)
3069 PF_strlen, // #114 float(string s) strlen (FRIK_FILE)
3070 PF_strcat, // #115 string(string s1, string s2) strcat (FRIK_FILE)
3071 PF_substring, // #116 string(string s, float start, float length) substring (FRIK_FILE)
3072 PF_stov, // #117 vector(string) stov (FRIK_FILE)
3073 PF_strzone, // #118 string(string s) strzone (FRIK_FILE)
3074 PF_strunzone, // #119 void(string s) strunzone (FRIK_FILE)
3075 #define a NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
3076 a a a a a a a a // #120-199
3077 a a a a a a a a a a // #200-299
3078 a a a a a a a a a a // #300-399
3079 PF_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY)
3080 PF_setcolor, // #401 void(entity ent, float colors) setcolor (DP_QC_SETCOLOR)
3081 PF_findchain, // #402 entity(.string fld, string match) findchain (DP_QC_FINDCHAIN)
3082 PF_findchainfloat, // #403 entity(.float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT)
3083 PF_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT)
3084 PF_te_blood, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD)
3085 PF_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER)
3086 PF_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB)
3087 PF_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE)
3088 PF_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN)
3089 PF_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW)
3090 PF_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK)
3091 PF_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_QUADEFFECTS1)
3092 PF_te_spikequad, // #413 void(vector org) te_spikequad (DP_QUADEFFECTS1)
3093 PF_te_superspikequad, // #414 void(vector org) te_superspikequad (DP_QUADEFFECTS1)
3094 PF_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_QUADEFFECTS1)
3095 PF_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH)
3096 PF_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH)
3097 PF_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS)
3098 PF_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS)
3099 PF_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS)
3100 PF_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS)
3101 PF_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS)
3102 PF_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS)
3103 PF_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS)
3104 PF_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS)
3105 PF_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS)
3106 PF_te_explosion2, // #427 void(vector org, float color) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS)
3107 PF_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS)
3108 PF_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS)
3109 PF_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS)
3110 PF_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS)
3111 PF_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS)
3112 PF_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN)
3113 PF_getsurfacenumpoints, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE)
3114 PF_getsurfacepoint, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE)
3115 PF_getsurfacenormal, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE)
3116 PF_getsurfacetexture, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE)
3117 PF_getsurfacenearpoint, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE)
3118 PF_getsurfaceclippedpoint, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE)
3119 PF_clientcommand, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND)
3120 PF_tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
3121 PF_argv, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
3129 a a a a a // #450-499 (LordHavoc)
3132 builtin_t *pr_builtins = pr_builtin;
3133 int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
3135 void PR_Cmd_Init(void)
3137 pr_strings_mempool = Mem_AllocPool("pr_stringszone");
3141 void PR_Cmd_Reset(void)
3143 Mem_EmptyPool(pr_strings_mempool);
3144 PR_Files_CloseAll();