📄 pr_cmds.c
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
#define PR_MAX_TEMPSTRING 2048 // 2001-10-25 Enhanced temp string handling by Maddes
memzone_t *zone_progstrings; // 2001-09-20 QuakeC string zone by Maddes
// 2001-10-20 Extension System by LordHavoc/Maddes start
char *pr_extensions[] =
{
// add the extension names here, syntax: "extensionname",
"TIMESCALE", // 2001-10-20 TIMESCALE extension by Tomaz/Maddes
// 2001-09-16 Quake 2 builtin functions by id/Maddes start
"DP_QC_ETOS",
"DP_QC_CHANGEPITCH",
"DP_QC_TRACETOSS",
// 2001-09-16 Quake 2 builtin functions by id/Maddes end
// 2001-11-15 DarkPlaces general builtin functions by LordHavoc start
"DP_REGISTERCVAR", // 2001-09-18 New BuiltIn Function: cvar_create() by Maddes
"DP_QC_SINCOSSQRTPOW",
"DP_QC_TRACEBOX",
"DP_QC_RANDOMVEC",
"DP_QC_MINMAXBOUND",
"DP_QC_FINDFLOAT",
"DP_QC_COPYENTITY",
"DP_SV_SETCOLOR",
"DP_QC_FINDCHAIN",
"DP_QC_FINDCHAINFLOAT",
// 2001-11-15 DarkPlaces general builtin functions by LordHavoc end
};
int pr_numextensions = sizeof(pr_extensions)/sizeof(pr_extensions[0]);
qboolean extension_find(char *name)
{
int i;
for (i=0; i < pr_numextensions; i++)
{
if (!Q_strcasecmp(pr_extensions[i], name))
return true;
}
return false;
}
/*
=================
PF_extension_find
returns true if the extension is supported by the server
float extension_find(string name)
=================
*/
void PF_extension_find (void)
{
G_FLOAT(OFS_RETURN) = extension_find(G_STRING(OFS_PARM0));
}
// 2001-10-20 Extension System by LordHavoc/Maddes end
/*
===============================================================================
BUILT-IN FUNCTIONS
===============================================================================
*/
char pr_varstring_temp[PR_MAX_TEMPSTRING]; // 2001-10-25 Enhanced temp string handling by Maddes
char *PF_VarString (int first)
{
int i;
// 2001-10-25 Enhanced temp string handling by Maddes start
/*
static char out[256];
out[0] = 0;
for (i=first ; i<pr_argc ; i++)
{
strcat (out, G_STRING((OFS_PARM0+i*3)));
}
return out;
*/
int maxlen;
char *add;
pr_varstring_temp[0] = 0;
for (i=first ; i<pr_argc ; i++)
{
maxlen = PR_MAX_TEMPSTRING - strlen(pr_varstring_temp) - 1; // -1 is EndOfString
add = G_STRING((OFS_PARM0+i*3));
if (maxlen > strlen(add))
{
strcat (pr_varstring_temp, add);
}
else
{
strncat (pr_varstring_temp, add, maxlen);
pr_varstring_temp[PR_MAX_TEMPSTRING-1] = 0;
break; // can stop here
}
}
return pr_varstring_temp;
// 2001-10-25 Enhanced temp string handling by Maddes end
}
/*
=================
PF_error
This is a TERMINAL error, which will kill off the entire server.
Dumps self.
error(value)
=================
*/
void PF_error (void)
{
char *s;
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======SERVER ERROR in %s:\n%s\n"
,pr_strings + pr_xfunction->s_name,s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
Host_Error ("Program error");
}
/*
=================
PF_objerror
Dumps out self, then an error message. The program is aborted and self is
removed, but the level can continue.
objerror(value)
=================
*/
void PF_objerror (void)
{
char *s;
edict_t *ed;
s = PF_VarString(0);
Con_Printf ("======OBJECT ERROR in %s:\n%s\n", pr_strings + pr_xfunction->s_name, s);
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
ED_Free (ed);
// Host_Error ("Program error"); // 2001-12-16 Do not stop server on objerror
}
/*
==============
PF_makevectors
Writes new values for v_forward, v_up, and v_right based on angles
makevectors(vector)
==============
*/
void PF_makevectors (void)
{
AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
}
/*
=================
PF_setorigin
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.
setorigin (entity, origin)
=================
*/
void PF_setorigin (void)
{
edict_t *e;
float *org;
e = G_EDICT(OFS_PARM0);
org = G_VECTOR(OFS_PARM1);
VectorCopy (org, e->v.origin);
SV_LinkEdict (e, false);
}
void SetMinMaxSize (edict_t *e, float *min, float *max, qboolean rotate)
{
float *angles;
vec3_t rmin, rmax;
float bounds[2][3];
float xvector[2], yvector[2];
float a;
vec3_t base, transformed;
int i, j, k, l;
for (i=0 ; i<3 ; i++)
if (min[i] > max[i])
PR_RunError ("backwards mins/maxs");
rotate = false; // FIXME: implement rotation properly again
if (!rotate)
{
VectorCopy (min, rmin);
VectorCopy (max, rmax);
}
else
{
// find min / max for rotations
angles = e->v.angles;
a = angles[1]/180 * M_PI;
xvector[0] = cos(a);
xvector[1] = sin(a);
yvector[0] = -sin(a);
yvector[1] = cos(a);
VectorCopy (min, bounds[0]);
VectorCopy (max, bounds[1]);
rmin[0] = rmin[1] = rmin[2] = 9999;
rmax[0] = rmax[1] = rmax[2] = -9999;
for (i=0 ; i<= 1 ; i++)
{
base[0] = bounds[i][0];
for (j=0 ; j<= 1 ; j++)
{
base[1] = bounds[j][1];
for (k=0 ; k<= 1 ; k++)
{
base[2] = bounds[k][2];
// transform the point
transformed[0] = xvector[0]*base[0] + yvector[0]*base[1];
transformed[1] = xvector[1]*base[0] + yvector[1]*base[1];
transformed[2] = base[2];
for (l=0 ; l<3 ; l++)
{
if (transformed[l] < rmin[l])
rmin[l] = transformed[l];
if (transformed[l] > rmax[l])
rmax[l] = transformed[l];
}
}
}
}
}
// set derived values
VectorCopy (rmin, e->v.mins);
VectorCopy (rmax, e->v.maxs);
VectorSubtract (max, min, e->v.size);
SV_LinkEdict (e, false);
}
/*
=================
PF_setsize
the size box is rotated by the current angle
setsize (entity, minvector, maxvector)
=================
*/
void PF_setsize (void)
{
edict_t *e;
float *min, *max;
e = G_EDICT(OFS_PARM0);
min = G_VECTOR(OFS_PARM1);
max = G_VECTOR(OFS_PARM2);
SetMinMaxSize (e, min, max, false);
}
/*
=================
PF_setmodel
setmodel(entity, model)
=================
*/
void PF_setmodel (void)
{
edict_t *e;
char *m, **check;
model_t *mod;
int i;
e = G_EDICT(OFS_PARM0);
m = G_STRING(OFS_PARM1);
// check to see if model was properly precached
for (i=0, check = sv.model_precache ; *check ; i++, check++)
if (!strcmp(*check, m))
break;
if (!*check)
PR_RunError ("no precache: %s\n", m);
e->v.model = m - pr_strings;
e->v.modelindex = i; //SV_ModelIndex (m);
mod = sv.models[(int)e->v.modelindex]; // Mod_ForName (m, true);
if (mod)
SetMinMaxSize (e, mod->mins, mod->maxs, true);
else
SetMinMaxSize (e, vec3_origin, vec3_origin, true);
}
/*
=================
PF_bprint
broadcast print to everyone on server
bprint(value)
=================
*/
void PF_bprint (void)
{
char *s;
s = PF_VarString(0);
SV_BroadcastPrintf ("%s", s);
}
/*
=================
PF_sprint
single print to a specific client
sprint(clientent, value)
=================
*/
void PF_sprint (void)
{
char *s;
client_t *client;
int entnum;
entnum = G_EDICTNUM(OFS_PARM0);
s = PF_VarString(1);
if (entnum < 1 || entnum > svs.maxclients)
{
Con_Printf ("tried to sprint to a non-client\n");
return;
}
client = &svs.clients[entnum-1];
MSG_WriteChar (&client->message,svc_print);
MSG_WriteString (&client->message, s );
}
/*
=================
PF_centerprint
single print to a specific client
centerprint(clientent, value)
=================
*/
void PF_centerprint (void)
{
char *s;
client_t *client;
int entnum;
entnum = G_EDICTNUM(OFS_PARM0);
s = PF_VarString(1);
if (entnum < 1 || entnum > svs.maxclients)
{
Con_Printf ("tried to sprint to a non-client\n");
return;
}
client = &svs.clients[entnum-1];
MSG_WriteChar (&client->message,svc_centerprint);
MSG_WriteString (&client->message, s );
}
/*
=================
PF_normalize
vector normalize(vector)
=================
*/
void PF_normalize (void)
{
float *value1;
vec3_t newvalue;
float new;
value1 = G_VECTOR(OFS_PARM0);
new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
new = sqrt(new);
if (new == 0)
newvalue[0] = newvalue[1] = newvalue[2] = 0;
else
{
new = 1/new;
newvalue[0] = value1[0] * new;
newvalue[1] = value1[1] * new;
newvalue[2] = value1[2] * new;
}
VectorCopy (newvalue, G_VECTOR(OFS_RETURN));
}
/*
=================
PF_vlen
scalar vlen(vector)
=================
*/
void PF_vlen (void)
{
float *value1;
float new;
value1 = G_VECTOR(OFS_PARM0);
new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
new = sqrt(new);
G_FLOAT(OFS_RETURN) = new;
}
/*
=================
PF_vectoyaw
float vectoyaw(vector)
=================
*/
void PF_vectoyaw (void)
{
float *value1;
float yaw;
value1 = G_VECTOR(OFS_PARM0);
if (value1[1] == 0 && value1[0] == 0)
yaw = 0;
else
{
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
}
G_FLOAT(OFS_RETURN) = yaw;
}
/*
=================
PF_vectoangles
vector vectoangles(vector)
=================
*/
void PF_vectoangles (void)
{
float *value1;
float forward;
float yaw, pitch;
value1 = G_VECTOR(OFS_PARM0);
if (value1[1] == 0 && value1[0] == 0)
{
yaw = 0;
if (value1[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
G_FLOAT(OFS_RETURN+0) = pitch;
G_FLOAT(OFS_RETURN+1) = yaw;
G_FLOAT(OFS_RETURN+2) = 0;
}
/*
=================
PF_Random
Returns a number from 0>= num <= 1
random()
=================
*/
void PF_random (void)
{
float num;
num = (rand ()&0x7fff) / ((float)0x7fff);
G_FLOAT(OFS_RETURN) = num;
}
/*
=================
PF_particle
particle(origin, color, count)
=================
*/
void PF_particle (void)
{
float *org, *dir;
float color;
float count;
org = G_VECTOR(OFS_PARM0);
dir = G_VECTOR(OFS_PARM1);
color = G_FLOAT(OFS_PARM2);
count = G_FLOAT(OFS_PARM3);
SV_StartParticle (org, dir, color, count);
}
/*
=================
PF_ambientsound
=================
*/
void PF_ambientsound (void)
{
char **check;
char *samp;
float *pos;
float vol, attenuation;
int i, soundnum;
pos = G_VECTOR (OFS_PARM0);
samp = G_STRING(OFS_PARM1);
vol = G_FLOAT(OFS_PARM2);
attenuation = G_FLOAT(OFS_PARM3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -