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_interface.c
32  *
33  * desc:		bot library interface
34  *
35  *
36  *****************************************************************************/
37 
38 #include "../qcommon/q_shared.h"
39 #include "l_memory.h"
40 #include "l_log.h"
41 #include "l_libvar.h"
42 #include "l_script.h"
43 #include "l_precomp.h"
44 #include "l_struct.h"
45 #include "aasfile.h"
46 #include "botlib.h"
47 #include "be_aas.h"
48 #include "be_aas_funcs.h"
49 #include "be_aas_def.h"
50 #include "be_interface.h"
51 
52 #include "be_ea.h"
53 #include "be_ai_weight.h"
54 #include "be_ai_goal.h"
55 #include "be_ai_move.h"
56 #include "be_ai_weap.h"
57 #include "be_ai_chat.h"
58 #include "be_ai_char.h"
59 #include "be_ai_gen.h"
60 
61 //library globals in a structure
62 botlib_globals_t botlibglobals;
63 
64 botlib_export_t be_botlib_export;
65 botlib_import_t botimport;
66 //
67 int botDeveloper;
68 //qtrue if the library is setup
69 int botlibsetup = qfalse;
70 
71 //===========================================================================
72 //
73 // several functions used by the exported functions
74 //
75 //===========================================================================
76 
77 //===========================================================================
78 //
79 // Parameter:				-
80 // Returns:					-
81 // Changes Globals:		-
82 //===========================================================================
83 // Ridah, faster Win32 code
84 #ifdef _WIN32
85 #include <windows.h>
86 #endif
87 
Sys_MilliSeconds(void)88 int Sys_MilliSeconds( void ) {
89 // Ridah, faster Win32 code
90 #ifdef _WIN32
91 	int sys_curtime;
92 	static qboolean initialized = qfalse;
93 	static int sys_timeBase;
94 
95 	if ( !initialized ) {
96 		sys_timeBase = timeGetTime();
97 		initialized = qtrue;
98 	}
99 	sys_curtime = timeGetTime() - sys_timeBase;
100 
101 	return sys_curtime;
102 #else
103 	return clock() * 1000 / CLOCKS_PER_SEC;
104 #endif
105 } //end of the function Sys_MilliSeconds
106 //===========================================================================
107 //
108 // Parameter:				-
109 // Returns:					-
110 // Changes Globals:		-
111 //===========================================================================
ValidClientNumber(int num,char * str)112 qboolean ValidClientNumber( int num, char *str ) {
113 	if ( num < 0 || num > botlibglobals.maxclients ) {
114 		//weird: the disabled stuff results in a crash
115 		botimport.Print( PRT_ERROR, "%s: invalid client number %d, [0, %d]\n",
116 						 str, num, botlibglobals.maxclients );
117 		return qfalse;
118 	} //end if
119 	return qtrue;
120 } //end of the function BotValidateClientNumber
121 //===========================================================================
122 //
123 // Parameter:				-
124 // Returns:					-
125 // Changes Globals:		-
126 //===========================================================================
ValidEntityNumber(int num,char * str)127 qboolean ValidEntityNumber( int num, char *str ) {
128 	if ( num < 0 || num > botlibglobals.maxentities ) {
129 		botimport.Print( PRT_ERROR, "%s: invalid entity number %d, [0, %d]\n",
130 						 str, num, botlibglobals.maxentities );
131 		return qfalse;
132 	} //end if
133 	return qtrue;
134 } //end of the function BotValidateClientNumber
135 //===========================================================================
136 //
137 // Parameter:				-
138 // Returns:					-
139 // Changes Globals:		-
140 //===========================================================================
BotLibSetup(char * str)141 qboolean BotLibSetup( char *str ) {
142 //	return qtrue;
143 
144 	if ( !botlibglobals.botlibsetup ) {
145 		botimport.Print( PRT_ERROR, "%s: bot library used before being setup\n", str );
146 		return qfalse;
147 	} //end if
148 	return qtrue;
149 } //end of the function BotLibSetup
150 //===========================================================================
151 //
152 // Parameter:				-
153 // Returns:					-
154 // Changes Globals:		-
155 //===========================================================================
Export_BotLibSetup(void)156 int Export_BotLibSetup( void ) {
157 	int errnum;
158 
159 	botDeveloper = LibVarGetValue("bot_developer");
160  	memset( &botlibglobals, 0, sizeof(botlibglobals) );
161 	//initialize byte swapping (litte endian etc.)
162 //	Swap_Init();
163 
164 	if( botDeveloper )
165 	{
166 		Log_Open( "botlib.log" );
167 	}
168 
169 	botimport.Print( PRT_MESSAGE, "------- BotLib Initialization -------\n" );
170 	//
171 	botlibglobals.maxclients = (int) LibVarValue( "maxclients", "128" );
172 	botlibglobals.maxentities = (int) LibVarValue( "maxentities", "2048" );
173 
174 	errnum = AAS_Setup();           //be_aas_main.c
175 	if ( errnum != BLERR_NOERROR ) {
176 		return errnum;
177 	}
178 	errnum = EA_Setup();            //be_ea.c
179 	if ( errnum != BLERR_NOERROR ) {
180 		return errnum;
181 	}
182 //	errnum = BotSetupWeaponAI();	//be_ai_weap.c
183 //	if (errnum != BLERR_NOERROR)return errnum;
184 //	errnum = BotSetupGoalAI();		//be_ai_goal.c
185 //	if (errnum != BLERR_NOERROR) return errnum;
186 //	errnum = BotSetupChatAI();		//be_ai_chat.c
187 //	if (errnum != BLERR_NOERROR) return errnum;
188 	errnum = BotSetupMoveAI();      //be_ai_move.c
189 	if ( errnum != BLERR_NOERROR ) {
190 		return errnum;
191 	}
192 
193 	botlibsetup = qtrue;
194 	botlibglobals.botlibsetup = qtrue;
195 
196 	return BLERR_NOERROR;
197 } //end of the function Export_BotLibSetup
198 //===========================================================================
199 //
200 // Parameter:				-
201 // Returns:					-
202 // Changes Globals:		-
203 //===========================================================================
Export_BotLibShutdown(void)204 int Export_BotLibShutdown( void ) {
205 	static int recursive = 0;
206 
207 	if ( !BotLibSetup( "BotLibShutdown" ) ) {
208 		return BLERR_LIBRARYNOTSETUP;
209 	}
210 	//
211 	if ( recursive ) {
212 		return BLERR_NOERROR;
213 	}
214 	recursive = 1;
215 	// shutdown all AI subsystems
216 	BotShutdownChatAI();        //be_ai_chat.c
217 	BotShutdownMoveAI();        //be_ai_move.c
218 	BotShutdownGoalAI();        //be_ai_goal.c
219 	BotShutdownWeaponAI();      //be_ai_weap.c
220 	BotShutdownWeights();       //be_ai_weight.c
221 	BotShutdownCharacters();    //be_ai_char.c
222 	// shutdown AAS
223 	AAS_Shutdown();
224 	// shutdown bot elemantary actions
225 	EA_Shutdown();
226 	// free all libvars
227 	LibVarDeAllocAll();
228 	// remove all global defines from the pre compiler
229 	PC_RemoveAllGlobalDefines();
230 	// shut down library log file
231 	Log_Shutdown();
232 	//
233 	botlibsetup = qfalse;
234 	botlibglobals.botlibsetup = qfalse;
235 	recursive = 0;
236 	// print any files still open
237 	PC_CheckOpenSourceHandles();
238 	//
239 #ifdef _DEBUG
240 	Log_AlwaysOpen( "memory.log" );
241 	PrintMemoryLabels();
242 	Log_Shutdown();
243 #endif
244 	return BLERR_NOERROR;
245 } //end of the function Export_BotLibShutdown
246 //===========================================================================
247 //
248 // Parameter:				-
249 // Returns:					-
250 // Changes Globals:		-
251 //===========================================================================
Export_BotLibVarSet(const char * var_name,const char * value)252 int Export_BotLibVarSet( const char *var_name, const char *value ) {
253 	LibVarSet( var_name, value );
254 	return BLERR_NOERROR;
255 } //end of the function Export_BotLibVarSet
256 //===========================================================================
257 //
258 // Parameter:				-
259 // Returns:					-
260 // Changes Globals:		-
261 //===========================================================================
Export_BotLibVarGet(const char * var_name,char * value,int size)262 int Export_BotLibVarGet( const char *var_name, char *value, int size ) {
263 	char *varvalue;
264 
265 	varvalue = LibVarGetString( var_name );
266 	strncpy( value, varvalue, size - 1 );
267 	value[size - 1] = '\0';
268 	return BLERR_NOERROR;
269 } //end of the function Export_BotLibVarGet
270 //===========================================================================
271 //
272 // Parameter:				-
273 // Returns:					-
274 // Changes Globals:		-
275 //===========================================================================
Export_BotLibStartFrame(float time)276 int Export_BotLibStartFrame( float time ) {
277 	if ( !BotLibSetup( "BotStartFrame" ) ) {
278 		return BLERR_LIBRARYNOTSETUP;
279 	}
280 	return AAS_StartFrame( time );
281 } //end of the function Export_BotLibStartFrame
282 //===========================================================================
283 //
284 // Parameter:				-
285 // Returns:					-
286 // Changes Globals:		-
287 //===========================================================================
Export_BotLibLoadMap(const char * mapname)288 int Export_BotLibLoadMap( const char *mapname ) {
289 #ifdef DEBUG
290 	int starttime = Sys_MilliSeconds();
291 #endif
292 	int errnum;
293 
294 	if ( !BotLibSetup( "BotLoadMap" ) ) {
295 		return BLERR_LIBRARYNOTSETUP;
296 	}
297 	//
298 	botimport.Print( PRT_MESSAGE, "------------ Map Loading ------------\n" );
299 	//startup AAS for the current map, model and sound index
300 	errnum = AAS_LoadMap( mapname );
301 	if ( errnum != BLERR_NOERROR ) {
302 		return errnum;
303 	}
304 	//initialize the items in the level
305 	BotInitLevelItems();        //be_ai_goal.h
306 	BotSetBrushModelTypes();    //be_ai_move.h
307 	//
308 	botimport.Print( PRT_MESSAGE, "-------------------------------------\n" );
309 #ifdef DEBUG
310 	botimport.Print( PRT_MESSAGE, "map loaded in %d msec\n", Sys_MilliSeconds() - starttime );
311 #endif
312 	//
313 	return BLERR_NOERROR;
314 } //end of the function Export_BotLibLoadMap
315 //===========================================================================
316 //
317 // Parameter:				-
318 // Returns:					-
319 // Changes Globals:		-
320 //===========================================================================
Export_BotLibUpdateEntity(int ent,bot_entitystate_t * state)321 int Export_BotLibUpdateEntity( int ent, bot_entitystate_t *state ) {
322 	if ( !BotLibSetup( "BotUpdateEntity" ) ) {
323 		return BLERR_LIBRARYNOTSETUP;
324 	}
325 	if ( !ValidEntityNumber( ent, "BotUpdateEntity" ) ) {
326 		return BLERR_INVALIDENTITYNUMBER;
327 	}
328 
329 	return AAS_UpdateEntity( ent, state );
330 } //end of the function Export_BotLibUpdateEntity
331 //===========================================================================
332 //
333 // Parameter:				-
334 // Returns:					-
335 // Changes Globals:		-
336 //===========================================================================
337 void AAS_TestMovementPrediction( int entnum, vec3_t origin, vec3_t dir );
338 void ElevatorBottomCenter( aas_reachability_t *reach, vec3_t bottomcenter );
339 int BotGetReachabilityToGoal( vec3_t origin, int areanum, int entnum,
340 							  int lastgoalareanum, int lastareanum,
341 							  int *avoidreach, float *avoidreachtimes, int *avoidreachtries,
342 							  bot_goal_t *goal, int travelflags );
343 
344 int AAS_PointLight( vec3_t origin, int *red, int *green, int *blue );
345 
346 int AAS_TraceAreas( vec3_t start, vec3_t end, int *areas, vec3_t *points, int maxareas );
347 
348 int AAS_Reachability_WeaponJump( int area1num, int area2num );
349 
350 int BotFuzzyPointReachabilityArea( vec3_t origin );
351 
352 float BotGapDistance( vec3_t origin, vec3_t hordir, int entnum );
353 
354 int AAS_NearestHideArea( int srcnum, vec3_t origin, int areanum, int enemynum, vec3_t enemyorigin, int enemyareanum, int travelflags );
355 
356 int AAS_FindAttackSpotWithinRange( int srcnum, int rangenum, int enemynum, float rangedist, int travelflags, float *outpos );
357 
358 qboolean AAS_GetRouteFirstVisPos( vec3_t srcpos, vec3_t destpos, int travelflags, vec3_t retpos );
359 
360 void AAS_SetAASBlockingEntity( vec3_t absmin, vec3_t absmax, qboolean blocking );
361 
BotExportTest(int parm0,char * parm1,vec3_t parm2,vec3_t parm3)362 int BotExportTest( int parm0, char *parm1, vec3_t parm2, vec3_t parm3 ) {
363 
364 //	return AAS_PointLight(parm2, NULL, NULL, NULL);
365 
366 #ifdef DEBUG
367 	static int area = -1;
368 	static int line[2];
369 	int newarea, i, highlightarea, bot_testhidepos, hideposarea, bot_testroutevispos;
370 //	int reachnum;
371 	vec3_t eye, forward, right, end, origin;
372 //	vec3_t bottomcenter;
373 //	aas_trace_t trace;
374 //	aas_face_t *face;
375 //	aas_entity_t *ent;
376 //	bsp_trace_t bsptrace;
377 //	aas_reachability_t reach;
378 //	bot_goal_t goal;
379 
380 //	clock_t start_time, end_time;
381 	vec3_t mins = {-16, -16, -24};
382 	vec3_t maxs = {16, 16, 32};
383 //	int areas[10], numareas;
384 
385 
386 	//return 0;
387 
388 	if ( !( *aasworld ).loaded ) {
389 		return 0;
390 	}
391 	AAS_SetCurrentWorld( 0 );
392 
393 	for ( i = 0; i < 2; i++ ) if ( !line[i] ) {
394 			line[i] = botimport.DebugLineCreate();
395 		}
396 
397 //	AAS_ClearShownDebugLines();
398 	bot_testhidepos = LibVarGetValue( "bot_testhidepos" );
399 	if ( bot_testhidepos ) {
400 		VectorCopy( parm2, origin );
401 		newarea = BotFuzzyPointReachabilityArea( origin );
402 		if ( parm0 & 1 ) {
403 			botlibglobals.goalareanum = newarea;
404 			VectorCopy( origin, botlibglobals.goalorigin );
405 			botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
406 							 origin[0], origin[1], origin[2], newarea );
407 		} //end if
408 		AAS_ClearShownPolygons();
409 		AAS_ClearShownDebugLines();
410 		hideposarea = AAS_NearestHideArea( -1, origin, AAS_PointAreaNum( origin ), 0,
411 										   botlibglobals.goalorigin, botlibglobals.goalareanum, TFL_DEFAULT );
412 
413 		if ( bot_testhidepos > 1 ) {
414 			if ( hideposarea ) {
415 				botimport.Print( PRT_MESSAGE, "hidepos (%i) %2.1f %2.1f %2.1f\n",
416 								 hideposarea,
417 								 ( *aasworld ).areawaypoints[hideposarea][0],
418 								 ( *aasworld ).areawaypoints[hideposarea][1],
419 								 ( *aasworld ).areawaypoints[hideposarea][2] );
420 			} else {
421 				botimport.Print( PRT_MESSAGE, "no hidepos found\n" );
422 			}
423 		}
424 
425 		//area we are currently in
426 		AAS_ShowAreaPolygons( newarea, 1, qtrue );
427 		//enemy position
428 		AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
429 		//area we should go hide
430 		AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
431 		return 0;
432 	}
433 
434 	bot_testroutevispos = LibVarGetValue( "bot_testroutevispos" );
435 	if ( bot_testroutevispos ) {
436 		VectorCopy( parm2, origin );
437 		newarea = BotFuzzyPointReachabilityArea( origin );
438 		if ( parm0 & 1 ) {
439 			botlibglobals.goalareanum = newarea;
440 			VectorCopy( origin, botlibglobals.goalorigin );
441 			botimport.Print( PRT_MESSAGE, "new enemy position %2.1f %2.1f %2.1f area %d\n",
442 							 origin[0], origin[1], origin[2], newarea );
443 		} //end if
444 		AAS_ClearShownPolygons();
445 		AAS_ClearShownDebugLines();
446 		AAS_GetRouteFirstVisPos( botlibglobals.goalorigin, origin, TFL_DEFAULT, eye );
447 		//area we are currently in
448 		AAS_ShowAreaPolygons( newarea, 1, qtrue );
449 		//enemy position
450 		AAS_ShowAreaPolygons( botlibglobals.goalareanum, 2, qtrue );
451 		//area that is visible in path from enemy pos
452 		hideposarea = BotFuzzyPointReachabilityArea( eye );
453 		AAS_ShowAreaPolygons( hideposarea, 4, qtrue );
454 		return 0;
455 	}
456 
457 	//if (AAS_AgainstLadder(parm2)) botimport.Print(PRT_MESSAGE, "against ladder\n");
458 	//BotOnGround(parm2, PRESENCE_NORMAL, 1, &newarea, &newarea);
459 	//botimport.Print(PRT_MESSAGE, "%f %f %f\n", parm2[0], parm2[1], parm2[2]);
460 	//*
461 	highlightarea = LibVarGetValue( "bot_highlightarea" );
462 	if ( highlightarea > 0 ) {
463 		newarea = highlightarea;
464 	} //end if
465 	else
466 	{
467 		VectorCopy( parm2, origin );
468 		origin[2] += 0.5;
469 		//newarea = AAS_PointAreaNum(origin);
470 		newarea = BotFuzzyPointReachabilityArea( origin );
471 	} //end else
472 
473 	botimport.Print( PRT_MESSAGE, "\rtravel time to goal (%d) = %d  ", botlibglobals.goalareanum,
474 					 AAS_AreaTravelTimeToGoalArea( newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT ) );
475 	//newarea = BotReachabilityArea(origin, qtrue);
476 	if ( newarea != area ) {
477 		botimport.Print( PRT_MESSAGE, "origin = %f, %f, %f\n", origin[0], origin[1], origin[2] );
478 		area = newarea;
479 		botimport.Print( PRT_MESSAGE, "new area %d, cluster %d, presence type %d\n",
480 						 area, AAS_AreaCluster( area ), AAS_PointPresenceType( origin ) );
481 		if ( ( *aasworld ).areasettings[area].areaflags & AREA_LIQUID ) {
482 			botimport.Print( PRT_MESSAGE, "liquid area\n" );
483 		} //end if
484 		botimport.Print( PRT_MESSAGE, "area contents: " );
485 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_WATER ) {
486 			botimport.Print( PRT_MESSAGE, "water " );
487 		} //end if
488 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_LAVA ) {
489 			botimport.Print( PRT_MESSAGE, "lava " );
490 		} //end if
491 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_SLIME ) {
492 //			botimport.Print(PRT_MESSAGE, "slime ");
493 			botimport.Print( PRT_MESSAGE, "slag " );
494 		} //end if
495 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_JUMPPAD ) {
496 			botimport.Print( PRT_MESSAGE, "jump pad " );
497 		} //end if
498 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_CLUSTERPORTAL ) {
499 			botimport.Print( PRT_MESSAGE, "cluster portal " );
500 		} //end if
501 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_DONOTENTER ) {
502 			botimport.Print( PRT_MESSAGE, "do not enter " );
503 		} //end if
504 		if ( ( *aasworld ).areasettings[area].contents & AREACONTENTS_DONOTENTER_LARGE ) {
505 			botimport.Print( PRT_MESSAGE, "do not enter large " );
506 		} //end if
507 		if ( !( *aasworld ).areasettings[area].contents ) {
508 			botimport.Print( PRT_MESSAGE, "empty " );
509 		} //end if
510 		if ( ( *aasworld ).areasettings[area].areaflags & AREA_DISABLED ) {
511 			botimport.Print( PRT_MESSAGE, "DISABLED" );
512 		} //end if
513 		botimport.Print( PRT_MESSAGE, "\n" );
514 		botimport.Print( PRT_MESSAGE, "travel time to goal (%d) = %d\n", botlibglobals.goalareanum,
515 						 AAS_AreaTravelTimeToGoalArea( newarea, origin, botlibglobals.goalareanum, TFL_DEFAULT | TFL_ROCKETJUMP ) );
516 		/*
517 		VectorCopy(origin, end);
518 		end[2] += 5;
519 		numareas = AAS_TraceAreas(origin, end, areas, NULL, 10);
520 		AAS_TraceClientBBox(origin, end, PRESENCE_CROUCH, -1);
521 		botimport.Print(PRT_MESSAGE, "num areas = %d, area = %d\n", numareas, areas[0]);
522 		*/
523 		/*
524 		botlibglobals.goalareanum = newarea;
525 		VectorCopy(parm2, botlibglobals.goalorigin);
526 		botimport.Print(PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
527 								origin[0], origin[1], origin[2], newarea);
528 		*/
529 	} //end if
530 	  //*
531 	if ( parm0 & 1 ) {
532 		botlibglobals.goalareanum = newarea;
533 		VectorCopy( parm2, botlibglobals.goalorigin );
534 		botimport.Print( PRT_MESSAGE, "new goal %2.1f %2.1f %2.1f area %d\n",
535 						 origin[0], origin[1], origin[2], newarea );
536 	} //end if*/
537 //	if (parm0 & BUTTON_USE)
538 //	{
539 //		botlibglobals.runai = !botlibglobals.runai;
540 //		if (botlibglobals.runai) botimport.Print(PRT_MESSAGE, "started AI\n");
541 //		else botimport.Print(PRT_MESSAGE, "stopped AI\n");
542 	//* /
543 	/*
544 	goal.areanum = botlibglobals.goalareanum;
545 	reachnum = BotGetReachabilityToGoal(parm2, newarea, 1,
546 									ms.avoidreach, ms.avoidreachtimes,
547 									&goal, TFL_DEFAULT);
548 	if (!reachnum)
549 	{
550 		botimport.Print(PRT_MESSAGE, "goal not reachable\n");
551 	} //end if
552 	else
553 	{
554 		AAS_ReachabilityFromNum(reachnum, &reach);
555 		AAS_ClearShownDebugLines();
556 		AAS_ShowArea(area, qtrue);
557 		AAS_ShowArea(reach.areanum, qtrue);
558 		AAS_DrawCross(reach.start, 6, LINECOLOR_BLUE);
559 		AAS_DrawCross(reach.end, 6, LINECOLOR_RED);
560 		//
561 		if (reach.traveltype == TRAVEL_ELEVATOR)
562 		{
563 			ElevatorBottomCenter(&reach, bottomcenter);
564 			AAS_DrawCross(bottomcenter, 10, LINECOLOR_GREEN);
565 		} //end if
566 	} //end else*/
567 //		botimport.Print(PRT_MESSAGE, "travel time to goal = %d\n",
568 //					AAS_AreaTravelTimeToGoalArea(area, origin, botlibglobals.goalareanum, TFL_DEFAULT));
569 //		botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
570 //		AAS_Reachability_WeaponJump(703, 716);
571 //	} //end if*/
572 
573 /*	face = AAS_AreaGroundFace(newarea, parm2);
574 	if (face)
575 	{
576 		AAS_ShowFace(face - (*aasworld).faces);
577 	} //end if*/
578 	/*
579 	AAS_ClearShownDebugLines();
580 	AAS_ShowArea(newarea, parm0 & BUTTON_USE);
581 	AAS_ShowReachableAreas(area);
582 	*/
583 	AAS_ClearShownPolygons();
584 	AAS_ClearShownDebugLines();
585 	AAS_ShowAreaPolygons( newarea, 1, parm0 & 4 );
586 	if ( parm0 & 2 ) {
587 		AAS_ShowReachableAreas( area );
588 	} else
589 	{
590 		static int lastgoalareanum, lastareanum;
591 		static int avoidreach[MAX_AVOIDREACH];
592 		static float avoidreachtimes[MAX_AVOIDREACH];
593 		static int avoidreachtries[MAX_AVOIDREACH];
594 		int reachnum;
595 		bot_goal_t goal;
596 		aas_reachability_t reach;
597 
598 		goal.areanum = botlibglobals.goalareanum;
599 		VectorCopy( botlibglobals.goalorigin, goal.origin );
600 		reachnum = BotGetReachabilityToGoal( origin, newarea, -1,
601 											 lastgoalareanum, lastareanum,
602 											 avoidreach, avoidreachtimes, avoidreachtries,
603 											 &goal, TFL_DEFAULT | TFL_FUNCBOB, TFL_DEFAULT | TFL_FUNCBOB );
604 		AAS_ReachabilityFromNum( reachnum, &reach );
605 		AAS_ShowReachability( &reach );
606 	} //end else
607 	VectorClear( forward );
608 	//BotGapDistance(origin, forward, 0);
609 	/*
610 	if (parm0 & BUTTON_USE)
611 	{
612 		botimport.Print(PRT_MESSAGE, "test rj from 703 to 716\n");
613 		AAS_Reachability_WeaponJump(703, 716);
614 	} //end if*/
615 
616 	AngleVectors( parm3, forward, right, NULL );
617 	//get the eye 16 units to the right of the origin
618 	VectorMA( parm2, 8, right, eye );
619 	//get the eye 24 units up
620 	eye[2] += 24;
621 	//get the end point for the line to be traced
622 	VectorMA( eye, 800, forward, end );
623 
624 //	AAS_TestMovementPrediction(1, parm2, forward);
625 /*	//trace the line to find the hit point
626 	trace = AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
627 	if (!line[0]) line[0] = botimport.DebugLineCreate();
628 	botimport.DebugLineShow(line[0], eye, trace.endpos, LINECOLOR_BLUE);
629 	//
630 	AAS_ClearShownDebugLines();
631 	if (trace.ent)
632 	{
633 		ent = &(*aasworld).entities[trace.ent];
634 		AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
635 	} //end if*/
636 
637 /*
638 	start_time = clock();
639 	for (i = 0; i < 2000; i++)
640 	{
641 		AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
642 //		AAS_TraceClientBBox(eye, end, PRESENCE_NORMAL, 1);
643 	} //end for
644 	end_time = clock();
645 	botimport.Print(PRT_MESSAGE, "me %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
646 	start_time = clock();
647 	for (i = 0; i < 2000; i++)
648 	{
649 		AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
650 	} //end for
651 	end_time = clock();
652 	botimport.Print(PRT_MESSAGE, "id %lu clocks, %lu CLOCKS_PER_SEC\n", end_time - start_time, CLOCKS_PER_SEC);
653 */
654 
655 	/*
656 	AAS_ClearShownDebugLines();
657 	//bsptrace = AAS_Trace(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
658 	bsptrace = AAS_Trace(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
659 	if (!line[0]) line[0] = botimport.DebugLineCreate();
660 	botimport.DebugLineShow(line[0], eye, bsptrace.endpos, LINECOLOR_YELLOW);
661 	if (bsptrace.fraction < 1.0)
662 	{
663 		face = AAS_TraceEndFace(&trace);
664 		if (face)
665 		{
666 			AAS_ShowFace(face - (*aasworld).faces);
667 		} //end if
668 		AAS_DrawPlaneCross(bsptrace.endpos,
669 									bsptrace.plane.normal,
670 									bsptrace.plane.dist + bsptrace.exp_dist,
671 									bsptrace.plane.type, LINECOLOR_GREEN);
672 		if (trace.ent)
673 		{
674 			ent = &(*aasworld).entities[trace.ent];
675 			AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
676 		} //end if
677 	} //end if*/
678 	/*/
679 	//bsptrace = AAS_Trace2(eye, NULL, NULL, end, 1, MASK_PLAYERSOLID);
680 	bsptrace = AAS_Trace2(eye, mins, maxs, end, 1, MASK_PLAYERSOLID);
681 	botimport.DebugLineShow(line[1], eye, bsptrace.endpos, LINECOLOR_BLUE);
682 	if (bsptrace.fraction < 1.0)
683 	{
684 		AAS_DrawPlaneCross(bsptrace.endpos,
685 									bsptrace.plane.normal,
686 									bsptrace.plane.dist,// + bsptrace.exp_dist,
687 									bsptrace.plane.type, LINECOLOR_RED);
688 		if (bsptrace.ent)
689 		{
690 			ent = &(*aasworld).entities[bsptrace.ent];
691 			AAS_ShowBoundingBox(ent->origin, ent->mins, ent->maxs);
692 		} //end if
693 	} //end if
694 	*/
695 #endif
696 	return 0;
697 } //end of the function BotExportTest
698 
699 
700 /*
701 ============
702 Init_AAS_Export
703 ============
704 */
Init_AAS_Export(aas_export_t * aas)705 static void Init_AAS_Export( aas_export_t *aas ) {
706 	//--------------------------------------------
707 	// be_aas_entity.c
708 	//--------------------------------------------
709 	aas->AAS_EntityInfo = AAS_EntityInfo;
710 	//--------------------------------------------
711 	// be_aas_main.c
712 	//--------------------------------------------
713 	aas->AAS_Initialized = AAS_Initialized;
714 	aas->AAS_PresenceTypeBoundingBox = AAS_PresenceTypeBoundingBox;
715 	aas->AAS_Time = AAS_Time;
716 	//--------------------------------------------
717 	// be_aas_sample.c
718 	//--------------------------------------------
719 	aas->AAS_PointAreaNum = AAS_PointAreaNum;
720 	aas->AAS_TraceAreas = AAS_TraceAreas;
721 	//--------------------------------------------
722 	// be_aas_bspq3.c
723 	//--------------------------------------------
724 	aas->AAS_PointContents = AAS_PointContents;
725 	aas->AAS_NextBSPEntity = AAS_NextBSPEntity;
726 	aas->AAS_ValueForBSPEpairKey = AAS_ValueForBSPEpairKey;
727 	aas->AAS_VectorForBSPEpairKey = AAS_VectorForBSPEpairKey;
728 	aas->AAS_FloatForBSPEpairKey = AAS_FloatForBSPEpairKey;
729 	aas->AAS_IntForBSPEpairKey = AAS_IntForBSPEpairKey;
730 	//--------------------------------------------
731 	// be_aas_reach.c
732 	//--------------------------------------------
733 	aas->AAS_AreaReachability = AAS_AreaReachability;
734 	//--------------------------------------------
735 	// be_aas_route.c
736 	//--------------------------------------------
737 	aas->AAS_AreaTravelTimeToGoalArea = AAS_AreaTravelTimeToGoalArea;
738 	//--------------------------------------------
739 	// be_aas_move.c
740 	//--------------------------------------------
741 	aas->AAS_Swimming = AAS_Swimming;
742 	aas->AAS_PredictClientMovement = AAS_PredictClientMovement;
743 
744 	// Ridah, route-tables
745 	//--------------------------------------------
746 	// be_aas_routetable.c
747 	//--------------------------------------------
748 	aas->AAS_RT_ShowRoute = AAS_RT_ShowRoute;
749 	aas->AAS_RT_GetHidePos = AAS_RT_GetHidePos;
750 	aas->AAS_FindAttackSpotWithinRange = AAS_FindAttackSpotWithinRange;
751 	aas->AAS_GetRouteFirstVisPos = AAS_GetRouteFirstVisPos;
752 	aas->AAS_SetAASBlockingEntity = AAS_SetAASBlockingEntity;
753 	// done.
754 
755 	// Ridah, multiple AAS files
756 	aas->AAS_SetCurrentWorld = AAS_SetCurrentWorld;
757 	// done.
758 
759 }
760 
761 
762 /*
763 ============
764 Init_EA_Export
765 ============
766 */
Init_EA_Export(ea_export_t * ea)767 static void Init_EA_Export( ea_export_t *ea ) {
768 	//ClientCommand elementary actions
769 	ea->EA_Say = EA_Say;
770 	ea->EA_SayTeam = EA_SayTeam;
771 	ea->EA_UseItem = EA_UseItem;
772 	ea->EA_DropItem = EA_DropItem;
773 	ea->EA_UseInv = EA_UseInv;
774 	ea->EA_DropInv = EA_DropInv;
775 	ea->EA_Gesture = EA_Gesture;
776 	ea->EA_Command = EA_Command;
777 	ea->EA_SelectWeapon = EA_SelectWeapon;
778 	ea->EA_Talk = EA_Talk;
779 	ea->EA_Attack = EA_Attack;
780 	ea->EA_Reload = EA_Reload;
781 	ea->EA_Use = EA_Use;
782 	ea->EA_Respawn = EA_Respawn;
783 	ea->EA_Jump = EA_Jump;
784 	ea->EA_DelayedJump = EA_DelayedJump;
785 	ea->EA_Crouch = EA_Crouch;
786 	ea->EA_MoveUp = EA_MoveUp;
787 	ea->EA_MoveDown = EA_MoveDown;
788 	ea->EA_MoveForward = EA_MoveForward;
789 	ea->EA_MoveBack = EA_MoveBack;
790 	ea->EA_MoveLeft = EA_MoveLeft;
791 	ea->EA_MoveRight = EA_MoveRight;
792 	ea->EA_Move = EA_Move;
793 	ea->EA_View = EA_View;
794 	ea->EA_GetInput = EA_GetInput;
795 	ea->EA_EndRegular = EA_EndRegular;
796 	ea->EA_ResetInput = EA_ResetInput;
797 }
798 
799 
800 /*
801 ============
802 Init_AI_Export
803 ============
804 */
Init_AI_Export(ai_export_t * ai)805 static void Init_AI_Export( ai_export_t *ai ) {
806 	//-----------------------------------
807 	// be_ai_char.h
808 	//-----------------------------------
809 	ai->BotLoadCharacter = BotLoadCharacter;
810 	ai->BotFreeCharacter = BotFreeCharacter;
811 	ai->Characteristic_Float = Characteristic_Float;
812 	ai->Characteristic_BFloat = Characteristic_BFloat;
813 	ai->Characteristic_Integer = Characteristic_Integer;
814 	ai->Characteristic_BInteger = Characteristic_BInteger;
815 	ai->Characteristic_String = Characteristic_String;
816 	//-----------------------------------
817 	// be_ai_chat.h
818 	//-----------------------------------
819 	ai->BotAllocChatState = BotAllocChatState;
820 	ai->BotFreeChatState = BotFreeChatState;
821 	ai->BotQueueConsoleMessage = BotQueueConsoleMessage;
822 	ai->BotRemoveConsoleMessage = BotRemoveConsoleMessage;
823 	ai->BotNextConsoleMessage = BotNextConsoleMessage;
824 	ai->BotNumConsoleMessages = BotNumConsoleMessages;
825 	ai->BotInitialChat = BotInitialChat;
826 	ai->BotNumInitialChats = BotNumInitialChats;
827 	ai->BotReplyChat = BotReplyChat;
828 	ai->BotChatLength = BotChatLength;
829 	ai->BotEnterChat = BotEnterChat;
830 	ai->BotGetChatMessage = BotGetChatMessage;
831 	ai->StringContains = StringContains;
832 	ai->BotFindMatch = BotFindMatch;
833 	ai->BotMatchVariable = BotMatchVariable;
834 	ai->UnifyWhiteSpaces = UnifyWhiteSpaces;
835 	ai->BotReplaceSynonyms = BotReplaceSynonyms;
836 	ai->BotLoadChatFile = BotLoadChatFile;
837 	ai->BotSetChatGender = BotSetChatGender;
838 	ai->BotSetChatName = BotSetChatName;
839 	//-----------------------------------
840 	// be_ai_goal.h
841 	//-----------------------------------
842 	ai->BotResetGoalState = BotResetGoalState;
843 	ai->BotResetAvoidGoals = BotResetAvoidGoals;
844 	ai->BotRemoveFromAvoidGoals = BotRemoveFromAvoidGoals;
845 	ai->BotPushGoal = BotPushGoal;
846 	ai->BotPopGoal = BotPopGoal;
847 	ai->BotEmptyGoalStack = BotEmptyGoalStack;
848 	ai->BotDumpAvoidGoals = BotDumpAvoidGoals;
849 	ai->BotDumpGoalStack = BotDumpGoalStack;
850 	ai->BotGoalName = BotGoalName;
851 	ai->BotGetTopGoal = BotGetTopGoal;
852 	ai->BotGetSecondGoal = BotGetSecondGoal;
853 	ai->BotChooseLTGItem = BotChooseLTGItem;
854 	ai->BotChooseNBGItem = BotChooseNBGItem;
855 	ai->BotTouchingGoal = BotTouchingGoal;
856 	ai->BotItemGoalInVisButNotVisible = BotItemGoalInVisButNotVisible;
857 	ai->BotGetLevelItemGoal = BotGetLevelItemGoal;
858 	ai->BotGetNextCampSpotGoal = BotGetNextCampSpotGoal;
859 	ai->BotGetMapLocationGoal = BotGetMapLocationGoal;
860 	ai->BotAvoidGoalTime = BotAvoidGoalTime;
861 	ai->BotInitLevelItems = BotInitLevelItems;
862 	ai->BotUpdateEntityItems = BotUpdateEntityItems;
863 	ai->BotLoadItemWeights = BotLoadItemWeights;
864 	ai->BotFreeItemWeights = BotFreeItemWeights;
865 	ai->BotInterbreedGoalFuzzyLogic = BotInterbreedGoalFuzzyLogic;
866 	ai->BotSaveGoalFuzzyLogic = BotSaveGoalFuzzyLogic;
867 	ai->BotMutateGoalFuzzyLogic = BotMutateGoalFuzzyLogic;
868 	ai->BotAllocGoalState = BotAllocGoalState;
869 	ai->BotFreeGoalState = BotFreeGoalState;
870 	//-----------------------------------
871 	// be_ai_move.h
872 	//-----------------------------------
873 	ai->BotResetMoveState = BotResetMoveState;
874 	ai->BotMoveToGoal = BotMoveToGoal;
875 	ai->BotMoveInDirection = BotMoveInDirection;
876 	ai->BotResetAvoidReach = BotResetAvoidReach;
877 	ai->BotResetLastAvoidReach = BotResetLastAvoidReach;
878 	ai->BotReachabilityArea = BotReachabilityArea;
879 	ai->BotMovementViewTarget = BotMovementViewTarget;
880 	ai->BotPredictVisiblePosition = BotPredictVisiblePosition;
881 	ai->BotAllocMoveState = BotAllocMoveState;
882 	ai->BotFreeMoveState = BotFreeMoveState;
883 	ai->BotInitMoveState = BotInitMoveState;
884 	// Ridah
885 	ai->BotInitAvoidReach = BotInitAvoidReach;
886 	// done.
887 	//-----------------------------------
888 	// be_ai_weap.h
889 	//-----------------------------------
890 	ai->BotChooseBestFightWeapon = BotChooseBestFightWeapon;
891 	ai->BotGetWeaponInfo = BotGetWeaponInfo;
892 	ai->BotLoadWeaponWeights = BotLoadWeaponWeights;
893 	ai->BotAllocWeaponState = BotAllocWeaponState;
894 	ai->BotFreeWeaponState = BotFreeWeaponState;
895 	ai->BotResetWeaponState = BotResetWeaponState;
896 	//-----------------------------------
897 	// be_ai_gen.h
898 	//-----------------------------------
899 	ai->GeneticParentsAndChildSelection = GeneticParentsAndChildSelection;
900 }
901 
902 
903 /*
904 ============
905 GetBotLibAPI
906 ============
907 */
GetBotLibAPI(int apiVersion,botlib_import_t * import)908 botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import ) {
909 	assert(import);
910 	botimport = *import;
911 	assert(botimport.Print);
912 
913 	memset( &be_botlib_export, 0, sizeof( be_botlib_export ) );
914 
915 	if ( apiVersion != BOTLIB_API_VERSION ) {
916 		botimport.Print( PRT_ERROR, "Mismatched BOTLIB_API_VERSION: expected %i, got %i\n", BOTLIB_API_VERSION, apiVersion );
917 		return NULL;
918 	}
919 
920 	Init_AAS_Export( &be_botlib_export.aas );
921 	Init_EA_Export( &be_botlib_export.ea );
922 	Init_AI_Export( &be_botlib_export.ai );
923 
924 	be_botlib_export.BotLibSetup = Export_BotLibSetup;
925 	be_botlib_export.BotLibShutdown = Export_BotLibShutdown;
926 	be_botlib_export.BotLibVarSet = Export_BotLibVarSet;
927 	be_botlib_export.BotLibVarGet = Export_BotLibVarGet;
928 	be_botlib_export.PC_AddGlobalDefine = PC_AddGlobalDefine;
929 	be_botlib_export.PC_LoadSourceHandle = PC_LoadSourceHandle;
930 	be_botlib_export.PC_FreeSourceHandle = PC_FreeSourceHandle;
931 	be_botlib_export.PC_ReadTokenHandle = PC_ReadTokenHandle;
932 	be_botlib_export.PC_SourceFileAndLine = PC_SourceFileAndLine;
933 
934 	be_botlib_export.BotLibStartFrame = Export_BotLibStartFrame;
935 	be_botlib_export.BotLibLoadMap = Export_BotLibLoadMap;
936 	be_botlib_export.BotLibUpdateEntity = Export_BotLibUpdateEntity;
937 	be_botlib_export.Test = BotExportTest;
938 
939 	return &be_botlib_export;
940 }
941