pandr's pr_* merge..

This commit is contained in:
Joseph Carter 2000-01-03 04:45:54 +00:00
parent d5217418ec
commit d0674e837c
9 changed files with 470 additions and 3855 deletions

View file

@ -18,6 +18,7 @@ QW/Q1 tree merging:
Nelson J. Rush <chesterrr@att.net>
Eric Windisch <windisch@nni.com>
Joseph Carter <knghtbrd@debian.org>
Peter Andreasen <pandr@pandr.dk>
Autoconf support:
Loring Holden <lsh@cs.brown.edu>

View file

@ -17,8 +17,11 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "qwsvdef.h"
#ifdef QUAKEWORLD
# include "qwsvdef.h"
#else
# include "quakedef.h"
#endif
#define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
#define RETURN_STRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(s))
@ -65,7 +68,11 @@ void PF_error (void)
ed = PROG_TO_EDICT(pr_global_struct->self);
ED_Print (ed);
#ifdef QUAKEWORLD
SV_Error ("Program error");
#else
Host_Error ("Program error");
#endif
}
/*
@ -89,7 +96,11 @@ void PF_objerror (void)
ED_Print (ed);
ED_Free (ed);
#ifdef QUAKEWORLD
SV_Error ("Program error");
#else
Host_Error ("Program error");
#endif
}
@ -111,8 +122,7 @@ void PF_makevectors (void)
=================
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 s
pawned, and then only if it is teleported.
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)
=================
@ -128,6 +138,86 @@ void PF_setorigin (void)
SV_LinkEdict (e, false);
}
/*
===============
QUAKEWORLD: Note, the function SetMinMaxSize is only used for UQUAKE
===============
*/
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);
}
/*
=================
@ -146,10 +236,14 @@ void PF_setsize (void)
e = G_EDICT(OFS_PARM0);
min = G_VECTOR(OFS_PARM1);
max = G_VECTOR(OFS_PARM2);
#ifdef QUAKEWORLD
VectorCopy (min, e->v.mins);
VectorCopy (max, e->v.maxs);
VectorSubtract (max, min, e->v.size);
SV_LinkEdict (e, false);
#else
SetMinMaxSize (e, min, max, false);
#endif
}
@ -182,6 +276,7 @@ void PF_setmodel (void)
e->v.model = PR_SetString(m);
e->v.modelindex = i;
#ifdef QUAKEWORLD
// if it is an inline model, get the size information for it
if (m[0] == '*')
{
@ -191,6 +286,14 @@ void PF_setmodel (void)
VectorSubtract (mod->maxs, mod->mins, e->v.size);
SV_LinkEdict (e, false);
}
#else
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);
#endif
}
@ -208,10 +311,16 @@ void PF_bprint (void)
char *s;
int level;
#ifdef QUAKEWORLD
level = G_FLOAT(OFS_PARM0);
s = PF_VarString(1);
SV_BroadcastPrintf (level, "%s", s);
#else
s = PF_VarString(0);
SV_BroadcastPrintf ("%s", s);
#endif
}
/*
@ -231,11 +340,20 @@ void PF_sprint (void)
int level;
entnum = G_EDICTNUM(OFS_PARM0);
#ifdef QUAKEWORLD
level = G_FLOAT(OFS_PARM1);
s = PF_VarString(2);
#else
s = PF_VarString(1);
#endif
#ifdef QUAKEWORLD
if (entnum < 1 || entnum > MAX_CLIENTS)
#else
if (entnum < 1 || entnum > svs.maxclients)
#endif
{
Con_Printf ("tried to sprint to a non-client\n");
return;
@ -243,7 +361,12 @@ void PF_sprint (void)
client = &svs.clients[entnum-1];
#ifdef QUAKEWORLD
SV_ClientPrintf (client, level, "%s", s);
#else
MSG_WriteChar (&client->message,svc_print);
MSG_WriteString (&client->message, s );
#endif
}
@ -265,7 +388,11 @@ void PF_centerprint (void)
entnum = G_EDICTNUM(OFS_PARM0);
s = PF_VarString(1);
#ifdef QUAKEWORLD
if (entnum < 1 || entnum > MAX_CLIENTS)
#else
if (entnum < 1 || entnum > svs.maxclients)
#endif
{
Con_Printf ("tried to sprint to a non-client\n");
return;
@ -273,8 +400,13 @@ void PF_centerprint (void)
cl = &svs.clients[entnum-1];
#ifdef QUAKEWORLD
ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
ClientReliableWrite_String (cl, s);
#else
MSG_WriteChar (&cl->message,svc_centerprint);
MSG_WriteString (&cl->message, s );
#endif
}
@ -414,6 +546,27 @@ void PF_random (void)
G_FLOAT(OFS_RETURN) = num;
}
#ifndef QUAKEWORLD /* !QUAKEWORLD */
/*
=================
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);
}
#endif
/*
=================
@ -486,6 +639,17 @@ void PF_sound (void)
sample = G_STRING(OFS_PARM2);
volume = G_FLOAT(OFS_PARM3) * 255;
attenuation = G_FLOAT(OFS_PARM4);
#ifndef QUAKEWORLD
if (volume < 0 || volume > 255)
Sys_Error ("SV_StartSound: volume = %i", volume);
if (attenuation < 0 || attenuation > 4)
Sys_Error ("SV_StartSound: attenuation = %f", attenuation);
if (channel < 0 || channel > 7)
Sys_Error ("SV_StartSound: channel = %i", channel);
#endif
SV_StartSound (entity, channel, sample, volume, attenuation);
}
@ -573,6 +737,8 @@ int PF_newcheckclient (int check)
if (check < 1)
check = 1;
#ifdef QUAKEWORLD
if (check > MAX_CLIENTS)
check = MAX_CLIENTS;
@ -580,10 +746,23 @@ int PF_newcheckclient (int check)
i = 1;
else
i = check + 1;
#else
if (check > svs.maxclients)
check = svs.maxclients;
if (check == svs.maxclients)
i = 1;
else
i = check + 1;
#endif
for ( ; ; i++)
{
#ifdef QUAKEWORLD
if (i == MAX_CLIENTS+1)
#else
if (i == svs.maxclients+1)
#endif
i = 1;
ent = EDICT_NUM(i);
@ -686,12 +865,17 @@ void PF_stuffcmd (void)
client_t *cl;
entnum = G_EDICTNUM(OFS_PARM0);
#ifdef QUAKEWORLD
if (entnum < 1 || entnum > MAX_CLIENTS)
#else
if (entnum < 1 || entnum > svs.maxclients)
#endif
PR_RunError ("Parm 0 not a client");
str = G_STRING(OFS_PARM1);
cl = &svs.clients[entnum-1];
#if QUAKEWORLD
if (strcmp(str, "disconnect\n") == 0) {
// so long and thanks for all the fish
cl->drop = true;
@ -700,6 +884,12 @@ void PF_stuffcmd (void)
ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(str));
ClientReliableWrite_String (cl, str);
#else
cl = host_client;
host_client = &svs.clients[entnum-1];
Host_ClientCommands ("%s", str);
host_client = cl;
#endif
}
/*
@ -801,7 +991,11 @@ PF_dprint
*/
void PF_dprint (void)
{
#ifdef QUAKEWORLD
Con_Printf ("%s",PF_VarString(0));
#else
Con_DPrintf ("%s",PF_VarString(0));
#endif
}
char pr_string_temp[128];
@ -932,6 +1126,9 @@ void PF_precache_model (void)
if (!sv.model_precache[i])
{
sv.model_precache[i] = s;
#ifndef QUAKEWORLD
sv.models[i] = Mod_ForName (s, true);
#endif
return;
}
if (!strcmp(sv.model_precache[i], s))
@ -1060,6 +1257,7 @@ void PF_lightstyle (void)
if (sv.state != ss_active)
return;
#ifdef QUAKEWORLD
for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
if ( client->state == cs_spawned )
{
@ -1067,6 +1265,15 @@ void PF_lightstyle (void)
ClientReliableWrite_Char (client, style);
ClientReliableWrite_String (client, val);
}
#else
for (j=0, client = svs.clients ; j<svs.maxclients ; j++, client++)
if (client->active || client->spawned)
{
MSG_WriteChar (&client->message, svc_lightstyle);
MSG_WriteChar (&client->message,style);
MSG_WriteString (&client->message, val);
}
#endif
}
void PF_rint (void)
@ -1154,8 +1361,11 @@ Pick a vector for the player to shoot along
vector aim(entity, missilespeed)
=============
*/
//cvar_t sv_aim = {"sv_aim", "0.93"};
#ifdef QUAKEWORLD
cvar_t sv_aim = {"sv_aim", "2"};
#else
cvar_t sv_aim = {"sv_aim", "0.93"};
#endif
void PF_aim (void)
{
edict_t *ent, *check, *bestent;
@ -1172,6 +1382,7 @@ void PF_aim (void)
VectorCopy (ent->v.origin, start);
start[2] += 20;
#ifdef QUAKEWORLD
// noaim option
i = NUM_FOR_EDICT(ent);
if (i>0 && i<MAX_CLIENTS)
@ -1183,6 +1394,7 @@ void PF_aim (void)
return;
}
}
#endif
// try sending a trace straight
VectorCopy (pr_global_struct->v_forward, dir);
@ -1301,9 +1513,9 @@ MESSAGE WRITING
sizebuf_t *WriteDest (void)
{
// int entnum;
int entnum;
int dest;
// edict_t *ent;
edict_t *ent;
dest = G_FLOAT(OFS_PARM0);
switch (dest)
@ -1312,25 +1524,29 @@ sizebuf_t *WriteDest (void)
return &sv.datagram;
case MSG_ONE:
#ifdef QUAKEWORLD
SV_Error("Shouldn't be at MSG_ONE");
#if 0
return &svs.clients[entnum-1].netchan.message;
#else
ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
entnum = NUM_FOR_EDICT(ent);
if (entnum < 1 || entnum > MAX_CLIENTS)
if (entnum < 1 || entnum > svs.maxclients)
PR_RunError ("WriteDest: not a client");
return &svs.clients[entnum-1].netchan.message;
return &svs.clients[entnum-1].message;
#endif
case MSG_ALL:
return &sv.reliable_datagram;
case MSG_INIT:
#ifdef QUAKEWORLD
if (sv.state != ss_loading)
PR_RunError ("PF_Write_*: MSG_INIT can only be written in spawn functions");
return &sv.signon;
case MSG_MULTICAST:
return &sv.multicast;
#endif
default:
PR_RunError ("WriteDest: bad destination");
@ -1340,6 +1556,7 @@ sizebuf_t *WriteDest (void)
return NULL;
}
#ifdef QUAKEWORLD
static client_t *Write_GetClient(void)
{
int entnum;
@ -1351,86 +1568,103 @@ static client_t *Write_GetClient(void)
PR_RunError ("WriteDest: not a client");
return &svs.clients[entnum-1];
}
#endif
void PF_WriteByte (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 1);
ClientReliableWrite_Byte(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteChar (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 1);
ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteShort (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 2);
ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteLong (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 4);
ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteAngle (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 1);
ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteCoord (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 2);
ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1));
} else
#endif
MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
}
void PF_WriteString (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 1+strlen(G_STRING(OFS_PARM1)));
ClientReliableWrite_String(cl, G_STRING(OFS_PARM1));
} else
#endif
MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
}
void PF_WriteEntity (void)
{
#ifdef QUAKEWORLD
if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
client_t *cl = Write_GetClient();
ClientReliableCheckBlock(cl, 2);
ClientReliableWrite_Short(cl, G_EDICTNUM(OFS_PARM1));
} else
#endif
MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
}
@ -1477,7 +1711,11 @@ void PF_setspawnparms (void)
ent = G_EDICT(OFS_PARM0);
i = NUM_FOR_EDICT(ent);
#ifdef QUAKEWORLD
if (i < 1 || i > MAX_CLIENTS)
#else
if (i < 1 || i > svs.maxclients)
#endif
PR_RunError ("Entity is not a client");
// copy spawn parms out of the client_t
@ -1498,15 +1736,27 @@ void PF_changelevel (void)
static int last_spawncount;
// make sure we don't issue two changelevels
#ifdef QUAKEWORLD
if (svs.spawncount == last_spawncount)
return;
last_spawncount = svs.spawncount;
#else
if (svs.changelevel_issued)
return;
svs.changelevel_issued = true;
#endif
s = G_STRING(OFS_PARM0);
#ifdef QUAKEWORLD
Cbuf_AddText (va("map %s\n",s));
#else
Cbuf_AddText (va("changelevel %s\n",s));
#endif
}
#ifdef QUAKEWORLD
/*
==============
PF_logfrag
@ -1613,6 +1863,7 @@ void PF_multicast (void)
SV_Multicast (o, to);
}
#endif /* QUAKEWORLD */
void PF_Fixme (void)
{
@ -1671,7 +1922,11 @@ PF_aim,
PF_cvar,
PF_localcmd,
PF_nextent,
#ifdef QUAKEWORLD
PF_Fixme,
#else
PF_particle,
#endif
PF_changeyaw,
PF_Fixme,
PF_vectoangles,
@ -1709,13 +1964,16 @@ PF_precache_model,
PF_precache_sound, // precache_sound2 is different only for qcc
PF_precache_file,
PF_setspawnparms,
PF_setspawnparms
#ifdef QUAKEWORLD
,
PF_logfrag,
PF_infokey,
PF_stof,
PF_multicast
#endif
};
builtin_t *pr_builtins = pr_builtin;

View file

@ -19,7 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// sv_edict.c -- entity dictionary
#ifdef QUAKEWORLD
#include "qwsvdef.h"
#else
#include "quakedef.h"
#endif
dprograms_t *progs;
dfunction_t *pr_functions;
@ -31,11 +35,30 @@ globalvars_t *pr_global_struct;
float *pr_globals; // same as pr_global_struct
int pr_edict_size; // in bytes
#ifdef QUAKEWORLD
int type_size[8] = {1,sizeof(void *)/4,1,3,1,1,sizeof(void *)/4,sizeof(void *)/4};
#else
unsigned short pr_crc;
int type_size[8] = {1,sizeof(string_t)/4,1,3,1,1,sizeof(func_t)/4,sizeof(void *)/4};
#endif
ddef_t *ED_FieldAtOfs (int ofs);
qboolean ED_ParseEpair (void *base, ddef_t *key, char *s);
#ifndef QUAKEWORLD
cvar_t nomonsters = {"nomonsters", "0"};
cvar_t gamecfg = {"gamecfg", "0"};
cvar_t scratch1 = {"scratch1", "0"};
cvar_t scratch2 = {"scratch2", "0"};
cvar_t scratch3 = {"scratch3", "0"};
cvar_t scratch4 = {"scratch4", "0"};
cvar_t savedgamecfg = {"savedgamecfg", "0", true};
cvar_t saved1 = {"saved1", "0", true};
cvar_t saved2 = {"saved2", "0", true};
cvar_t saved3 = {"saved3", "0", true};
cvar_t saved4 = {"saved4", "0", true};
#endif
#define MAX_FIELD_LEN 64
#define GEFV_CACHESIZE 2
@ -46,9 +69,11 @@ typedef struct {
static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}};
#ifdef QUAKEWORLD
func_t SpectatorConnect;
func_t SpectatorThink;
func_t SpectatorDisconnect;
#endif
/*
@ -80,7 +105,11 @@ edict_t *ED_Alloc (void)
int i;
edict_t *e;
#ifdef QUAKEWORLD
for ( i=MAX_CLIENTS+1 ; i<sv.num_edicts ; i++)
#else
for ( i=svs.maxclients+1 ; i<sv.num_edicts ; i++)
#endif
{
e = EDICT_NUM(i);
// the first couple seconds of server time can involve a lot of
@ -93,6 +122,7 @@ edict_t *ED_Alloc (void)
}
if (i == MAX_EDICTS)
#ifdef QUAKEWORLD
{
Con_Printf ("WARNING: ED_Alloc: no free edicts\n");
i--; // step on whatever is the last edict
@ -101,6 +131,12 @@ edict_t *ED_Alloc (void)
}
else
sv.num_edicts++;
#else
Sys_Error ("ED_Alloc: no free edicts");
sv.num_edicts++;
#endif
e = EDICT_NUM(i);
ED_ClearEdict (e);
@ -551,7 +587,15 @@ void ED_PrintEdict_f (void)
int i;
i = Q_atoi (Cmd_Argv(1));
#ifdef QUAKEWORLD
Con_Printf ("\n EDICT %i:\n",i);
#else
if (i >= sv.num_edicts)
{
Con_Printf("Bad edict number\n");
return;
}
#endif
ED_PrintNum (i);
}
@ -650,17 +694,29 @@ void ED_ParseGlobals (char *data)
if (com_token[0] == '}')
break;
if (!data)
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: EOF without closing brace");
#else
Sys_Error ("ED_ParseEntity: EOF without closing brace");
#endif
strcpy (keyname, com_token);
// parse value
data = COM_Parse (data);
if (!data)
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: EOF without closing brace");
#else
Sys_Error ("ED_ParseEntity: EOF without closing brace");
#endif
if (com_token[0] == '}')
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: closing brace without data");
#else
Sys_Error ("ED_ParseEntity: closing brace without data");
#endif
key = ED_FindGlobal (keyname);
if (!key)
@ -670,7 +726,11 @@ void ED_ParseGlobals (char *data)
}
if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
#ifdef QUAKEWORLD
SV_Error ("ED_ParseGlobals: parse error");
#else
Host_Error ("ED_ParseGlobals: parse error");
#endif
}
}
@ -797,6 +857,7 @@ char *ED_ParseEdict (char *data, edict_t *ent)
qboolean anglehack;
qboolean init;
char keyname[256];
int n;
init = false;
@ -812,7 +873,11 @@ char *ED_ParseEdict (char *data, edict_t *ent)
if (com_token[0] == '}')
break;
if (!data)
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: EOF without closing brace");
#else
Sys_Error ("ED_ParseEntity: EOF without closing brace");
#endif
// anglehack is to allow QuakeEd to write single scalar angles
// and allow them to be turned into vectors. (FIXME...)
@ -829,14 +894,32 @@ if (!strcmp(com_token, "light"))
strcpy (com_token, "light_lev"); // hack for single light def
strcpy (keyname, com_token);
#ifndef QUAKEWORLD
// another hack to fix heynames with trailing spaces
n = strlen(keyname);
while (n && keyname[n-1] == ' ')
{
keyname[n-1] = 0;
n--;
}
#endif
// parse value
data = COM_Parse (data);
if (!data)
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: EOF without closing brace");
#else
Sys_Error ("ED_ParseEntity: EOF without closing brace");
#endif
if (com_token[0] == '}')
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEntity: closing brace without data");
#else
Sys_Error ("ED_ParseEntity: closing brace without data");
#endif
init = true;
@ -860,7 +943,11 @@ sprintf (com_token, "0 %s 0", temp);
}
if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
#ifdef QUAKEWORLD
SV_Error ("ED_ParseEdict: parse error");
#else
Host_Error ("ED_ParseEdict: parse error");
#endif
}
if (!init)
@ -903,7 +990,11 @@ void ED_LoadFromFile (char *data)
if (!data)
break;
if (com_token[0] != '{')
#ifdef QUAKEWORLD
SV_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
#else
Sys_Error ("ED_LoadFromFile: found %s when expecting {",com_token);
#endif
if (!ent)
ent = EDICT_NUM(0);
@ -912,12 +1003,27 @@ void ED_LoadFromFile (char *data)
data = ED_ParseEdict (data, ent);
// remove things from different skill levels or deathmatch
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
#ifndef QUAKEWORLD
if (deathmatch.value)
{
#endif
if (((int)ent->v.spawnflags & SPAWNFLAG_NOT_DEATHMATCH))
{
ED_Free (ent);
inhibit++;
continue;
}
#ifndef QUAKEWORLD
}
else if ((current_skill == 0 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_EASY))
|| (current_skill == 1 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_MEDIUM))
|| (current_skill >= 2 && ((int)ent->v.spawnflags & SPAWNFLAG_NOT_HARD)) )
{
ED_Free (ent);
inhibit++;
continue;
}
#endif
//
// immediately call spawn function
@ -943,7 +1049,9 @@ void ED_LoadFromFile (char *data)
pr_global_struct->self = EDICT_TO_PROG(ent);
PR_ExecuteProgram (func - pr_functions);
#ifdef QUAKEWORLD
SV_FlushSignon();
#endif
}
Con_DPrintf ("%i entities inhibited\n", inhibit);
@ -965,25 +1073,48 @@ void PR_LoadProgs (void)
for (i=0 ; i<GEFV_CACHESIZE ; i++)
gefvCache[i].field[0] = 0;
#ifndef QUAKEWORLD
CRC_Init (&pr_crc);
#endif
#ifdef QUAKEWORLD
progs = (dprograms_t *)COM_LoadHunkFile ("qwprogs.dat");
if (!progs)
#endif
progs = (dprograms_t *)COM_LoadHunkFile ("progs.dat");
if (!progs)
#ifdef QUAKEWORLD
SV_Error ("PR_LoadProgs: couldn't load progs.dat");
#else
Sys_Error ("PR_LoadProgs: couldn't load progs.dat");
#endif
Con_DPrintf ("Programs occupy %iK.\n", com_filesize/1024);
#ifdef QUAKEWORLD
// add prog crc to the serverinfo
sprintf (num, "%i", CRC_Block ((byte *)progs, com_filesize));
Info_SetValueForStarKey (svs.info, "*progs", num, MAX_SERVERINFO_STRING);
#else
for (i=0 ; i<com_filesize ; i++)
CRC_ProcessByte (&pr_crc, ((byte *)progs)[i]);
#endif
// byte swap the header
for (i=0 ; i<sizeof(*progs)/4 ; i++)
((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
if (progs->version != PROG_VERSION)
#ifdef QUAKEWORLD
SV_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
#else
Sys_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION);
#endif
if (progs->crc != PROGHEADER_CRC)
#ifdef QUAKEWORLD
SV_Error ("You must have the progs.dat from QuakeWorld installed");
#else
Sys_Error ("progs.dat system vars have been modified, progdefs.h is out of date");
#endif
pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
pr_strings = (char *)progs + progs->ofs_strings;
@ -991,7 +1122,9 @@ void PR_LoadProgs (void)
pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
#ifdef QUAKEWORLD
num_prstr = 0;
#endif
pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals);
pr_globals = (float *)pr_global_struct;
@ -1028,7 +1161,11 @@ void PR_LoadProgs (void)
{
pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
if (pr_fielddefs[i].type & DEF_SAVEGLOBAL)
#ifdef QUAKEWORLD
SV_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
#else
Sys_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL");
#endif
pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs);
pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
}
@ -1036,6 +1173,7 @@ void PR_LoadProgs (void)
for (i=0 ; i<progs->numglobals ; i++)
((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
#ifdef QUAKEWORLD
// Zoid, find the spectator functions
SpectatorConnect = SpectatorThink = SpectatorDisconnect = 0;
@ -1045,6 +1183,7 @@ void PR_LoadProgs (void)
SpectatorThink = (func_t)(f - pr_functions);
if ((f = ED_FindFunction ("SpectatorDisconnect")) != NULL)
SpectatorDisconnect = (func_t)(f - pr_functions);
#endif
}
@ -1059,6 +1198,19 @@ void PR_Init (void)
Cmd_AddCommand ("edicts", ED_PrintEdicts);
Cmd_AddCommand ("edictcount", ED_Count);
Cmd_AddCommand ("profile", PR_Profile_f);
#ifndef QUAKEWORLD
Cvar_RegisterVariable (&nomonsters);
Cvar_RegisterVariable (&gamecfg);
Cvar_RegisterVariable (&scratch1);
Cvar_RegisterVariable (&scratch2);
Cvar_RegisterVariable (&scratch3);
Cvar_RegisterVariable (&scratch4);
Cvar_RegisterVariable (&savedgamecfg);
Cvar_RegisterVariable (&saved1);
Cvar_RegisterVariable (&saved2);
Cvar_RegisterVariable (&saved3);
Cvar_RegisterVariable (&saved4);
#endif
}
@ -1066,7 +1218,11 @@ void PR_Init (void)
edict_t *EDICT_NUM(int n)
{
if (n < 0 || n >= MAX_EDICTS)
#ifdef QUAKEWORLD
SV_Error ("EDICT_NUM: bad number %i", n);
#else
Sys_Error ("EDICT_NUM: bad number %i", n);
#endif
return (edict_t *)((byte *)sv.edicts+ (n)*pr_edict_size);
}
@ -1078,7 +1234,11 @@ int NUM_FOR_EDICT(edict_t *e)
b = b / pr_edict_size;
if (b < 0 || b >= sv.num_edicts)
#ifdef QUAKEWORLD
SV_Error ("NUM_FOR_EDICT: bad pointer");
#else
Sys_Error ("NUM_FOR_EDICT: bad pointer");
#endif
return b;
}

View file

@ -18,7 +18,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef QUAKEWORLD
#include "qwsvdef.h"
#else
#include "quakedef.h"
#endif
/*
@ -271,9 +275,13 @@ void PR_RunError (char *error, ...)
PR_StackTrace ();
Con_Printf ("%s\n", string);
pr_depth = 0; // dump the stack so SV_Error can shutdown functions
pr_depth = 0; // dump the stack so {SV|Host}_Error can shutdown functions
#ifdef QUAKEWORLD
SV_Error ("Program error");
#else
Host_Error ("Program error");
#endif
}
/*
@ -335,7 +343,11 @@ int PR_LeaveFunction (void)
int i, c;
if (pr_depth <= 0)
#ifdef QUAKEWORLD
SV_Error ("prog stack underflow");
#else
Sys_Error ("prog stack underflow");
#endif
// restore locals from the stack
c = pr_xfunction->locals;
@ -374,7 +386,11 @@ void PR_ExecuteProgram (func_t fnum)
{
if (pr_global_struct->self)
ED_Print (PROG_TO_EDICT(pr_global_struct->self));
#ifdef QUAKEWORLD
SV_Error ("PR_ExecuteProgram: NULL function");
#else
Host_Error ("PR_ExecuteProgram: NULL function");
#endif
}
f = &pr_functions[fnum];
@ -648,7 +664,16 @@ while (1)
case OP_STATE:
ed = PROG_TO_EDICT(pr_global_struct->self);
#ifdef QUAKEWORLD
ed->v.nextthink = pr_global_struct->time + 0.1;
#else
# ifdef FPS_20
ed->v.nextthink = pr_global_struct->time + 0.05;
# else
ed->v.nextthink = pr_global_struct->time + 0.1;
# endif
#endif
if (a->_float != ed->v.frame)
{
ed->v.frame = a->_float;
@ -665,15 +690,22 @@ while (1)
/*----------------------*/
#ifdef QUAKEWORLD
char *pr_strtbl[MAX_PRSTR];
int num_prstr;
#endif
char *PR_GetString(int num)
{
#ifdef QUAKEWORLD
if (num < 0) {
//Con_DPrintf("GET:%d == %s\n", num, pr_strtbl[-num]);
return pr_strtbl[-num];
}
#endif
return pr_strings + num;
}
@ -681,6 +713,7 @@ int PR_SetString(char *s)
{
int i;
#ifdef QUAKEWORLD
if (s - pr_strings < 0) {
for (i = 0; i <= num_prstr; i++)
if (pr_strtbl[i] == s)
@ -694,6 +727,7 @@ int PR_SetString(char *s)
//Con_DPrintf("SET:%d == %s\n", -num_prstr, s);
return -num_prstr;
}
#endif
return (int)(s - pr_strings);
}

View file

@ -123,9 +123,13 @@ extern qboolean pr_trace;
extern dfunction_t *pr_xfunction;
extern int pr_xstatement;
#ifdef QUAKEWORLD
extern func_t SpectatorConnect;
extern func_t SpectatorThink;
extern func_t SpectatorDisconnect;
#else
extern unsigned short pr_crc;
#endif
void PR_RunError (char *error, ...);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,668 +0,0 @@
/*
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"
/*
*/
typedef struct
{
int s;
dfunction_t *f;
} prstack_t;
#define MAX_STACK_DEPTH 32
prstack_t pr_stack[MAX_STACK_DEPTH];
int pr_depth;
#define LOCALSTACK_SIZE 2048
int localstack[LOCALSTACK_SIZE];
int localstack_used;
qboolean pr_trace;
dfunction_t *pr_xfunction;
int pr_xstatement;
int pr_argc;
char *pr_opnames[] =
{
"DONE",
"MUL_F",
"MUL_V",
"MUL_FV",
"MUL_VF",
"DIV",
"ADD_F",
"ADD_V",
"SUB_F",
"SUB_V",
"EQ_F",
"EQ_V",
"EQ_S",
"EQ_E",
"EQ_FNC",
"NE_F",
"NE_V",
"NE_S",
"NE_E",
"NE_FNC",
"LE",
"GE",
"LT",
"GT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"INDIRECT",
"ADDRESS",
"STORE_F",
"STORE_V",
"STORE_S",
"STORE_ENT",
"STORE_FLD",
"STORE_FNC",
"STOREP_F",
"STOREP_V",
"STOREP_S",
"STOREP_ENT",
"STOREP_FLD",
"STOREP_FNC",
"RETURN",
"NOT_F",
"NOT_V",
"NOT_S",
"NOT_ENT",
"NOT_FNC",
"IF",
"IFNOT",
"CALL0",
"CALL1",
"CALL2",
"CALL3",
"CALL4",
"CALL5",
"CALL6",
"CALL7",
"CALL8",
"STATE",
"GOTO",
"AND",
"OR",
"BITAND",
"BITOR"
};
char *PR_GlobalString (int ofs);
char *PR_GlobalStringNoContents (int ofs);
//=============================================================================
/*
=================
PR_PrintStatement
=================
*/
void PR_PrintStatement (dstatement_t *s)
{
int i;
if ( (unsigned)s->op < sizeof(pr_opnames)/sizeof(pr_opnames[0]))
{
Con_Printf ("%s ", pr_opnames[s->op]);
i = strlen(pr_opnames[s->op]);
for ( ; i<10 ; i++)
Con_Printf (" ");
}
if (s->op == OP_IF || s->op == OP_IFNOT)
Con_Printf ("%sbranch %i",PR_GlobalString(s->a),s->b);
else if (s->op == OP_GOTO)
{
Con_Printf ("branch %i",s->a);
}
else if ( (unsigned)(s->op - OP_STORE_F) < 6)
{
Con_Printf ("%s",PR_GlobalString(s->a));
Con_Printf ("%s", PR_GlobalStringNoContents(s->b));
}
else
{
if (s->a)
Con_Printf ("%s",PR_GlobalString(s->a));
if (s->b)
Con_Printf ("%s",PR_GlobalString(s->b));
if (s->c)
Con_Printf ("%s", PR_GlobalStringNoContents(s->c));
}
Con_Printf ("\n");
}
/*
============
PR_StackTrace
============
*/
void PR_StackTrace (void)
{
dfunction_t *f;
int i;
if (pr_depth == 0)
{
Con_Printf ("<NO STACK>\n");
return;
}
pr_stack[pr_depth].f = pr_xfunction;
for (i=pr_depth ; i>=0 ; i--)
{
f = pr_stack[i].f;
if (!f)
{
Con_Printf ("<NO FUNCTION>\n");
}
else
Con_Printf ("%12s : %s\n", pr_strings + f->s_file, pr_strings + f->s_name);
}
}
/*
============
PR_Profile_f
============
*/
void PR_Profile_f (void)
{
dfunction_t *f, *best;
int max;
int num;
int i;
num = 0;
do
{
max = 0;
best = NULL;
for (i=0 ; i<progs->numfunctions ; i++)
{
f = &pr_functions[i];
if (f->profile > max)
{
max = f->profile;
best = f;
}
}
if (best)
{
if (num < 10)
Con_Printf ("%7i %s\n", best->profile, pr_strings+best->s_name);
num++;
best->profile = 0;
}
} while (best);
}
/*
============
PR_RunError
Aborts the currently executing function
============
*/
void PR_RunError (char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr,error);
vsprintf (string,error,argptr);
va_end (argptr);
PR_PrintStatement (pr_statements + pr_xstatement);
PR_StackTrace ();
Con_Printf ("%s\n", string);
pr_depth = 0; // dump the stack so host_error can shutdown functions
Host_Error ("Program error");
}
/*
============================================================================
PR_ExecuteProgram
The interpretation main loop
============================================================================
*/
/*
====================
PR_EnterFunction
Returns the new program statement counter
====================
*/
int PR_EnterFunction (dfunction_t *f)
{
int i, j, c, o;
pr_stack[pr_depth].s = pr_xstatement;
pr_stack[pr_depth].f = pr_xfunction;
pr_depth++;
if (pr_depth >= MAX_STACK_DEPTH)
PR_RunError ("stack overflow");
// save off any locals that the new function steps on
c = f->locals;
if (localstack_used + c > LOCALSTACK_SIZE)
PR_RunError ("PR_ExecuteProgram: locals stack overflow\n");
for (i=0 ; i < c ; i++)
localstack[localstack_used+i] = ((int *)pr_globals)[f->parm_start + i];
localstack_used += c;
// copy parameters
o = f->parm_start;
for (i=0 ; i<f->numparms ; i++)
{
for (j=0 ; j<f->parm_size[i] ; j++)
{
((int *)pr_globals)[o] = ((int *)pr_globals)[OFS_PARM0+i*3+j];
o++;
}
}
pr_xfunction = f;
return f->first_statement - 1; // offset the s++
}
/*
====================
PR_LeaveFunction
====================
*/
int PR_LeaveFunction (void)
{
int i, c;
if (pr_depth <= 0)
Sys_Error ("prog stack underflow");
// restore locals from the stack
c = pr_xfunction->locals;
localstack_used -= c;
if (localstack_used < 0)
PR_RunError ("PR_ExecuteProgram: locals stack underflow\n");
for (i=0 ; i < c ; i++)
((int *)pr_globals)[pr_xfunction->parm_start + i] = localstack[localstack_used+i];
// up stack
pr_depth--;
pr_xfunction = pr_stack[pr_depth].f;
return pr_stack[pr_depth].s;
}
/*
====================
PR_ExecuteProgram
====================
*/
void PR_ExecuteProgram (func_t fnum)
{
eval_t *a, *b, *c;
int s;
dstatement_t *st;
dfunction_t *f, *newf;
int runaway;
int i;
edict_t *ed;
int exitdepth;
eval_t *ptr;
if (!fnum || fnum >= progs->numfunctions)
{
if (pr_global_struct->self)
ED_Print (PROG_TO_EDICT(pr_global_struct->self));
Host_Error ("PR_ExecuteProgram: NULL function");
}
f = &pr_functions[fnum];
runaway = 100000;
pr_trace = false;
// make a stack frame
exitdepth = pr_depth;
s = PR_EnterFunction (f);
while (1)
{
s++; // next statement
st = &pr_statements[s];
a = (eval_t *)&pr_globals[st->a];
b = (eval_t *)&pr_globals[st->b];
c = (eval_t *)&pr_globals[st->c];
if (!--runaway)
PR_RunError ("runaway loop error");
pr_xfunction->profile++;
pr_xstatement = s;
if (pr_trace)
PR_PrintStatement (st);
switch (st->op)
{
case OP_ADD_F:
c->_float = a->_float + b->_float;
break;
case OP_ADD_V:
c->vector[0] = a->vector[0] + b->vector[0];
c->vector[1] = a->vector[1] + b->vector[1];
c->vector[2] = a->vector[2] + b->vector[2];
break;
case OP_SUB_F:
c->_float = a->_float - b->_float;
break;
case OP_SUB_V:
c->vector[0] = a->vector[0] - b->vector[0];
c->vector[1] = a->vector[1] - b->vector[1];
c->vector[2] = a->vector[2] - b->vector[2];
break;
case OP_MUL_F:
c->_float = a->_float * b->_float;
break;
case OP_MUL_V:
c->_float = a->vector[0]*b->vector[0]
+ a->vector[1]*b->vector[1]
+ a->vector[2]*b->vector[2];
break;
case OP_MUL_FV:
c->vector[0] = a->_float * b->vector[0];
c->vector[1] = a->_float * b->vector[1];
c->vector[2] = a->_float * b->vector[2];
break;
case OP_MUL_VF:
c->vector[0] = b->_float * a->vector[0];
c->vector[1] = b->_float * a->vector[1];
c->vector[2] = b->_float * a->vector[2];
break;
case OP_DIV_F:
c->_float = a->_float / b->_float;
break;
case OP_BITAND:
c->_float = (int)a->_float & (int)b->_float;
break;
case OP_BITOR:
c->_float = (int)a->_float | (int)b->_float;
break;
case OP_GE:
c->_float = a->_float >= b->_float;
break;
case OP_LE:
c->_float = a->_float <= b->_float;
break;
case OP_GT:
c->_float = a->_float > b->_float;
break;
case OP_LT:
c->_float = a->_float < b->_float;
break;
case OP_AND:
c->_float = a->_float && b->_float;
break;
case OP_OR:
c->_float = a->_float || b->_float;
break;
case OP_NOT_F:
c->_float = !a->_float;
break;
case OP_NOT_V:
c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2];
break;
case OP_NOT_S:
c->_float = !a->string || !pr_strings[a->string];
break;
case OP_NOT_FNC:
c->_float = !a->function;
break;
case OP_NOT_ENT:
c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts);
break;
case OP_EQ_F:
c->_float = a->_float == b->_float;
break;
case OP_EQ_V:
c->_float = (a->vector[0] == b->vector[0]) &&
(a->vector[1] == b->vector[1]) &&
(a->vector[2] == b->vector[2]);
break;
case OP_EQ_S:
c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_EQ_E:
c->_float = a->_int == b->_int;
break;
case OP_EQ_FNC:
c->_float = a->function == b->function;
break;
case OP_NE_F:
c->_float = a->_float != b->_float;
break;
case OP_NE_V:
c->_float = (a->vector[0] != b->vector[0]) ||
(a->vector[1] != b->vector[1]) ||
(a->vector[2] != b->vector[2]);
break;
case OP_NE_S:
c->_float = strcmp(pr_strings+a->string,pr_strings+b->string);
break;
case OP_NE_E:
c->_float = a->_int != b->_int;
break;
case OP_NE_FNC:
c->_float = a->function != b->function;
break;
//==================
case OP_STORE_F:
case OP_STORE_ENT:
case OP_STORE_FLD: // integers
case OP_STORE_S:
case OP_STORE_FNC: // pointers
b->_int = a->_int;
break;
case OP_STORE_V:
b->vector[0] = a->vector[0];
b->vector[1] = a->vector[1];
b->vector[2] = a->vector[2];
break;
case OP_STOREP_F:
case OP_STOREP_ENT:
case OP_STOREP_FLD: // integers
case OP_STOREP_S:
case OP_STOREP_FNC: // pointers
ptr = (eval_t *)((byte *)sv.edicts + b->_int);
ptr->_int = a->_int;
break;
case OP_STOREP_V:
ptr = (eval_t *)((byte *)sv.edicts + b->_int);
ptr->vector[0] = a->vector[0];
ptr->vector[1] = a->vector[1];
ptr->vector[2] = a->vector[2];
break;
case OP_ADDRESS:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
if (ed == (edict_t *)sv.edicts && sv.state == ss_active)
PR_RunError ("assignment to world entity");
c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts;
break;
case OP_LOAD_F:
case OP_LOAD_FLD:
case OP_LOAD_ENT:
case OP_LOAD_S:
case OP_LOAD_FNC:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->_int = a->_int;
break;
case OP_LOAD_V:
ed = PROG_TO_EDICT(a->edict);
#ifdef PARANOID
NUM_FOR_EDICT(ed); // make sure it's in range
#endif
a = (eval_t *)((int *)&ed->v + b->_int);
c->vector[0] = a->vector[0];
c->vector[1] = a->vector[1];
c->vector[2] = a->vector[2];
break;
//==================
case OP_IFNOT:
if (!a->_int)
s += st->b - 1; // offset the s++
break;
case OP_IF:
if (a->_int)
s += st->b - 1; // offset the s++
break;
case OP_GOTO:
s += st->a - 1; // offset the s++
break;
case OP_CALL0:
case OP_CALL1:
case OP_CALL2:
case OP_CALL3:
case OP_CALL4:
case OP_CALL5:
case OP_CALL6:
case OP_CALL7:
case OP_CALL8:
pr_argc = st->op - OP_CALL0;
if (!a->function)
PR_RunError ("NULL function");
newf = &pr_functions[a->function];
if (newf->first_statement < 0)
{ // negative statements are built in functions
i = -newf->first_statement;
if (i >= pr_numbuiltins)
PR_RunError ("Bad builtin call number");
pr_builtins[i] ();
break;
}
s = PR_EnterFunction (newf);
break;
case OP_DONE:
case OP_RETURN:
pr_globals[OFS_RETURN] = pr_globals[st->a];
pr_globals[OFS_RETURN+1] = pr_globals[st->a+1];
pr_globals[OFS_RETURN+2] = pr_globals[st->a+2];
s = PR_LeaveFunction ();
if (pr_depth == exitdepth)
return; // all done
break;
case OP_STATE:
ed = PROG_TO_EDICT(pr_global_struct->self);
#ifdef FPS_20
ed->v.nextthink = pr_global_struct->time + 0.05;
#else
ed->v.nextthink = pr_global_struct->time + 0.1;
#endif
if (a->_float != ed->v.frame)
{
ed->v.frame = a->_float;
}
ed->v.think = b->function;
break;
default:
PR_RunError ("Bad opcode %i", st->op);
}
}
}

View file

@ -1,134 +0,0 @@
/*
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 "pr_comp.h" // defs shared with qcc
#include "progdefs.h" // generated by program cdefs
typedef union eval_s
{
string_t string;
float _float;
float vector[3];
func_t function;
int _int;
int edict;
} eval_t;
#define MAX_ENT_LEAFS 16
typedef struct edict_s
{
qboolean free;
link_t area; // linked to a division node or leaf
int num_leafs;
short leafnums[MAX_ENT_LEAFS];
entity_state_t baseline;
float freetime; // sv.time when the object was freed
entvars_t v; // C exported fields from progs
// other fields from progs come immediately after
} edict_t;
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
//============================================================================
extern dprograms_t *progs;
extern dfunction_t *pr_functions;
extern char *pr_strings;
extern ddef_t *pr_globaldefs;
extern ddef_t *pr_fielddefs;
extern dstatement_t *pr_statements;
extern globalvars_t *pr_global_struct;
extern float *pr_globals; // same as pr_global_struct
extern int pr_edict_size; // in bytes
//============================================================================
void PR_Init (void);
void PR_ExecuteProgram (func_t fnum);
void PR_LoadProgs (void);
void PR_Profile_f (void);
edict_t *ED_Alloc (void);
void ED_Free (edict_t *ed);
char *ED_NewString (char *string);
// returns a copy of the string allocated from the server's string heap
void ED_Print (edict_t *ed);
void ED_Write (FILE *f, edict_t *ed);
char *ED_ParseEdict (char *data, edict_t *ent);
void ED_WriteGlobals (FILE *f);
void ED_ParseGlobals (char *data);
void ED_LoadFromFile (char *data);
//define EDICT_NUM(n) ((edict_t *)(sv.edicts+ (n)*pr_edict_size))
//define NUM_FOR_EDICT(e) (((byte *)(e) - sv.edicts)/pr_edict_size)
edict_t *EDICT_NUM(int n);
int NUM_FOR_EDICT(edict_t *e);
#define NEXT_EDICT(e) ((edict_t *)( (byte *)e + pr_edict_size))
#define EDICT_TO_PROG(e) ((byte *)e - (byte *)sv.edicts)
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
//============================================================================
#define G_FLOAT(o) (pr_globals[o])
#define G_INT(o) (*(int *)&pr_globals[o])
#define G_EDICT(o) ((edict_t *)((byte *)sv.edicts+ *(int *)&pr_globals[o]))
#define G_EDICTNUM(o) NUM_FOR_EDICT(G_EDICT(o))
#define G_VECTOR(o) (&pr_globals[o])
#define G_STRING(o) (pr_strings + *(string_t *)&pr_globals[o])
#define G_FUNCTION(o) (*(func_t *)&pr_globals[o])
#define E_FLOAT(e,o) (((float*)&e->v)[o])
#define E_INT(e,o) (*(int *)&((float*)&e->v)[o])
#define E_VECTOR(e,o) (&((float*)&e->v)[o])
#define E_STRING(e,o) (pr_strings + *(string_t *)&((float*)&e->v)[o])
extern int type_size[8];
typedef void (*builtin_t) (void);
extern builtin_t *pr_builtins;
extern int pr_numbuiltins;
extern int pr_argc;
extern qboolean pr_trace;
extern dfunction_t *pr_xfunction;
extern int pr_xstatement;
extern unsigned short pr_crc;
void PR_RunError (char *error, ...);
void ED_PrintEdicts (void);
void ED_PrintNum (int ent);
eval_t *GetEdictFieldValue(edict_t *ed, char *field);