📄 pr_cmds.c
字号:
//char pr_strcat_buf [128]; // 2001-10-25 Enhanced temp string handling by Maddes
// need this because pr_string_temp sucks
void PF_strcat (void)
{
char *s1, *s2;
int maxlen; // 2001-10-25 Enhanced temp string handling by Maddes
// memset(pr_strcat_buf, 0, 127); // 2001-10-25 Enhanced temp string handling by Maddes
s1 = G_STRING(OFS_PARM0);
s2 = PF_VarString(1);
// 2001-10-25 Enhanced temp string handling by Maddes start
// strcpy(pr_strcat_buf, s1);
pr_string_temp[0] = 0;
if (strlen(s1) < PR_MAX_TEMPSTRING)
{
strcpy(pr_string_temp, s1);
}
else
{
strncpy(pr_string_temp, s1, PR_MAX_TEMPSTRING);
pr_string_temp[PR_MAX_TEMPSTRING-1] = 0;
}
// strcat(pr_strcat_buf, s2);
maxlen = PR_MAX_TEMPSTRING - strlen(pr_string_temp) - 1; // -1 is EndOfString
if (maxlen > 0)
{
if (maxlen > strlen(s2))
{
strcat (pr_string_temp, s2);
}
else
{
strncat (pr_string_temp, s2, maxlen);
pr_string_temp[PR_MAX_TEMPSTRING-1] = 0;
}
}
// G_INT(OFS_RETURN) = pr_strcat_buf - pr_strings;
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
// 2001-10-25 Enhanced temp string handling by Maddes end
}
/*
=================
PF_substring
string substring (string, float, float)
=================
*/
void PF_substring (void)
{
int offset, length;
int maxoffset; // 2001-10-25 Enhanced temp string handling by Maddes
char *p;
p = G_STRING(OFS_PARM0);
offset = (int)G_FLOAT(OFS_PARM1); // for some reason, Quake doesn't like G_INT
length = (int)G_FLOAT(OFS_PARM2);
// cap values
maxoffset = strlen(p);
if (offset > maxoffset)
{
offset = maxoffset;
}
if (offset < 0)
offset = 0;
// 2001-10-25 Enhanced temp string handling by Maddes start
if (length >= PR_MAX_TEMPSTRING)
length = PR_MAX_TEMPSTRING-1;
// 2001-10-25 Enhanced temp string handling by Maddes end
if (length < 0)
length = 0;
p += offset;
strncpy(pr_string_temp, p, length);
pr_string_temp[length]=0;
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
/*
=================
PF_stof
float stof (string)
=================
*/
// thanks Zoid, taken from QuakeWorld
void PF_stof (void)
{
char *s;
s = G_STRING(OFS_PARM0);
G_FLOAT(OFS_RETURN) = atof(s);
}
/*
=================
PF_stov
vector stov (string)
=================
*/
void PF_stov (void)
{
char *v;
int i;
vec3_t d;
v = G_STRING(OFS_PARM0);
for (i=0; i<3; i++)
{
while(v && (v[0] == ' ' || v[0] == '\'')) //skip unneeded data
v++;
d[i] = atof(v);
while (v && v[0] != ' ') // skip to next space
v++;
}
VectorCopy (d, G_VECTOR(OFS_RETURN));
}
// 2001-09-20 QuakeC string manipulation by FrikaC/Maddes end
// 2001-09-20 QuakeC file access by FrikaC/Maddes start
/*
=================
PF_fopen
float fopen (string,float)
=================
*/
void PF_fopen (void)
{
char *p = G_STRING(OFS_PARM0);
char *ftemp;
int fmode = G_FLOAT(OFS_PARM1);
int h = 0, fsize = 0;
switch (fmode)
{
case 0: // read
Sys_FileOpenRead (va("%s/%s",com_gamedir, p), &h);
G_FLOAT(OFS_RETURN) = (float) h;
return;
case 1: // append -- this is nasty
// copy whole file into the zone
fsize = Sys_FileOpenRead(va("%s/%s",com_gamedir, p), &h);
if (h == -1)
{
h = Sys_FileOpenWrite(va("%s/%s",com_gamedir, p));
G_FLOAT(OFS_RETURN) = (float) h;
return;
}
// 2001-09-20 QuakeC string zone by Maddes start
if (!zone_progstrings)
{
PF_allocate_zone_progstrings();
}
// 2001-09-20 QuakeC string zone by Maddes end
ftemp = Z_Malloc(zone_progstrings, fsize + 1); // 2001-09-20 QuakeC string zone by Maddes
Sys_FileRead(h, ftemp, fsize);
Sys_FileClose(h);
// spit it back out
h = Sys_FileOpenWrite(va("%s/%s",com_gamedir, p));
Sys_FileWrite(h, ftemp, fsize);
Z_Free(zone_progstrings, ftemp); // free it from memory // 2001-09-20 QuakeC string zone by Maddes
G_FLOAT(OFS_RETURN) = (float) h; // return still open handle
return;
default: // write
h = Sys_FileOpenWrite (va("%s/%s", com_gamedir, p));
G_FLOAT(OFS_RETURN) = (float) h;
return;
}
}
/*
=================
PF_fclose
void fclose (float)
=================
*/
void PF_fclose (void)
{
int h = (int)G_FLOAT(OFS_PARM0);
Sys_FileClose(h);
}
/*
=================
PF_fgets
string fgets (float)
=================
*/
void PF_fgets (void)
{
// reads one line (up to a \n) into a string
int h;
int i;
int count;
char buffer;
h = (int)G_FLOAT(OFS_PARM0);
count = Sys_FileRead(h, &buffer, 1);
if (count && buffer == '\r') // carriage return
{
count = Sys_FileRead(h, &buffer, 1); // skip
}
if (!count) // EndOfFile
{
G_INT(OFS_RETURN) = OFS_NULL; // void string
return;
}
i = 0;
while (count && buffer != '\n')
{
if (i < PR_MAX_TEMPSTRING-1) // no place for character in temp string
{
pr_string_temp[i++] = buffer;
}
// read next character
count = Sys_FileRead(h, &buffer, 1);
if (count && buffer == '\r') // carriage return
{
count = Sys_FileRead(h, &buffer, 1); // skip
}
};
pr_string_temp[i] = 0;
G_INT(OFS_RETURN) = pr_string_temp - pr_strings;
}
/*
=================
PF_fputs
void fputs (float,string)
=================
*/
void PF_fputs (void)
{
// writes to file, like bprint
float handle = G_FLOAT(OFS_PARM0);
char *str = PF_VarString(1);
Sys_FileWrite (handle, str, strlen(str));
}
// 2001-09-20 QuakeC file access by FrikaC/Maddes end
// 2001-11-15 DarkPlaces general builtin functions by LordHavoc start
/*
=================
PF_fmin
Returns the minimum of two or more supplied floats
float fmin(float f1, float f2, ...)
=================
*/
void PF_fmin (void)
{
// LordHavoc: 3+ argument enhancement suggested by FrikaC
if (pr_argc == 2)
G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
else if (pr_argc >= 3)
{
int i;
float f = G_FLOAT(OFS_PARM0);
for (i = 1;i < pr_argc;i++)
if (G_FLOAT((OFS_PARM0+i*3)) < f)
f = G_FLOAT((OFS_PARM0+i*3));
G_FLOAT(OFS_RETURN) = f;
}
else
PR_RunError("fmin: must supply at least 2 floats\n");
}
/*
=================
PF_fmax
Returns the maximum of two or more supplied floats
float fmax(float f1, float f2, ...)
=================
*/
void PF_fmax (void)
{
// LordHavoc: 3+ argument enhancement suggested by FrikaC
if (pr_argc == 2)
G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
else if (pr_argc >= 3)
{
int i;
float f = G_FLOAT(OFS_PARM0);
for (i = 1;i < pr_argc;i++)
if (G_FLOAT((OFS_PARM0+i*3)) > f)
f = G_FLOAT((OFS_PARM0+i*3));
G_FLOAT(OFS_RETURN) = f;
}
else
PR_RunError("fmax: must supply at least 2 floats\n");
}
/*
=================
PF_fbound
Returns number bounded by supplied range
float fbound(float min, float f, float max)
=================
*/
void PF_fbound (void)
{
G_FLOAT(OFS_RETURN) = bound(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1), G_FLOAT(OFS_PARM2));
}
/*
=================
PF_fpow
Returns base raised to power exp (base^exp)
float fpow(float base, float exp)
=================
*/
void PF_fpow (void)
{
G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1));
}
/*
=================
PF_findfloat
Loops through all entities beginning with the "start" entity, and checks the named entity field for a match.
entity findfloat(entity start, .string fld, float match)
=================
*/
// LordHavoc: added this for searching float, int, and entity reference fields
void PF_FindFloat (void)
{
int e;
int f;
float s;
edict_t *ed;
e = G_EDICTNUM(OFS_PARM0);
f = G_INT(OFS_PARM1);
s = G_FLOAT(OFS_PARM2);
for (e++ ; e < sv.num_edicts ; e++)
{
ed = EDICT_NUM(e);
if (ed->free)
continue;
if (E_FLOAT(ed,f) == s)
{
RETURN_EDICT(ed);
return;
}
}
RETURN_EDICT(sv.edicts);
}
/*
=================
PF_tracebox
Used for use tracing and shot targeting
Traces are blocked by bbox and exact bsp entities, and also slide box entities
if the tryents flag is set(?).
void(vector v1, vector mins, vector maxs, vector v2, float nomonsters, entity forent) tracebox
=================
*/
// LordHavoc: added this for my own use, VERY useful, similar to traceline
void PF_tracebox (void)
{
float *v1, *v2, *m1, *m2;
trace_t trace;
int nomonsters;
edict_t *ent;
v1 = G_VECTOR(OFS_PARM0);
m1 = G_VECTOR(OFS_PARM1);
m2 = G_VECTOR(OFS_PARM2);
v2 = G_VECTOR(OFS_PARM3);
nomonsters = G_FLOAT(OFS_PARM4);
ent = G_EDICT(OFS_PARM5);
trace = SV_Move (v1, m1, m2, v2, nomonsters, ent);
pr_global_struct->trace_allsolid = trace.allsolid;
pr_global_struct->trace_startsolid = trace.startsolid;
pr_global_struct->trace_fraction = trace.fraction;
pr_global_struct->trace_inwater = trace.inwater;
pr_global_struct->trace_inopen = trace.inopen;
VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
pr_global_struct->trace_plane_dist = trace.plane.dist;
if (trace.ent)
pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
else
pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
}
/*
=================
PF_randomvec
Returns a vector of length < 1
vector randomvec()
=================
*/
void PF_randomvec (void)
{
vec3_t temp;
do
{
temp[0] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
temp[1] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
temp[2] = (rand()&32767) * (2.0 / 32767.0) - 1.0;
}
while (DotProduct(temp, temp) >= 1);
VectorCopy (temp, G_VECTOR(OFS_RETURN));
}
/*
=================
PF_copyentity
copies data from one entity to another
copyentity(src, dst)
=================
*/
void PF_copyentity (void)
{
edict_t *in, *out;
in = G_EDICT(OFS_PARM0);
out = G_EDICT(OFS_PARM1);
memcpy(out, in, pr_edict_size);
}
/*
=================
PF_setcolor
sets the color of a client and broadcasts the update to all connected clients
setcolor(clientent, value)
=================
*/
void PF_setcolor (void)
{
client_t *client;
int entnum, i;
entnum = G_EDICTNUM(OFS_PARM0);
i = G_FLOAT(OFS_PARM1);
if (entnum < 1 || entnum > svs.maxclients)
{
Con_DPrintf ("PROGS.DAT tried to setcolor a non-client\n");
return;
}
client = &svs.clients[entnum-1];
client->colors = i;
client->edict->v.team = (i & 15) + 1;
MSG_WriteByte (&sv.reliable_datagram, svc_updatecolors);
MSG_WriteByte (&sv.reliable_datagram, entnum - 1);
MSG_WriteByte (&sv.reliable_datagram, i);
}
// chained search for strings in entity fields
// entity(.string field, string match) findchain = #402;
void PF_findchain (void)
{
int i;
int f;
char *s, *t;
edict_t *ent, *chain;
chain = (edict_t *)sv.edicts;
f = G_INT(OFS_PARM0);
s = G_STRING(OFS_PARM1);
if (!s || !s[0])
{
RETURN_EDICT(sv.edicts);
return;
}
ent = NEXT_EDICT(sv.edicts);
for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
{
if (ent->free)
continue;
t = E_STRING(ent,f);
if (!t)
continue;
if (strcmp(t,s))
continue;
ent->v.chain = EDICT_TO_PROG(chain);
chain = ent;
}
RETURN_EDICT(chain);
}
// LordHavoc: chained search for float, int, and entity reference fields
// entity(.string field, float match) findchainfloat = #403;
void PF_findchainfloat (void)
{
int i;
int f;
float s;
edict_t *ent, *chain;
chain = (edict_t *)sv.edicts;
f = G_INT(OFS_PARM0);
s = G_FLOAT(OFS_PARM1);
ent = NEXT_EDICT(sv.edicts);
for (i = 1;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent))
{
if (ent->free)
continue;
if (E_FLOAT(ent,f) != s)
continue;
ent->v.chain = EDICT_TO_PROG(chain);
chain = ent;
}
RETURN_EDICT(chain);
}
// 2001-11-15 DarkPlaces general builtin functions by LordHavoc end
// 2001-09-14 Enhanced BuiltIn Function System (EBFS) by Maddes start
/*
builtin_t pr_builtin[] =
{
...
};
*/
builtin_t *pr_builtins; // = pr_builtin;
int pr_numbuiltins; // = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
// for builtin function definitions see Quake Standards Group at http://www.quakesrc.org/
ebfs_builtin_t pr_ebfs_builtins[] =
{
{ 0, NULL, PF_Fixme }, // has to be first entry as it is needed for initialization in PR_LoadProgs()
{ 1, "makevectors", PF_makevectors }, // void(entity e) makevectors = #1;
{ 2, "setorigin", PF_setorigin }, // void(entity e, vector o) setorigin = #2;
{ 3, "setmodel", PF_setmodel }, // void(entity e, string m) setmodel = #3;
{ 4, "setsize", PF_setsize }, // void(entity e, vector min, vector max) setsize = #4;
// { 5, "fixme", PF_Fixme }, // void(entity e, vector min, vector max) setabssize = #5;
{ 6, "break", PF_break }, // void() break = #6;
{ 7, "random", PF_random }, // float() random = #7;
{ 8, "sound", PF_sound }, // void(entity e, float chan, string samp) sound = #8;
{ 9, "normalize", PF_normalize }, // vector(vector v) normalize = #9;
{ 10, "error", PF_error }, // void(string e) error = #10;
{ 11, "objerror", PF_objerror }, // void(string e) objerror = #11;
{ 12, "vlen", PF_vlen }, // float(vector v) vlen = #12;
{ 13, "vectoyaw", PF_vectoyaw }, // float(vector v) vectoyaw = #13;
{ 14, "spawn", PF_Spawn }, // entity() spawn = #14;
{ 15, "remove", PF_Remove }, // void(entity e) remove = #15;
{ 16, "traceline", PF_traceline }, // float(vector v1, vector v2, float tryents) traceline = #16;
{ 17, "checkclient", PF_checkclient }, // entity() clientlist = #17;
{ 18, "find", PF_Find }, // entity(entity start, .string fld, string match) find = #18;
{ 19, "precache_sound", PF_precache_sound }, // void(string s) precache_sound = #19;
{ 20, "precache_model", PF_precache_model }, // void(string s) precache_model = #20;
{ 21, "stuffcmd", PF_stuffcmd }, // void(entity client, string s)stuffcmd = #21;
{ 22, "findradius", PF_findradius }, // entity(vector org, float rad) findradius = #22;
{ 23, "bprint", PF_bprint }, // void(string s) bprint = #23;
{ 24, "sprint", PF_sprint }, // void(entity client, string s) sprint = #24;
{ 25, "dprint", PF_dprint }, // void(string s) dprint = #25;
{ 26, "ftos", PF_ftos }, // void(string s) ftos = #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -