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