306 lines
6.1 KiB
C
306 lines
6.1 KiB
C
|
// entities.c
|
||
|
|
||
|
#include "light.h"
|
||
|
|
||
|
entity_t entities[max_map_entities];
|
||
|
int num_entities;
|
||
|
|
||
|
/*
|
||
|
==============================================================================
|
||
|
|
||
|
entity file parsing
|
||
|
|
||
|
if a light has a targetname, generate a unique style in the 32-63 range
|
||
|
==============================================================================
|
||
|
*/
|
||
|
|
||
|
int numlighttargets;
|
||
|
char lighttargets[32][64];
|
||
|
|
||
|
int lightstylefortargetname (char *targetname, qboolean alloc)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i=0 ; i<numlighttargets ; i++)
|
||
|
if (!strcmp (lighttargets[i], targetname))
|
||
|
return 32 + i;
|
||
|
if (!alloc)
|
||
|
return -1;
|
||
|
strcpy (lighttargets[i], targetname);
|
||
|
numlighttargets++;
|
||
|
return numlighttargets-1 + 32;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
matchtargets
|
||
|
==================
|
||
|
*/
|
||
|
void matchtargets (void)
|
||
|
{
|
||
|
int i,j;
|
||
|
|
||
|
for (i=0 ; i<num_entities ; i++)
|
||
|
{
|
||
|
if (!entities[i].target[0])
|
||
|
continue;
|
||
|
|
||
|
for (j=0 ; j<num_entities ; j++)
|
||
|
if (!strcmp(entities[j].targetname, entities[i].target))
|
||
|
{
|
||
|
entities[i].targetent = &entities[j];
|
||
|
break;
|
||
|
}
|
||
|
if (j==num_entities)
|
||
|
{
|
||
|
printf ("warning: entity at (%i,%i,%i) (%s) has unmatched target\n", (int)entities[i].origin[0], (int)entities[i].origin[1], (int)entities[i].origin[2], entities[i].classname);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// set the style on the source ent for switchable lights
|
||
|
if (entities[j].style)
|
||
|
{
|
||
|
char s[16];
|
||
|
|
||
|
entities[i].style = entities[j].style;
|
||
|
sprintf (s,"%i", entities[i].style);
|
||
|
setkeyvalue (&entities[i], "style", s);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
loadentities
|
||
|
==================
|
||
|
*/
|
||
|
void loadentities (void)
|
||
|
{
|
||
|
char *data;
|
||
|
entity_t *entity;
|
||
|
char key[64];
|
||
|
epair_t *epair;
|
||
|
double vec[3];
|
||
|
int i;
|
||
|
|
||
|
data = dentdata;
|
||
|
//
|
||
|
// start parsing
|
||
|
//
|
||
|
num_entities = 0;
|
||
|
|
||
|
// go through all the entities
|
||
|
while (1)
|
||
|
{
|
||
|
// parse the opening brace
|
||
|
data = com_parse (data);
|
||
|
if (!data)
|
||
|
break;
|
||
|
if (com_token[0] != '{')
|
||
|
error ("loadentities: found %s when expecting {",com_token);
|
||
|
|
||
|
if (num_entities == max_map_entities)
|
||
|
error ("loadentities: max_map_entities");
|
||
|
entity = &entities[num_entities];
|
||
|
num_entities++;
|
||
|
|
||
|
// go through all the keys in this entity
|
||
|
while (1)
|
||
|
{
|
||
|
int c;
|
||
|
|
||
|
// parse key
|
||
|
data = com_parse (data);
|
||
|
if (!data)
|
||
|
error ("loadentities: eof without closing brace");
|
||
|
if (!strcmp(com_token,"}"))
|
||
|
break;
|
||
|
strcpy (key, com_token);
|
||
|
|
||
|
// parse value
|
||
|
data = com_parse (data);
|
||
|
if (!data)
|
||
|
error ("loadentities: eof without closing brace");
|
||
|
c = com_token[0];
|
||
|
if (c == '}')
|
||
|
error ("loadentities: closing brace without data");
|
||
|
|
||
|
epair = malloc (sizeof(epair_t));
|
||
|
memset (epair, 0, sizeof(epair));
|
||
|
strcpy (epair->key, key);
|
||
|
strcpy (epair->value, com_token);
|
||
|
epair->next = entity->epairs;
|
||
|
entity->epairs = epair;
|
||
|
|
||
|
if (!strcmp(key, "classname"))
|
||
|
strcpy (entity->classname, com_token);
|
||
|
else if (!strcmp(key, "target"))
|
||
|
strcpy (entity->target, com_token);
|
||
|
else if (!strcmp(key, "targetname"))
|
||
|
strcpy (entity->targetname, com_token);
|
||
|
else if (!strcmp(key, "origin"))
|
||
|
{
|
||
|
// scan into doubles, then assign
|
||
|
// which makes it vec_t size independent
|
||
|
if (sscanf(com_token, "%lf %lf %lf",
|
||
|
&vec[0], &vec[1], &vec[2]) != 3)
|
||
|
error ("loadentities: not 3 values for origin");
|
||
|
for (i=0 ; i<3 ; i++)
|
||
|
entity->origin[i] = vec[i];
|
||
|
}
|
||
|
else if (!strncmp(key, "light", 5) || !strcmp (key, "_light") )
|
||
|
{
|
||
|
entity->light = atof(com_token);
|
||
|
}
|
||
|
else if (!strcmp(key, "style"))
|
||
|
{
|
||
|
entity->style = atof(com_token);
|
||
|
if ((unsigned)entity->style > 254)
|
||
|
error ("bad light style %i (must be 0-254)", entity->style);
|
||
|
}
|
||
|
else if (!strcmp(key, "angle"))
|
||
|
{
|
||
|
entity->angle = atof(com_token);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// all fields have been parsed
|
||
|
if (!strncmp (entity->classname, "light", 5) && !entity->light)
|
||
|
entity->light = defaultlightlevel;
|
||
|
|
||
|
if (!strcmp (entity->classname, "light"))
|
||
|
{
|
||
|
if (entity->targetname[0] && !entity->style)
|
||
|
{
|
||
|
char s[16];
|
||
|
|
||
|
entity->style = lightstylefortargetname (entity->targetname, true);
|
||
|
sprintf (s,"%i", entity->style);
|
||
|
setkeyvalue (entity, "style", s);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf ("%d entities read\n", num_entities);
|
||
|
|
||
|
matchtargets ();
|
||
|
}
|
||
|
|
||
|
char *valueforkey (entity_t *ent, char *key)
|
||
|
{
|
||
|
epair_t *ep;
|
||
|
|
||
|
for (ep=ent->epairs ; ep ; ep=ep->next)
|
||
|
if (!strcmp (ep->key, key) )
|
||
|
return ep->value;
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
void setkeyvalue (entity_t *ent, char *key, char *value)
|
||
|
{
|
||
|
epair_t *ep;
|
||
|
|
||
|
for (ep=ent->epairs ; ep ; ep=ep->next)
|
||
|
if (!strcmp (ep->key, key) )
|
||
|
{
|
||
|
strcpy (ep->value, value);
|
||
|
return;
|
||
|
}
|
||
|
ep = malloc (sizeof(*ep));
|
||
|
ep->next = ent->epairs;
|
||
|
ent->epairs = ep;
|
||
|
strcpy (ep->key, key);
|
||
|
strcpy (ep->value, value);
|
||
|
}
|
||
|
|
||
|
//jim
|
||
|
entity_t *findentitywithkeypair( char *key, char *value )
|
||
|
{
|
||
|
entity_t *ent;
|
||
|
epair_t *ep;
|
||
|
int i;
|
||
|
|
||
|
for (i=0 ; i<num_entities ; i++)
|
||
|
{
|
||
|
ent = &entities[ i ];
|
||
|
for (ep=ent->epairs ; ep ; ep=ep->next)
|
||
|
{
|
||
|
if (!strcmp (ep->key, key) )
|
||
|
{
|
||
|
if ( !strcmp( ep->value, value ) )
|
||
|
{
|
||
|
return ent;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
float floatforkey (entity_t *ent, char *key)
|
||
|
{
|
||
|
char *k;
|
||
|
|
||
|
k = valueforkey (ent, key);
|
||
|
return atof(k);
|
||
|
}
|
||
|
|
||
|
//jim
|
||
|
void getvectorforkey (entity_t *ent, char *key, vec3_t vec)
|
||
|
{
|
||
|
char *k;
|
||
|
|
||
|
k = valueforkey (ent, key);
|
||
|
// sscanf (k, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]);
|
||
|
sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
writeentitiestostring
|
||
|
================
|
||
|
*/
|
||
|
void writeentitiestostring (void)
|
||
|
{
|
||
|
char *buf, *end;
|
||
|
epair_t *ep;
|
||
|
char line[128];
|
||
|
int i;
|
||
|
|
||
|
buf = dentdata;
|
||
|
end = buf;
|
||
|
*end = 0;
|
||
|
|
||
|
printf ("%i switchable light styles\n", numlighttargets);
|
||
|
|
||
|
for (i=0 ; i<num_entities ; i++)
|
||
|
{
|
||
|
ep = entities[i].epairs;
|
||
|
if (!ep)
|
||
|
continue; // ent got removed
|
||
|
|
||
|
strcat (end,"{\n");
|
||
|
end += 2;
|
||
|
|
||
|
for (ep = entities[i].epairs ; ep ; ep=ep->next)
|
||
|
{
|
||
|
sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
|
||
|
strcat (end, line);
|
||
|
end += strlen(line);
|
||
|
}
|
||
|
strcat (end,"}\n");
|
||
|
end += 2;
|
||
|
|
||
|
if (end > buf + max_map_entstring)
|
||
|
error ("entity text too long");
|
||
|
}
|
||
|
entdatasize = end - buf + 1;
|
||
|
}
|
||
|
|