1 /*
2  * entities.c
3  * $Id: entities.c,v 1.10 2007-12-14 16:41:23 sezero Exp $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #include "q_stdinc.h"
25 #include "compiler.h"
26 #include "arch_def.h"
27 #include "cmdlib.h"
28 #include "mathlib.h"
29 #include "bspfile.h"
30 #include "entities.h"
31 #include "light.h"
32 
33 
34 entity_t	entities[MAX_MAP_ENTITIES];
35 int			num_entities;
36 
37 
38 /*
39 ==============================================================================
40 
41 ENTITY FILE PARSING
42 
43 If a light has a targetname, generate a unique style in the 32-63 range
44 ==============================================================================
45 */
46 
47 static int		numlighttargets;
48 static char	lighttargets[32][64];
49 
LightStyleForTargetname(char * targetname,qboolean alloc)50 static int LightStyleForTargetname (char *targetname, qboolean alloc)
51 {
52 	int		i;
53 
54 	for (i = 0 ; i < numlighttargets ; i++)
55 		if (!strcmp (lighttargets[i], targetname))
56 			return 32 + i;
57 	if (!alloc)
58 		return -1;
59 	strcpy (lighttargets[i], targetname);
60 	numlighttargets++;
61 	return numlighttargets-1 + 32;
62 }
63 
64 
65 /*
66 ==================
67 MatchTargets
68 ==================
69 */
MatchTargets(void)70 static void MatchTargets (void)
71 {
72 	int		i, j;
73 
74 	for (i = 0 ; i < num_entities ; i++)
75 	{
76 		if (!entities[i].target[0])
77 			continue;
78 
79 		for (j = 0 ; j < num_entities ; j++)
80 			if (!strcmp(entities[j].targetname, entities[i].target))
81 			{
82 				entities[i].targetent = &entities[j];
83 				break;
84 			}
85 		if (j == num_entities)
86 		{
87 			printf ("WARNING: entity at (%i,%i,%i) (%s) has unmatched target\n",
88 					(int)entities[i].origin[0], (int)entities[i].origin[1],
89 					(int)entities[i].origin[2], entities[i].classname);
90 			continue;
91 		}
92 
93 	// set the style on the source ent for switchable lights
94 		if (entities[j].style)
95 		{
96 			char	s[16];
97 
98 			entities[i].style = entities[j].style;
99 			sprintf (s,"%i", entities[i].style);
100 			SetKeyValue (&entities[i], "style", s);
101 		}
102 	}
103 }
104 
105 
106 /*
107 ==================
108 LoadEntities
109 ==================
110 */
LoadEntities(void)111 void LoadEntities (void)
112 {
113 	const char	*data;
114 	entity_t	*entity;
115 	char		key[64];
116 	epair_t		*epair;
117 
118 	data = dentdata;
119 //
120 // start parsing
121 //
122 	num_entities = 0;
123 
124 // go through all the entities
125 	while (1)
126 	{
127 	// parse the opening brace
128 		data = COM_Parse (data);
129 		if (!data)
130 			break;
131 		if (com_token[0] != '{')
132 			COM_Error ("%s: found %s when expecting {", __thisfunc__, com_token);
133 
134 		if (num_entities == MAX_MAP_ENTITIES)
135 			COM_Error ("%s: MAX_MAP_ENTITIES", __thisfunc__);
136 		entity = &entities[num_entities];
137 		num_entities++;
138 
139 	// go through all the keys in this entity
140 		while (1)
141 		{
142 			int		c;
143 
144 		// parse key
145 			data = COM_Parse (data);
146 			if (!data)
147 				COM_Error ("%s: EOF without closing brace", __thisfunc__);
148 			if (!strcmp(com_token,"}"))
149 				break;
150 			strcpy (key, com_token);
151 
152 		// parse value
153 			data = COM_Parse (data);
154 			if (!data)
155 				COM_Error ("%s: EOF without closing brace", __thisfunc__);
156 			c = com_token[0];
157 			if (c == '}')
158 				COM_Error ("%s: closing brace without data", __thisfunc__);
159 
160 			epair = (epair_t *) SafeMalloc (sizeof(epair_t));
161 			strcpy (epair->key, key);
162 			strcpy (epair->value, com_token);
163 			epair->next = entity->epairs;
164 			entity->epairs = epair;
165 
166 			if (!strcmp(key, "classname"))
167 				strcpy (entity->classname, com_token);
168 			else if (!strcmp(key, "target"))
169 				strcpy (entity->target, com_token);
170 			else if (!strcmp(key, "targetname"))
171 				strcpy (entity->targetname, com_token);
172 			else if (!strcmp(key, "origin"))
173 			{
174 				if (sscanf(com_token, "%lf %lf %lf",
175 						&entity->origin[0],
176 						&entity->origin[1],
177 						&entity->origin[2]) != 3)
178 					COM_Error ("%s: not 3 values for origin", __thisfunc__);
179 			}
180 			else if (!strncmp(key, "light", 5))
181 			{
182 				entity->light = atoi(com_token);
183 			}
184 			else if (!strcmp(key, "style"))
185 			{
186 				entity->style = atoi(com_token);
187 				if ((unsigned int)entity->style > 254)
188 					COM_Error ("Bad light style %i (must be 0-254)", entity->style);
189 			}
190 			else if (!strcmp(key, "angle"))
191 			{
192 				entity->angle = (float)atof(com_token);
193 			}
194 		}
195 
196 	// all fields have been parsed
197 		if (!strncmp (entity->classname, "light", 5) && !entity->light)
198 			entity->light = DEFAULTLIGHTLEVEL;
199 
200 		if (!strncmp (entity->classname, "light", 5))
201 		{
202 			if (entity->targetname[0] && !entity->style)
203 			{
204 				char	s[16];
205 
206 				entity->style = LightStyleForTargetname (entity->targetname, true);
207 				sprintf (s,"%i", entity->style);
208 				SetKeyValue (entity, "style", s);
209 			}
210 		}
211 	}
212 
213 	printf ("%d entities read\n", num_entities);
214 
215 	MatchTargets ();
216 }
217 
218 
ValueForKey(entity_t * ent,const char * key)219 const char *ValueForKey (entity_t *ent, const char *key)
220 {
221 	epair_t	*ep;
222 
223 	for (ep = ent->epairs ; ep ; ep = ep->next)
224 	{
225 		if (!strcmp (ep->key, key) )
226 			return ep->value;
227 	}
228 
229 	return "";
230 }
231 
SetKeyValue(entity_t * ent,const char * key,const char * value)232 void SetKeyValue (entity_t *ent, const char *key, const char *value)
233 {
234 	epair_t	*ep;
235 
236 	for (ep = ent->epairs ; ep ; ep = ep->next)
237 	{
238 		if (!strcmp (ep->key, key) )
239 		{
240 			strcpy (ep->value, value);
241 			return;
242 		}
243 	}
244 
245 	ep = (epair_t *) SafeMalloc (sizeof(*ep));
246 	ep->next = ent->epairs;
247 	ent->epairs = ep;
248 	strcpy (ep->key, key);
249 	strcpy (ep->value, value);
250 }
251 
FloatForKey(entity_t * ent,const char * key)252 float FloatForKey (entity_t *ent, const char *key)
253 {
254 	const char	*k;
255 
256 	k = ValueForKey (ent, key);
257 	return (float)atof(k);
258 }
259 
GetVectorForKey(entity_t * ent,const char * key,vec3_t vec)260 void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
261 {
262 	const char	*k;
263 
264 	k = ValueForKey (ent, key);
265 	sscanf (k, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]);
266 }
267 
268 
269 /*
270 ================
271 WriteEntitiesToString
272 ================
273 */
WriteEntitiesToString(void)274 void WriteEntitiesToString (void)
275 {
276 	char	*buf, *end;
277 	epair_t	*ep;
278 	char	line[128];
279 	int		i;
280 
281 	buf = dentdata;
282 	end = buf;
283 	*end = 0;
284 
285 	printf ("%i switchable light styles\n", numlighttargets);
286 
287 	for (i = 0 ; i < num_entities ; i++)
288 	{
289 		ep = entities[i].epairs;
290 		if (!ep)
291 			continue;	// ent got removed
292 
293 		strcat (end,"{\n");
294 		end += 2;
295 
296 		for (ep = entities[i].epairs ; ep ; ep = ep->next)
297 		{
298 			sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
299 			strcat (end, line);
300 			end += strlen(line);
301 		}
302 		strcat (end,"}\n");
303 		end += 2;
304 
305 		if (end > buf + MAX_MAP_ENTSTRING)
306 			COM_Error ("Entity text too long");
307 	}
308 	entdatasize = end - buf + 1;
309 }
310 
311