📄 pr_edict.c
字号:
}
/*
=============
ED_Print
For debugging
=============
*/
void ED_Print (edict_t *ed)
{
int l;
ddef_t *d;
int *v;
int i, j;
char *name;
int type;
if (ed->free)
{
Con_Printf ("FREE\n");
return;
}
Con_Printf("\nEDICT %i:\n", NUM_FOR_EDICT(ed));
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)((char *)&ed->v + d->ofs*4);
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<type_size[type] ; j++)
if (v[j])
break;
if (j == type_size[type])
continue;
Con_Printf ("%s",name);
l = strlen (name);
while (l++ < 15)
Con_Printf (" ");
Con_Printf ("%s\n", PR_ValueString(d->type, (eval_t *)v));
}
}
/*
=============
ED_Write
For savegames
=============
*/
void ED_Write (FILE *f, edict_t *ed)
{
ddef_t *d;
int *v;
int i, j;
char *name;
int type;
fprintf (f, "{\n");
if (ed->free)
{
fprintf (f, "}\n");
return;
}
for (i=1 ; i<progs->numfielddefs ; i++)
{
d = &pr_fielddefs[i];
name = pr_strings + d->s_name;
if (name[strlen(name)-2] == '_')
continue; // skip _x, _y, _z vars
v = (int *)((char *)&ed->v + d->ofs*4);
// if the value is still all 0, skip the field
type = d->type & ~DEF_SAVEGLOBAL;
for (j=0 ; j<type_size[type] ; j++)
if (v[j])
break;
if (j == type_size[type])
continue;
fprintf (f,"\"%s\" ",name);
fprintf (f,"\"%s\"\n", PR_UglyValueString(d->type, (eval_t *)v));
}
fprintf (f, "}\n");
}
void ED_PrintNum (int ent)
{
ED_Print (EDICT_NUM(ent));
}
/*
=============
ED_PrintEdicts
For debugging, prints all the entities in the current server
=============
*/
void ED_PrintEdicts (void)
{
int i;
Con_Printf ("%i entities\n", sv.num_edicts);
for (i=0 ; i<sv.num_edicts ; i++)
ED_PrintNum (i);
}
/*
=============
ED_PrintEdict_f
For debugging, prints a single edict
=============
*/
void ED_PrintEdict_f (void)
{
int i;
i = Q_atoi (Cmd_Argv(1));
if (i >= sv.num_edicts)
{
Con_Printf("Bad edict number\n");
return;
}
ED_PrintNum (i);
}
/*
=============
ED_Count
For debugging
=============
*/
void ED_Count (void)
{
int i;
edict_t *ent;
int active, models, solid, step;
active = models = solid = step = 0;
for (i=0 ; i<sv.num_edicts ; i++)
{
ent = EDICT_NUM(i);
if (ent->free)
continue;
active++;
if (ent->v.solid)
solid++;
if (ent->v.model)
models++;
if (ent->v.movetype == MOVETYPE_STEP)
step++;
}
Con_Printf ("num_edicts:%3i\n", sv.num_edicts);
Con_Printf ("active :%3i\n", active);
Con_Printf ("view :%3i\n", models);
Con_Printf ("touch :%3i\n", solid);
Con_Printf ("step :%3i\n", step);
}
/*
==============================================================================
ARCHIVING GLOBALS
FIXME: need to tag constants, doesn't really work
==============================================================================
*/
/*
=============
ED_WriteGlobals
=============
*/
void ED_WriteGlobals (FILE *f)
{
ddef_t *def;
int i;
char *name;
int type;
fprintf (f,"{\n");
for (i=0 ; i<progs->numglobaldefs ; i++)
{
def = &pr_globaldefs[i];
type = def->type;
if ( !(def->type & DEF_SAVEGLOBAL) )
continue;
type &= ~DEF_SAVEGLOBAL;
if (type != ev_string
&& type != ev_float
&& type != ev_entity)
continue;
name = pr_strings + def->s_name;
fprintf (f,"\"%s\" ", name);
fprintf (f,"\"%s\"\n", PR_UglyValueString(type, (eval_t *)&pr_globals[def->ofs]));
}
fprintf (f,"}\n");
}
/*
=============
ED_ParseGlobals
=============
*/
void ED_ParseGlobals (char *data)
{
char keyname[64];
ddef_t *key;
while (1)
{
// parse key
data = COM_Parse (data);
if (com_token[0] == '}')
break;
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
strcpy (keyname, com_token);
// parse value
data = COM_Parse (data);
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
if (com_token[0] == '}')
Sys_Error ("ED_ParseEntity: closing brace without data");
key = ED_FindGlobal (keyname);
if (!key)
{
Con_Printf ("'%s' is not a global\n", keyname);
continue;
}
if (!ED_ParseEpair ((void *)pr_globals, key, com_token))
Host_Error ("ED_ParseGlobals: parse error");
}
}
//============================================================================
/*
=============
ED_NewString
=============
*/
char *ED_NewString (char *string)
{
char *new, *new_p;
int i,l;
l = strlen(string) + 1;
new = Hunk_Alloc (l);
new_p = new;
for (i=0 ; i< l ; i++)
{
if (string[i] == '\\' && i < l-1)
{
i++;
if (string[i] == 'n')
*new_p++ = '\n';
else
*new_p++ = '\\';
}
else
*new_p++ = string[i];
}
return new;
}
/*
=============
ED_ParseEval
Can parse either fields or globals
returns false if error
=============
*/
qboolean ED_ParseEpair (void *base, ddef_t *key, char *s)
{
int i;
char string[128];
ddef_t *def;
char *v, *w;
void *d;
dfunction_t *func;
d = (void *)((int *)base + key->ofs);
switch (key->type & ~DEF_SAVEGLOBAL)
{
case ev_string:
*(string_t *)d = ED_NewString (s) - pr_strings;
break;
case ev_float:
*(float *)d = atof (s);
break;
case ev_vector:
strcpy (string, s);
v = string;
w = string;
for (i=0 ; i<3 ; i++)
{
while (*v && *v != ' ')
v++;
*v = 0;
((float *)d)[i] = atof (w);
w = v = v+1;
}
break;
case ev_entity:
*(int *)d = EDICT_TO_PROG(EDICT_NUM(atoi (s)));
break;
case ev_field:
def = ED_FindField (s);
if (!def)
{
Con_Printf ("Can't find field %s\n", s);
return false;
}
*(int *)d = G_INT(def->ofs);
break;
case ev_function:
func = ED_FindFunction (s);
if (!func)
{
Con_Printf ("Can't find function %s\n", s);
return false;
}
*(func_t *)d = func - pr_functions;
break;
default:
break;
}
return true;
}
/*
====================
ED_ParseEdict
Parses an edict out of the given string, returning the new position
ed should be a properly initialized empty edict.
Used for initial level load and for savegames.
====================
*/
char *ED_ParseEdict (char *data, edict_t *ent)
{
ddef_t *key;
qboolean anglehack;
qboolean init;
char keyname[256];
int n;
init = false;
// clear it
if (ent != sv.edicts) // hack
memset (&ent->v, 0, progs->entityfields * 4);
// go through all the dictionary pairs
while (1)
{
// parse key
data = COM_Parse (data);
if (com_token[0] == '}')
break;
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
// anglehack is to allow QuakeEd to write single scalar angles
// and allow them to be turned into vectors. (FIXME...)
if (!strcmp(com_token, "angle"))
{
strcpy (com_token, "angles");
anglehack = true;
}
else
anglehack = false;
// FIXME: change light to _light to get rid of this hack
if (!strcmp(com_token, "light"))
strcpy (com_token, "light_lev"); // hack for single light def
strcpy (keyname, com_token);
// another hack to fix heynames with trailing spaces
n = strlen(keyname);
while (n && keyname[n-1] == ' ')
{
keyname[n-1] = 0;
n--;
}
// parse value
data = COM_Parse (data);
if (!data)
Sys_Error ("ED_ParseEntity: EOF without closing brace");
if (com_token[0] == '}')
Sys_Error ("ED_ParseEntity: closing brace without data");
init = true;
// keynames with a leading underscore are used for utility comments,
// and are immediately discarded by quake
if (keyname[0] == '_')
continue;
key = ED_FindField (keyname);
if (!key)
{
Con_Printf ("'%s' is not a field\n", keyname);
continue;
}
if (anglehack)
{
char temp[32];
strcpy (temp, com_token);
sprintf (com_token, "0 %s 0", temp);
}
if (!ED_ParseEpair ((void *)&ent->v, key, com_token))
Host_Error ("ED_ParseEdict: parse error");
}
if (!init)
ent->free = true;
return data;
}
/*
================
ED_LoadFromFile
The entities are directly placed in the array, rather than allocated with
ED_Alloc, because otherwise an error loading the map would have entity
number references out of order.
Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
Used for both fresh maps and savegame loads. A fresh map would also need
to call ED_CallSpawnFunctions () to let the objects initialize themselves.
================
*/
void ED_LoadFromFile (char *data)
{
edict_t *ent;
int inhibit;
dfunction_t *func;
ent = NULL;
inhibit = 0;
pr_global_struct->time = sv.time;
// parse ents
while (1)
{
// parse the opening brace
data = COM_Parse (data);
if (!data)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -