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