be_aas_main.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. /*****************************************************************************
  19. * name: be_aas_main.c
  20. *
  21. * desc: AAS
  22. *
  23. * $Archive: /MissionPack/code/botlib/be_aas_main.c $
  24. *
  25. *****************************************************************************/
  26. #include "../game/q_shared.h"
  27. #include "l_memory.h"
  28. #include "l_libvar.h"
  29. #include "l_utils.h"
  30. #include "l_script.h"
  31. #include "l_precomp.h"
  32. #include "l_struct.h"
  33. #include "l_log.h"
  34. #include "aasfile.h"
  35. #include "../game/botlib.h"
  36. #include "../game/be_aas.h"
  37. #include "be_aas_funcs.h"
  38. #include "be_interface.h"
  39. #include "be_aas_def.h"
  40. aas_t aasworld;
  41. libvar_t *saveroutingcache;
  42. //===========================================================================
  43. //
  44. // Parameter: -
  45. // Returns: -
  46. // Changes Globals: -
  47. //===========================================================================
  48. void QDECL AAS_Error(char *fmt, ...)
  49. {
  50. char str[1024];
  51. va_list arglist;
  52. va_start(arglist, fmt);
  53. vsprintf(str, fmt, arglist);
  54. va_end(arglist);
  55. botimport.Print(PRT_FATAL, str);
  56. } //end of the function AAS_Error
  57. //===========================================================================
  58. //
  59. // Parameter: -
  60. // Returns: -
  61. // Changes Globals: -
  62. //===========================================================================
  63. char *AAS_StringFromIndex(char *indexname, char *stringindex[], int numindexes, int index)
  64. {
  65. if (!aasworld.indexessetup)
  66. {
  67. botimport.Print(PRT_ERROR, "%s: index %d not setup\n", indexname, index);
  68. return "";
  69. } //end if
  70. if (index < 0 || index >= numindexes)
  71. {
  72. botimport.Print(PRT_ERROR, "%s: index %d out of range\n", indexname, index);
  73. return "";
  74. } //end if
  75. if (!stringindex[index])
  76. {
  77. if (index)
  78. {
  79. botimport.Print(PRT_ERROR, "%s: reference to unused index %d\n", indexname, index);
  80. } //end if
  81. return "";
  82. } //end if
  83. return stringindex[index];
  84. } //end of the function AAS_StringFromIndex
  85. //===========================================================================
  86. //
  87. // Parameter: -
  88. // Returns: -
  89. // Changes Globals: -
  90. //===========================================================================
  91. int AAS_IndexFromString(char *indexname, char *stringindex[], int numindexes, char *string)
  92. {
  93. int i;
  94. if (!aasworld.indexessetup)
  95. {
  96. botimport.Print(PRT_ERROR, "%s: index not setup \"%s\"\n", indexname, string);
  97. return 0;
  98. } //end if
  99. for (i = 0; i < numindexes; i++)
  100. {
  101. if (!stringindex[i]) continue;
  102. if (!Q_stricmp(stringindex[i], string)) return i;
  103. } //end for
  104. return 0;
  105. } //end of the function AAS_IndexFromString
  106. //===========================================================================
  107. //
  108. // Parameter: -
  109. // Returns: -
  110. // Changes Globals: -
  111. //===========================================================================
  112. char *AAS_ModelFromIndex(int index)
  113. {
  114. return AAS_StringFromIndex("ModelFromIndex", &aasworld.configstrings[CS_MODELS], MAX_MODELS, index);
  115. } //end of the function AAS_ModelFromIndex
  116. //===========================================================================
  117. //
  118. // Parameter: -
  119. // Returns: -
  120. // Changes Globals: -
  121. //===========================================================================
  122. int AAS_IndexFromModel(char *modelname)
  123. {
  124. return AAS_IndexFromString("IndexFromModel", &aasworld.configstrings[CS_MODELS], MAX_MODELS, modelname);
  125. } //end of the function AAS_IndexFromModel
  126. //===========================================================================
  127. //
  128. // Parameter: -
  129. // Returns: -
  130. // Changes Globals: -
  131. //===========================================================================
  132. void AAS_UpdateStringIndexes(int numconfigstrings, char *configstrings[])
  133. {
  134. int i;
  135. //set string pointers and copy the strings
  136. for (i = 0; i < numconfigstrings; i++)
  137. {
  138. if (configstrings[i])
  139. {
  140. //if (aasworld.configstrings[i]) FreeMemory(aasworld.configstrings[i]);
  141. aasworld.configstrings[i] = (char *) GetMemory(strlen(configstrings[i]) + 1);
  142. strcpy(aasworld.configstrings[i], configstrings[i]);
  143. } //end if
  144. } //end for
  145. aasworld.indexessetup = qtrue;
  146. } //end of the function AAS_UpdateStringIndexes
  147. //===========================================================================
  148. //
  149. // Parameter: -
  150. // Returns: -
  151. // Changes Globals: -
  152. //===========================================================================
  153. int AAS_Loaded(void)
  154. {
  155. return aasworld.loaded;
  156. } //end of the function AAS_Loaded
  157. //===========================================================================
  158. //
  159. // Parameter: -
  160. // Returns: -
  161. // Changes Globals: -
  162. //===========================================================================
  163. int AAS_Initialized(void)
  164. {
  165. return aasworld.initialized;
  166. } //end of the function AAS_Initialized
  167. //===========================================================================
  168. //
  169. // Parameter: -
  170. // Returns: -
  171. // Changes Globals: -
  172. //===========================================================================
  173. void AAS_SetInitialized(void)
  174. {
  175. aasworld.initialized = qtrue;
  176. botimport.Print(PRT_MESSAGE, "AAS initialized.\n");
  177. #ifdef DEBUG
  178. //create all the routing cache
  179. //AAS_CreateAllRoutingCache();
  180. //
  181. //AAS_RoutingInfo();
  182. #endif
  183. } //end of the function AAS_SetInitialized
  184. //===========================================================================
  185. //
  186. // Parameter: -
  187. // Returns: -
  188. // Changes Globals: -
  189. //===========================================================================
  190. void AAS_ContinueInit(float time)
  191. {
  192. //if no AAS file loaded
  193. if (!aasworld.loaded) return;
  194. //if AAS is already initialized
  195. if (aasworld.initialized) return;
  196. //calculate reachability, if not finished return
  197. if (AAS_ContinueInitReachability(time)) return;
  198. //initialize clustering for the new map
  199. AAS_InitClustering();
  200. //if reachability has been calculated and an AAS file should be written
  201. //or there is a forced data optimization
  202. if (aasworld.savefile || ((int)LibVarGetValue("forcewrite")))
  203. {
  204. //optimize the AAS data
  205. if ((int)LibVarValue("aasoptimize", "0")) AAS_Optimize();
  206. //save the AAS file
  207. if (AAS_WriteAASFile(aasworld.filename))
  208. {
  209. botimport.Print(PRT_MESSAGE, "%s written succesfully\n", aasworld.filename);
  210. } //end if
  211. else
  212. {
  213. botimport.Print(PRT_ERROR, "couldn't write %s\n", aasworld.filename);
  214. } //end else
  215. } //end if
  216. //initialize the routing
  217. AAS_InitRouting();
  218. //at this point AAS is initialized
  219. AAS_SetInitialized();
  220. } //end of the function AAS_ContinueInit
  221. //===========================================================================
  222. // called at the start of every frame
  223. //
  224. // Parameter: -
  225. // Returns: -
  226. // Changes Globals: -
  227. //===========================================================================
  228. int AAS_StartFrame(float time)
  229. {
  230. aasworld.time = time;
  231. //unlink all entities that were not updated last frame
  232. AAS_UnlinkInvalidEntities();
  233. //invalidate the entities
  234. AAS_InvalidateEntities();
  235. //initialize AAS
  236. AAS_ContinueInit(time);
  237. //
  238. aasworld.frameroutingupdates = 0;
  239. //
  240. if (bot_developer)
  241. {
  242. if (LibVarGetValue("showcacheupdates"))
  243. {
  244. AAS_RoutingInfo();
  245. LibVarSet("showcacheupdates", "0");
  246. } //end if
  247. if (LibVarGetValue("showmemoryusage"))
  248. {
  249. PrintUsedMemorySize();
  250. LibVarSet("showmemoryusage", "0");
  251. } //end if
  252. if (LibVarGetValue("memorydump"))
  253. {
  254. PrintMemoryLabels();
  255. LibVarSet("memorydump", "0");
  256. } //end if
  257. } //end if
  258. //
  259. if (saveroutingcache->value)
  260. {
  261. AAS_WriteRouteCache();
  262. LibVarSet("saveroutingcache", "0");
  263. } //end if
  264. //
  265. aasworld.numframes++;
  266. return BLERR_NOERROR;
  267. } //end of the function AAS_StartFrame
  268. //===========================================================================
  269. //
  270. // Parameter: -
  271. // Returns: -
  272. // Changes Globals: -
  273. //===========================================================================
  274. float AAS_Time(void)
  275. {
  276. return aasworld.time;
  277. } //end of the function AAS_Time
  278. //===========================================================================
  279. //
  280. // Parameter: -
  281. // Returns: -
  282. // Changes Globals: -
  283. //===========================================================================
  284. void AAS_ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
  285. {
  286. vec3_t pVec, vec;
  287. VectorSubtract( point, vStart, pVec );
  288. VectorSubtract( vEnd, vStart, vec );
  289. VectorNormalize( vec );
  290. // project onto the directional vector for this segment
  291. VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
  292. } //end of the function AAS_ProjectPointOntoVector
  293. //===========================================================================
  294. //
  295. // Parameter: -
  296. // Returns: -
  297. // Changes Globals: -
  298. //===========================================================================
  299. int AAS_LoadFiles(const char *mapname)
  300. {
  301. int errnum;
  302. char aasfile[MAX_PATH];
  303. // char bspfile[MAX_PATH];
  304. strcpy(aasworld.mapname, mapname);
  305. //NOTE: first reset the entity links into the AAS areas and BSP leaves
  306. // the AAS link heap and BSP link heap are reset after respectively the
  307. // AAS file and BSP file are loaded
  308. AAS_ResetEntityLinks();
  309. // load bsp info
  310. AAS_LoadBSPFile();
  311. //load the aas file
  312. Com_sprintf(aasfile, MAX_PATH, "maps/%s.aas", mapname);
  313. errnum = AAS_LoadAASFile(aasfile);
  314. if (errnum != BLERR_NOERROR)
  315. return errnum;
  316. botimport.Print(PRT_MESSAGE, "loaded %s\n", aasfile);
  317. strncpy(aasworld.filename, aasfile, MAX_PATH);
  318. return BLERR_NOERROR;
  319. } //end of the function AAS_LoadFiles
  320. //===========================================================================
  321. // called everytime a map changes
  322. //
  323. // Parameter: -
  324. // Returns: -
  325. // Changes Globals: -
  326. //===========================================================================
  327. int AAS_LoadMap(const char *mapname)
  328. {
  329. int errnum;
  330. //if no mapname is provided then the string indexes are updated
  331. if (!mapname)
  332. {
  333. return 0;
  334. } //end if
  335. //
  336. aasworld.initialized = qfalse;
  337. //NOTE: free the routing caches before loading a new map because
  338. // to free the caches the old number of areas, number of clusters
  339. // and number of areas in a clusters must be available
  340. AAS_FreeRoutingCaches();
  341. //load the map
  342. errnum = AAS_LoadFiles(mapname);
  343. if (errnum != BLERR_NOERROR)
  344. {
  345. aasworld.loaded = qfalse;
  346. return errnum;
  347. } //end if
  348. //
  349. AAS_InitSettings();
  350. //initialize the AAS link heap for the new map
  351. AAS_InitAASLinkHeap();
  352. //initialize the AAS linked entities for the new map
  353. AAS_InitAASLinkedEntities();
  354. //initialize reachability for the new map
  355. AAS_InitReachability();
  356. //initialize the alternative routing
  357. AAS_InitAlternativeRouting();
  358. //everything went ok
  359. return 0;
  360. } //end of the function AAS_LoadMap
  361. //===========================================================================
  362. // called when the library is first loaded
  363. //
  364. // Parameter: -
  365. // Returns: -
  366. // Changes Globals: -
  367. //===========================================================================
  368. int AAS_Setup(void)
  369. {
  370. aasworld.maxclients = (int) LibVarValue("maxclients", "128");
  371. aasworld.maxentities = (int) LibVarValue("maxentities", "1024");
  372. // as soon as it's set to 1 the routing cache will be saved
  373. saveroutingcache = LibVar("saveroutingcache", "0");
  374. //allocate memory for the entities
  375. if (aasworld.entities) FreeMemory(aasworld.entities);
  376. aasworld.entities = (aas_entity_t *) GetClearedHunkMemory(aasworld.maxentities * sizeof(aas_entity_t));
  377. //invalidate all the entities
  378. AAS_InvalidateEntities();
  379. //force some recalculations
  380. //LibVarSet("forceclustering", "1"); //force clustering calculation
  381. //LibVarSet("forcereachability", "1"); //force reachability calculation
  382. aasworld.numframes = 0;
  383. return BLERR_NOERROR;
  384. } //end of the function AAS_Setup
  385. //===========================================================================
  386. //
  387. // Parameter: -
  388. // Returns: -
  389. // Changes Globals: -
  390. //===========================================================================
  391. void AAS_Shutdown(void)
  392. {
  393. AAS_ShutdownAlternativeRouting();
  394. //
  395. AAS_DumpBSPData();
  396. //free routing caches
  397. AAS_FreeRoutingCaches();
  398. //free aas link heap
  399. AAS_FreeAASLinkHeap();
  400. //free aas linked entities
  401. AAS_FreeAASLinkedEntities();
  402. //free the aas data
  403. AAS_DumpAASData();
  404. //free the entities
  405. if (aasworld.entities) FreeMemory(aasworld.entities);
  406. //clear the aasworld structure
  407. Com_Memset(&aasworld, 0, sizeof(aas_t));
  408. //aas has not been initialized
  409. aasworld.initialized = qfalse;
  410. //NOTE: as soon as a new .bsp file is loaded the .bsp file memory is
  411. // freed an reallocated, so there's no need to free that memory here
  412. //print shutdown
  413. botimport.Print(PRT_MESSAGE, "AAS shutdown.\n");
  414. } //end of the function AAS_Shutdown