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