1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 /*****************************************************************************
24 * name: be_aas_bspq3.c
25 *
26 * desc: BSP, Environment Sampling
27 *
28 * $Archive: /MissionPack/code/botlib/be_aas_bspq3.c $
29 *
30 *****************************************************************************/
31
32 #include "../qcommon/q_shared.h"
33 #include "l_memory.h"
34 #include "l_script.h"
35 #include "l_precomp.h"
36 #include "l_struct.h"
37 #include "aasfile.h"
38 #include "botlib.h"
39 #include "be_aas.h"
40 #include "be_aas_funcs.h"
41 #include "be_aas_def.h"
42
43 extern botlib_import_t botimport;
44
45 //#define TRACE_DEBUG
46
47 #define ON_EPSILON 0.005
48 //#define DEG2RAD( a ) (( a * M_PI ) / 180.0F)
49
50 #define MAX_BSPENTITIES 2048
51
52 typedef struct rgb_s
53 {
54 int red;
55 int green;
56 int blue;
57 } rgb_t;
58
59 //bsp entity epair
60 typedef struct bsp_epair_s
61 {
62 char *key;
63 char *value;
64 struct bsp_epair_s *next;
65 } bsp_epair_t;
66
67 //bsp data entity
68 typedef struct bsp_entity_s
69 {
70 bsp_epair_t *epairs;
71 } bsp_entity_t;
72
73 //id Sofware BSP data
74 typedef struct bsp_s
75 {
76 //true when bsp file is loaded
77 int loaded;
78 //entity data
79 int entdatasize;
80 char *dentdata;
81 //bsp entities
82 int numentities;
83 bsp_entity_t entities[MAX_BSPENTITIES];
84 } bsp_t;
85
86 //global bsp
87 bsp_t bspworld;
88
89
90 #ifdef BSP_DEBUG
91 typedef struct cname_s
92 {
93 int value;
94 char *name;
95 } cname_t;
96
97 cname_t contentnames[] =
98 {
99 {CONTENTS_SOLID,"CONTENTS_SOLID"},
100 {CONTENTS_WINDOW,"CONTENTS_WINDOW"},
101 {CONTENTS_AUX,"CONTENTS_AUX"},
102 {CONTENTS_LAVA,"CONTENTS_LAVA"},
103 {CONTENTS_SLIME,"CONTENTS_SLIME"},
104 {CONTENTS_WATER,"CONTENTS_WATER"},
105 {CONTENTS_MIST,"CONTENTS_MIST"},
106 {LAST_VISIBLE_CONTENTS,"LAST_VISIBLE_CONTENTS"},
107
108 {CONTENTS_AREAPORTAL,"CONTENTS_AREAPORTAL"},
109 {CONTENTS_PLAYERCLIP,"CONTENTS_PLAYERCLIP"},
110 {CONTENTS_MONSTERCLIP,"CONTENTS_MONSTERCLIP"},
111 {CONTENTS_CURRENT_0,"CONTENTS_CURRENT_0"},
112 {CONTENTS_CURRENT_90,"CONTENTS_CURRENT_90"},
113 {CONTENTS_CURRENT_180,"CONTENTS_CURRENT_180"},
114 {CONTENTS_CURRENT_270,"CONTENTS_CURRENT_270"},
115 {CONTENTS_CURRENT_UP,"CONTENTS_CURRENT_UP"},
116 {CONTENTS_CURRENT_DOWN,"CONTENTS_CURRENT_DOWN"},
117 {CONTENTS_ORIGIN,"CONTENTS_ORIGIN"},
118 {CONTENTS_MONSTER,"CONTENTS_MONSTER"},
119 {CONTENTS_DEADMONSTER,"CONTENTS_DEADMONSTER"},
120 {CONTENTS_DETAIL,"CONTENTS_DETAIL"},
121 {CONTENTS_TRANSLUCENT,"CONTENTS_TRANSLUCENT"},
122 {CONTENTS_LADDER,"CONTENTS_LADDER"},
123 {0, 0}
124 };
125
PrintContents(int contents)126 void PrintContents(int contents)
127 {
128 int i;
129
130 for (i = 0; contentnames[i].value; i++)
131 {
132 if (contents & contentnames[i].value)
133 {
134 botimport.Print(PRT_MESSAGE, "%s\n", contentnames[i].name);
135 } //end if
136 } //end for
137 } //end of the function PrintContents
138
139 #endif // BSP_DEBUG
140 //===========================================================================
141 // traces axial boxes of any size through the world
142 //
143 // Parameter: -
144 // Returns: -
145 // Changes Globals: -
146 //===========================================================================
AAS_Trace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,int passent,int contentmask)147 bsp_trace_t AAS_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask)
148 {
149 bsp_trace_t bsptrace;
150 botimport.Trace(&bsptrace, start, mins, maxs, end, passent, contentmask);
151 return bsptrace;
152 } //end of the function AAS_Trace
153 //===========================================================================
154 // returns the contents at the given point
155 //
156 // Parameter: -
157 // Returns: -
158 // Changes Globals: -
159 //===========================================================================
AAS_PointContents(vec3_t point)160 int AAS_PointContents(vec3_t point)
161 {
162 return botimport.PointContents(point);
163 } //end of the function AAS_PointContents
164 //===========================================================================
165 //
166 // Parameter: -
167 // Returns: -
168 // Changes Globals: -
169 //===========================================================================
AAS_EntityCollision(int entnum,vec3_t start,vec3_t boxmins,vec3_t boxmaxs,vec3_t end,int contentmask,bsp_trace_t * trace)170 qboolean AAS_EntityCollision(int entnum,
171 vec3_t start, vec3_t boxmins, vec3_t boxmaxs, vec3_t end,
172 int contentmask, bsp_trace_t *trace)
173 {
174 bsp_trace_t enttrace;
175
176 botimport.EntityTrace(&enttrace, start, boxmins, boxmaxs, end, entnum, contentmask);
177 if (enttrace.fraction < trace->fraction)
178 {
179 Com_Memcpy(trace, &enttrace, sizeof(bsp_trace_t));
180 return qtrue;
181 } //end if
182 return qfalse;
183 } //end of the function AAS_EntityCollision
184 //===========================================================================
185 // returns true if in Potentially Hearable Set
186 //
187 // Parameter: -
188 // Returns: -
189 // Changes Globals: -
190 //===========================================================================
AAS_inPVS(vec3_t p1,vec3_t p2)191 qboolean AAS_inPVS(vec3_t p1, vec3_t p2)
192 {
193 return botimport.inPVS(p1, p2);
194 } //end of the function AAS_InPVS
195 //===========================================================================
196 // returns true if in Potentially Visible Set
197 //
198 // Parameter: -
199 // Returns: -
200 // Changes Globals: -
201 //===========================================================================
AAS_inPHS(vec3_t p1,vec3_t p2)202 qboolean AAS_inPHS(vec3_t p1, vec3_t p2)
203 {
204 return qtrue;
205 } //end of the function AAS_inPHS
206 //===========================================================================
207 //
208 // Parameter: -
209 // Returns: -
210 // Changes Globals: -
211 //===========================================================================
AAS_BSPModelMinsMaxsOrigin(int modelnum,vec3_t angles,vec3_t mins,vec3_t maxs,vec3_t origin)212 void AAS_BSPModelMinsMaxsOrigin(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin)
213 {
214 botimport.BSPModelMinsMaxsOrigin(modelnum, angles, mins, maxs, origin);
215 } //end of the function AAS_BSPModelMinsMaxs
216 //===========================================================================
217 // unlinks the entity from all leaves
218 //
219 // Parameter: -
220 // Returns: -
221 // Changes Globals: -
222 //===========================================================================
AAS_UnlinkFromBSPLeaves(bsp_link_t * leaves)223 void AAS_UnlinkFromBSPLeaves(bsp_link_t *leaves)
224 {
225 } //end of the function AAS_UnlinkFromBSPLeaves
226 //===========================================================================
227 //
228 // Parameter: -
229 // Returns: -
230 // Changes Globals: -
231 //===========================================================================
AAS_BSPLinkEntity(vec3_t absmins,vec3_t absmaxs,int entnum,int modelnum)232 bsp_link_t *AAS_BSPLinkEntity(vec3_t absmins, vec3_t absmaxs, int entnum, int modelnum)
233 {
234 return NULL;
235 } //end of the function AAS_BSPLinkEntity
236 //===========================================================================
237 //
238 // Parameter: -
239 // Returns: -
240 // Changes Globals: -
241 //===========================================================================
AAS_BoxEntities(vec3_t absmins,vec3_t absmaxs,int * list,int maxcount)242 int AAS_BoxEntities(vec3_t absmins, vec3_t absmaxs, int *list, int maxcount)
243 {
244 return 0;
245 } //end of the function AAS_BoxEntities
246 //===========================================================================
247 //
248 // Parameter: -
249 // Returns: -
250 // Changes Globals: -
251 //===========================================================================
AAS_NextBSPEntity(int ent)252 int AAS_NextBSPEntity(int ent)
253 {
254 ent++;
255 if (ent >= 1 && ent < bspworld.numentities) return ent;
256 return 0;
257 } //end of the function AAS_NextBSPEntity
258 //===========================================================================
259 //
260 // Parameter: -
261 // Returns: -
262 // Changes Globals: -
263 //===========================================================================
AAS_BSPEntityInRange(int ent)264 int AAS_BSPEntityInRange(int ent)
265 {
266 if (ent <= 0 || ent >= bspworld.numentities)
267 {
268 botimport.Print(PRT_MESSAGE, "bsp entity out of range\n");
269 return qfalse;
270 } //end if
271 return qtrue;
272 } //end of the function AAS_BSPEntityInRange
273 //===========================================================================
274 //
275 // Parameter: -
276 // Returns: -
277 // Changes Globals: -
278 //===========================================================================
AAS_ValueForBSPEpairKey(int ent,char * key,char * value,int size)279 int AAS_ValueForBSPEpairKey(int ent, char *key, char *value, int size)
280 {
281 bsp_epair_t *epair;
282
283 value[0] = '\0';
284 if (!AAS_BSPEntityInRange(ent)) return qfalse;
285 for (epair = bspworld.entities[ent].epairs; epair; epair = epair->next)
286 {
287 if (!strcmp(epair->key, key))
288 {
289 strncpy(value, epair->value, size-1);
290 value[size-1] = '\0';
291 return qtrue;
292 } //end if
293 } //end for
294 return qfalse;
295 } //end of the function AAS_FindBSPEpair
296 //===========================================================================
297 //
298 // Parameter: -
299 // Returns: -
300 // Changes Globals: -
301 //===========================================================================
AAS_VectorForBSPEpairKey(int ent,char * key,vec3_t v)302 int AAS_VectorForBSPEpairKey(int ent, char *key, vec3_t v)
303 {
304 char buf[MAX_EPAIRKEY];
305 double v1, v2, v3;
306
307 VectorClear(v);
308 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
309 //scanf into doubles, then assign, so it is vec_t size independent
310 v1 = v2 = v3 = 0;
311 sscanf(buf, "%lf %lf %lf", &v1, &v2, &v3);
312 v[0] = v1;
313 v[1] = v2;
314 v[2] = v3;
315 return qtrue;
316 } //end of the function AAS_VectorForBSPEpairKey
317 //===========================================================================
318 //
319 // Parameter: -
320 // Returns: -
321 // Changes Globals: -
322 //===========================================================================
AAS_FloatForBSPEpairKey(int ent,char * key,float * value)323 int AAS_FloatForBSPEpairKey(int ent, char *key, float *value)
324 {
325 char buf[MAX_EPAIRKEY];
326
327 *value = 0;
328 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
329 *value = atof(buf);
330 return qtrue;
331 } //end of the function AAS_FloatForBSPEpairKey
332 //===========================================================================
333 //
334 // Parameter: -
335 // Returns: -
336 // Changes Globals: -
337 //===========================================================================
AAS_IntForBSPEpairKey(int ent,char * key,int * value)338 int AAS_IntForBSPEpairKey(int ent, char *key, int *value)
339 {
340 char buf[MAX_EPAIRKEY];
341
342 *value = 0;
343 if (!AAS_ValueForBSPEpairKey(ent, key, buf, MAX_EPAIRKEY)) return qfalse;
344 *value = atoi(buf);
345 return qtrue;
346 } //end of the function AAS_IntForBSPEpairKey
347 //===========================================================================
348 //
349 // Parameter: -
350 // Returns: -
351 // Changes Globals: -
352 //===========================================================================
AAS_FreeBSPEntities(void)353 void AAS_FreeBSPEntities(void)
354 {
355 int i;
356 bsp_entity_t *ent;
357 bsp_epair_t *epair, *nextepair;
358
359 for (i = 1; i < bspworld.numentities; i++)
360 {
361 ent = &bspworld.entities[i];
362 for (epair = ent->epairs; epair; epair = nextepair)
363 {
364 nextepair = epair->next;
365 //
366 if (epair->key) FreeMemory(epair->key);
367 if (epair->value) FreeMemory(epair->value);
368 FreeMemory(epair);
369 } //end for
370 } //end for
371 bspworld.numentities = 0;
372 } //end of the function AAS_FreeBSPEntities
373 //===========================================================================
374 //
375 // Parameter: -
376 // Returns: -
377 // Changes Globals: -
378 //===========================================================================
AAS_ParseBSPEntities(void)379 void AAS_ParseBSPEntities(void)
380 {
381 script_t *script;
382 token_t token;
383 bsp_entity_t *ent;
384 bsp_epair_t *epair;
385
386 script = LoadScriptMemory(bspworld.dentdata, bspworld.entdatasize, "entdata");
387 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES|SCFL_NOSTRINGESCAPECHARS);//SCFL_PRIMITIVE);
388
389 bspworld.numentities = 1;
390
391 while(PS_ReadToken(script, &token))
392 {
393 if (strcmp(token.string, "{"))
394 {
395 ScriptError(script, "invalid %s\n", token.string);
396 AAS_FreeBSPEntities();
397 FreeScript(script);
398 return;
399 } //end if
400 if (bspworld.numentities >= MAX_BSPENTITIES)
401 {
402 botimport.Print(PRT_MESSAGE, "too many entities in BSP file\n");
403 break;
404 } //end if
405 ent = &bspworld.entities[bspworld.numentities];
406 bspworld.numentities++;
407 ent->epairs = NULL;
408 while(PS_ReadToken(script, &token))
409 {
410 if (!strcmp(token.string, "}")) break;
411 epair = (bsp_epair_t *) GetClearedHunkMemory(sizeof(bsp_epair_t));
412 epair->next = ent->epairs;
413 ent->epairs = epair;
414 if (token.type != TT_STRING)
415 {
416 ScriptError(script, "invalid %s\n", token.string);
417 AAS_FreeBSPEntities();
418 FreeScript(script);
419 return;
420 } //end if
421 StripDoubleQuotes(token.string);
422 epair->key = (char *) GetHunkMemory(strlen(token.string) + 1);
423 strcpy(epair->key, token.string);
424 if (!PS_ExpectTokenType(script, TT_STRING, 0, &token))
425 {
426 AAS_FreeBSPEntities();
427 FreeScript(script);
428 return;
429 } //end if
430 StripDoubleQuotes(token.string);
431 epair->value = (char *) GetHunkMemory(strlen(token.string) + 1);
432 strcpy(epair->value, token.string);
433 } //end while
434 if (strcmp(token.string, "}"))
435 {
436 ScriptError(script, "missing }\n");
437 AAS_FreeBSPEntities();
438 FreeScript(script);
439 return;
440 } //end if
441 } //end while
442 FreeScript(script);
443 } //end of the function AAS_ParseBSPEntities
444 //===========================================================================
445 //
446 // Parameter: -
447 // Returns: -
448 // Changes Globals: -
449 //===========================================================================
AAS_BSPTraceLight(vec3_t start,vec3_t end,vec3_t endpos,int * red,int * green,int * blue)450 int AAS_BSPTraceLight(vec3_t start, vec3_t end, vec3_t endpos, int *red, int *green, int *blue)
451 {
452 return 0;
453 } //end of the function AAS_BSPTraceLight
454 //===========================================================================
455 //
456 // Parameter: -
457 // Returns: -
458 // Changes Globals: -
459 //===========================================================================
AAS_DumpBSPData(void)460 void AAS_DumpBSPData(void)
461 {
462 AAS_FreeBSPEntities();
463
464 if (bspworld.dentdata) FreeMemory(bspworld.dentdata);
465 bspworld.dentdata = NULL;
466 bspworld.entdatasize = 0;
467 //
468 bspworld.loaded = qfalse;
469 Com_Memset( &bspworld, 0, sizeof(bspworld) );
470 } //end of the function AAS_DumpBSPData
471 //===========================================================================
472 // load an bsp file
473 //
474 // Parameter: -
475 // Returns: -
476 // Changes Globals: -
477 //===========================================================================
AAS_LoadBSPFile(void)478 int AAS_LoadBSPFile(void)
479 {
480 AAS_DumpBSPData();
481 bspworld.entdatasize = strlen(botimport.BSPEntityData()) + 1;
482 bspworld.dentdata = (char *) GetClearedHunkMemory(bspworld.entdatasize);
483 Com_Memcpy(bspworld.dentdata, botimport.BSPEntityData(), bspworld.entdatasize);
484 AAS_ParseBSPEntities();
485 bspworld.loaded = qtrue;
486 return BLERR_NOERROR;
487 } //end of the function AAS_LoadBSPFile
488