aas_file.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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. #include "qbsp.h"
  19. #include "../botlib/aasfile.h"
  20. #include "aas_file.h"
  21. #include "aas_store.h"
  22. #include "aas_create.h"
  23. #define AAS_Error Error
  24. //===========================================================================
  25. //
  26. // Parameter: -
  27. // Returns: -
  28. // Changes Globals: -
  29. //===========================================================================
  30. void AAS_SwapAASData(void)
  31. {
  32. int i, j;
  33. //bounding boxes
  34. for (i = 0; i < aasworld.numbboxes; i++)
  35. {
  36. aasworld.bboxes[i].presencetype = LittleLong(aasworld.bboxes[i].presencetype);
  37. aasworld.bboxes[i].flags = LittleLong(aasworld.bboxes[i].flags);
  38. for (j = 0; j < 3; j++)
  39. {
  40. aasworld.bboxes[i].mins[j] = LittleLong(aasworld.bboxes[i].mins[j]);
  41. aasworld.bboxes[i].maxs[j] = LittleLong(aasworld.bboxes[i].maxs[j]);
  42. } //end for
  43. } //end for
  44. //vertexes
  45. for (i = 0; i < aasworld.numvertexes; i++)
  46. {
  47. for (j = 0; j < 3; j++)
  48. aasworld.vertexes[i][j] = LittleFloat(aasworld.vertexes[i][j]);
  49. } //end for
  50. //planes
  51. for (i = 0; i < aasworld.numplanes; i++)
  52. {
  53. for (j = 0; j < 3; j++)
  54. aasworld.planes[i].normal[j] = LittleFloat(aasworld.planes[i].normal[j]);
  55. aasworld.planes[i].dist = LittleFloat(aasworld.planes[i].dist);
  56. aasworld.planes[i].type = LittleLong(aasworld.planes[i].type);
  57. } //end for
  58. //edges
  59. for (i = 0; i < aasworld.numedges; i++)
  60. {
  61. aasworld.edges[i].v[0] = LittleLong(aasworld.edges[i].v[0]);
  62. aasworld.edges[i].v[1] = LittleLong(aasworld.edges[i].v[1]);
  63. } //end for
  64. //edgeindex
  65. for (i = 0; i < aasworld.edgeindexsize; i++)
  66. {
  67. aasworld.edgeindex[i] = LittleLong(aasworld.edgeindex[i]);
  68. } //end for
  69. //faces
  70. for (i = 0; i < aasworld.numfaces; i++)
  71. {
  72. aasworld.faces[i].planenum = LittleLong(aasworld.faces[i].planenum);
  73. aasworld.faces[i].faceflags = LittleLong(aasworld.faces[i].faceflags);
  74. aasworld.faces[i].numedges = LittleLong(aasworld.faces[i].numedges);
  75. aasworld.faces[i].firstedge = LittleLong(aasworld.faces[i].firstedge);
  76. aasworld.faces[i].frontarea = LittleLong(aasworld.faces[i].frontarea);
  77. aasworld.faces[i].backarea = LittleLong(aasworld.faces[i].backarea);
  78. } //end for
  79. //face index
  80. for (i = 0; i < aasworld.faceindexsize; i++)
  81. {
  82. aasworld.faceindex[i] = LittleLong(aasworld.faceindex[i]);
  83. } //end for
  84. //convex areas
  85. for (i = 0; i < aasworld.numareas; i++)
  86. {
  87. aasworld.areas[i].areanum = LittleLong(aasworld.areas[i].areanum);
  88. aasworld.areas[i].numfaces = LittleLong(aasworld.areas[i].numfaces);
  89. aasworld.areas[i].firstface = LittleLong(aasworld.areas[i].firstface);
  90. for (j = 0; j < 3; j++)
  91. {
  92. aasworld.areas[i].mins[j] = LittleFloat(aasworld.areas[i].mins[j]);
  93. aasworld.areas[i].maxs[j] = LittleFloat(aasworld.areas[i].maxs[j]);
  94. aasworld.areas[i].center[j] = LittleFloat(aasworld.areas[i].center[j]);
  95. } //end for
  96. } //end for
  97. //area settings
  98. for (i = 0; i < aasworld.numareasettings; i++)
  99. {
  100. aasworld.areasettings[i].contents = LittleLong(aasworld.areasettings[i].contents);
  101. aasworld.areasettings[i].areaflags = LittleLong(aasworld.areasettings[i].areaflags);
  102. aasworld.areasettings[i].presencetype = LittleLong(aasworld.areasettings[i].presencetype);
  103. aasworld.areasettings[i].cluster = LittleLong(aasworld.areasettings[i].cluster);
  104. aasworld.areasettings[i].clusterareanum = LittleLong(aasworld.areasettings[i].clusterareanum);
  105. aasworld.areasettings[i].numreachableareas = LittleLong(aasworld.areasettings[i].numreachableareas);
  106. aasworld.areasettings[i].firstreachablearea = LittleLong(aasworld.areasettings[i].firstreachablearea);
  107. } //end for
  108. //area reachability
  109. for (i = 0; i < aasworld.reachabilitysize; i++)
  110. {
  111. aasworld.reachability[i].areanum = LittleLong(aasworld.reachability[i].areanum);
  112. aasworld.reachability[i].facenum = LittleLong(aasworld.reachability[i].facenum);
  113. aasworld.reachability[i].edgenum = LittleLong(aasworld.reachability[i].edgenum);
  114. for (j = 0; j < 3; j++)
  115. {
  116. aasworld.reachability[i].start[j] = LittleFloat(aasworld.reachability[i].start[j]);
  117. aasworld.reachability[i].end[j] = LittleFloat(aasworld.reachability[i].end[j]);
  118. } //end for
  119. aasworld.reachability[i].traveltype = LittleLong(aasworld.reachability[i].traveltype);
  120. aasworld.reachability[i].traveltime = LittleShort(aasworld.reachability[i].traveltime);
  121. } //end for
  122. //nodes
  123. for (i = 0; i < aasworld.numnodes; i++)
  124. {
  125. aasworld.nodes[i].planenum = LittleLong(aasworld.nodes[i].planenum);
  126. aasworld.nodes[i].children[0] = LittleLong(aasworld.nodes[i].children[0]);
  127. aasworld.nodes[i].children[1] = LittleLong(aasworld.nodes[i].children[1]);
  128. } //end for
  129. //cluster portals
  130. for (i = 0; i < aasworld.numportals; i++)
  131. {
  132. aasworld.portals[i].areanum = LittleLong(aasworld.portals[i].areanum);
  133. aasworld.portals[i].frontcluster = LittleLong(aasworld.portals[i].frontcluster);
  134. aasworld.portals[i].backcluster = LittleLong(aasworld.portals[i].backcluster);
  135. aasworld.portals[i].clusterareanum[0] = LittleLong(aasworld.portals[i].clusterareanum[0]);
  136. aasworld.portals[i].clusterareanum[1] = LittleLong(aasworld.portals[i].clusterareanum[1]);
  137. } //end for
  138. //cluster portal index
  139. for (i = 0; i < aasworld.portalindexsize; i++)
  140. {
  141. aasworld.portalindex[i] = LittleLong(aasworld.portalindex[i]);
  142. } //end for
  143. //cluster
  144. for (i = 0; i < aasworld.numclusters; i++)
  145. {
  146. aasworld.clusters[i].numareas = LittleLong(aasworld.clusters[i].numareas);
  147. aasworld.clusters[i].numportals = LittleLong(aasworld.clusters[i].numportals);
  148. aasworld.clusters[i].firstportal = LittleLong(aasworld.clusters[i].firstportal);
  149. } //end for
  150. } //end of the function AAS_SwapAASData
  151. //===========================================================================
  152. // dump the current loaded aas file
  153. //
  154. // Parameter: -
  155. // Returns: -
  156. // Changes Globals: -
  157. //===========================================================================
  158. void AAS_DumpAASData(void)
  159. {
  160. /*
  161. if (aasworld.vertexes) FreeMemory(aasworld.vertexes);
  162. aasworld.vertexes = NULL;
  163. if (aasworld.planes) FreeMemory(aasworld.planes);
  164. aasworld.planes = NULL;
  165. if (aasworld.edges) FreeMemory(aasworld.edges);
  166. aasworld.edges = NULL;
  167. if (aasworld.edgeindex) FreeMemory(aasworld.edgeindex);
  168. aasworld.edgeindex = NULL;
  169. if (aasworld.faces) FreeMemory(aasworld.faces);
  170. aasworld.faces = NULL;
  171. if (aasworld.faceindex) FreeMemory(aasworld.faceindex);
  172. aasworld.faceindex = NULL;
  173. if (aasworld.areas) FreeMemory(aasworld.areas);
  174. aasworld.areas = NULL;
  175. if (aasworld.areasettings) FreeMemory(aasworld.areasettings);
  176. aasworld.areasettings = NULL;
  177. if (aasworld.reachability) FreeMemory(aasworld.reachability);
  178. aasworld.reachability = NULL;
  179. */
  180. aasworld.loaded = false;
  181. } //end of the function AAS_DumpAASData
  182. //===========================================================================
  183. // allocate memory and read a lump of a AAS file
  184. //
  185. // Parameter: -
  186. // Returns: -
  187. // Changes Globals: -
  188. //===========================================================================
  189. char *AAS_LoadAASLump(FILE *fp, int offset, int length, void *buf)
  190. {
  191. if (!length)
  192. {
  193. printf("lump size 0\n");
  194. return buf;
  195. } //end if
  196. //seek to the data
  197. if (fseek(fp, offset, SEEK_SET))
  198. {
  199. AAS_Error("can't seek to lump\n");
  200. AAS_DumpAASData();
  201. fclose(fp);
  202. return 0;
  203. } //end if
  204. //allocate memory
  205. if (!buf) buf = (void *) GetClearedMemory(length);
  206. //read the data
  207. if (fread((char *) buf, 1, length, fp) != length)
  208. {
  209. AAS_Error("can't read lump\n");
  210. FreeMemory(buf);
  211. AAS_DumpAASData();
  212. fclose(fp);
  213. return NULL;
  214. } //end if
  215. return buf;
  216. } //end of the function AAS_LoadAASLump
  217. //===========================================================================
  218. //
  219. // Parameter: -
  220. // Returns: -
  221. // Changes Globals: -
  222. //===========================================================================
  223. void AAS_DData(unsigned char *data, int size)
  224. {
  225. int i;
  226. for (i = 0; i < size; i++)
  227. {
  228. data[i] ^= (unsigned char) i * 119;
  229. } //end for
  230. } //end of the function AAS_DData
  231. //===========================================================================
  232. // load an aas file
  233. //
  234. // Parameter: -
  235. // Returns: -
  236. // Changes Globals: -
  237. //===========================================================================
  238. qboolean AAS_LoadAASFile(char *filename, int fpoffset, int fplength)
  239. {
  240. FILE *fp;
  241. aas_header_t header;
  242. int offset, length;
  243. //dump current loaded aas file
  244. AAS_DumpAASData();
  245. //open the file
  246. fp = fopen(filename, "rb");
  247. if (!fp)
  248. {
  249. AAS_Error("can't open %s\n", filename);
  250. return false;
  251. } //end if
  252. //seek to the correct position (in the pak file)
  253. if (fseek(fp, fpoffset, SEEK_SET))
  254. {
  255. AAS_Error("can't seek to file %s\n");
  256. fclose(fp);
  257. return false;
  258. } //end if
  259. //read the header
  260. if (fread(&header, sizeof(aas_header_t), 1, fp) != 1)
  261. {
  262. AAS_Error("can't read header of file %s\n", filename);
  263. fclose(fp);
  264. return false;
  265. } //end if
  266. //check header identification
  267. header.ident = LittleLong(header.ident);
  268. if (header.ident != AASID)
  269. {
  270. AAS_Error("%s is not an AAS file\n", filename);
  271. fclose(fp);
  272. return false;
  273. } //end if
  274. //check the version
  275. header.version = LittleLong(header.version);
  276. if (header.version != AASVERSION_OLD && header.version != AASVERSION)
  277. {
  278. AAS_Error("%s is version %i, not %i\n", filename, header.version, AASVERSION);
  279. fclose(fp);
  280. return false;
  281. } //end if
  282. //
  283. if (header.version == AASVERSION)
  284. {
  285. AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
  286. } //end if
  287. aasworld.bspchecksum = LittleLong(header.bspchecksum);
  288. //load the lumps:
  289. //bounding boxes
  290. offset = fpoffset + LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
  291. length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
  292. aasworld.bboxes = (aas_bbox_t *) AAS_LoadAASLump(fp, offset, length, aasworld.bboxes);
  293. if (!aasworld.bboxes) return false;
  294. aasworld.numbboxes = length / sizeof(aas_bbox_t);
  295. //vertexes
  296. offset = fpoffset + LittleLong(header.lumps[AASLUMP_VERTEXES].fileofs);
  297. length = LittleLong(header.lumps[AASLUMP_VERTEXES].filelen);
  298. aasworld.vertexes = (aas_vertex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.vertexes);
  299. if (!aasworld.vertexes) return false;
  300. aasworld.numvertexes = length / sizeof(aas_vertex_t);
  301. //planes
  302. offset = fpoffset + LittleLong(header.lumps[AASLUMP_PLANES].fileofs);
  303. length = LittleLong(header.lumps[AASLUMP_PLANES].filelen);
  304. aasworld.planes = (aas_plane_t *) AAS_LoadAASLump(fp, offset, length, aasworld.planes);
  305. if (!aasworld.planes) return false;
  306. aasworld.numplanes = length / sizeof(aas_plane_t);
  307. //edges
  308. offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGES].fileofs);
  309. length = LittleLong(header.lumps[AASLUMP_EDGES].filelen);
  310. aasworld.edges = (aas_edge_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edges);
  311. if (!aasworld.edges) return false;
  312. aasworld.numedges = length / sizeof(aas_edge_t);
  313. //edgeindex
  314. offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGEINDEX].fileofs);
  315. length = LittleLong(header.lumps[AASLUMP_EDGEINDEX].filelen);
  316. aasworld.edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edgeindex);
  317. if (!aasworld.edgeindex) return false;
  318. aasworld.edgeindexsize = length / sizeof(aas_edgeindex_t);
  319. //faces
  320. offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACES].fileofs);
  321. length = LittleLong(header.lumps[AASLUMP_FACES].filelen);
  322. aasworld.faces = (aas_face_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faces);
  323. if (!aasworld.faces) return false;
  324. aasworld.numfaces = length / sizeof(aas_face_t);
  325. //faceindex
  326. offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACEINDEX].fileofs);
  327. length = LittleLong(header.lumps[AASLUMP_FACEINDEX].filelen);
  328. aasworld.faceindex = (aas_faceindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faceindex);
  329. if (!aasworld.faceindex) return false;
  330. aasworld.faceindexsize = length / sizeof(int);
  331. //convex areas
  332. offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREAS].fileofs);
  333. length = LittleLong(header.lumps[AASLUMP_AREAS].filelen);
  334. aasworld.areas = (aas_area_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areas);
  335. if (!aasworld.areas) return false;
  336. aasworld.numareas = length / sizeof(aas_area_t);
  337. //area settings
  338. offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREASETTINGS].fileofs);
  339. length = LittleLong(header.lumps[AASLUMP_AREASETTINGS].filelen);
  340. aasworld.areasettings = (aas_areasettings_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areasettings);
  341. if (!aasworld.areasettings) return false;
  342. aasworld.numareasettings = length / sizeof(aas_areasettings_t);
  343. //reachability list
  344. offset = fpoffset + LittleLong(header.lumps[AASLUMP_REACHABILITY].fileofs);
  345. length = LittleLong(header.lumps[AASLUMP_REACHABILITY].filelen);
  346. aasworld.reachability = (aas_reachability_t *) AAS_LoadAASLump(fp, offset, length, aasworld.reachability);
  347. if (length && !aasworld.reachability) return false;
  348. aasworld.reachabilitysize = length / sizeof(aas_reachability_t);
  349. //nodes
  350. offset = fpoffset + LittleLong(header.lumps[AASLUMP_NODES].fileofs);
  351. length = LittleLong(header.lumps[AASLUMP_NODES].filelen);
  352. aasworld.nodes = (aas_node_t *) AAS_LoadAASLump(fp, offset, length, aasworld.nodes);
  353. if (!aasworld.nodes) return false;
  354. aasworld.numnodes = length / sizeof(aas_node_t);
  355. //cluster portals
  356. offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALS].fileofs);
  357. length = LittleLong(header.lumps[AASLUMP_PORTALS].filelen);
  358. aasworld.portals = (aas_portal_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portals);
  359. if (length && !aasworld.portals) return false;
  360. aasworld.numportals = length / sizeof(aas_portal_t);
  361. //cluster portal index
  362. offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALINDEX].fileofs);
  363. length = LittleLong(header.lumps[AASLUMP_PORTALINDEX].filelen);
  364. aasworld.portalindex = (aas_portalindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portalindex);
  365. if (length && !aasworld.portalindex) return false;
  366. aasworld.portalindexsize = length / sizeof(aas_portalindex_t);
  367. //clusters
  368. offset = fpoffset + LittleLong(header.lumps[AASLUMP_CLUSTERS].fileofs);
  369. length = LittleLong(header.lumps[AASLUMP_CLUSTERS].filelen);
  370. aasworld.clusters = (aas_cluster_t *) AAS_LoadAASLump(fp, offset, length, aasworld.clusters);
  371. if (length && !aasworld.clusters) return false;
  372. aasworld.numclusters = length / sizeof(aas_cluster_t);
  373. //swap everything
  374. AAS_SwapAASData();
  375. //aas file is loaded
  376. aasworld.loaded = true;
  377. //close the file
  378. fclose(fp);
  379. return true;
  380. } //end of the function AAS_LoadAASFile
  381. //===========================================================================
  382. //
  383. // Parameter: -
  384. // Returns: -
  385. // Changes Globals: -
  386. //===========================================================================
  387. int AAS_WriteAASLump(FILE *fp, aas_header_t *h, int lumpnum, void *data, int length)
  388. {
  389. aas_lump_t *lump;
  390. lump = &h->lumps[lumpnum];
  391. lump->fileofs = LittleLong(ftell(fp));
  392. lump->filelen = LittleLong(length);
  393. if (length > 0)
  394. {
  395. if (fwrite(data, length, 1, fp) < 1)
  396. {
  397. Log_Print("error writing lump %s\n", lumpnum);
  398. fclose(fp);
  399. return false;
  400. } //end if
  401. } //end if
  402. return true;
  403. } //end of the function AAS_WriteAASLump
  404. //===========================================================================
  405. //
  406. // Parameter: -
  407. // Returns: -
  408. // Changes Globals: -
  409. //===========================================================================
  410. void AAS_ShowNumReachabilities(int tt, char *name)
  411. {
  412. int i, num;
  413. num = 0;
  414. for (i = 0; i < aasworld.reachabilitysize; i++)
  415. {
  416. if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == tt)
  417. num++;
  418. } //end for
  419. Log_Print("%6d %s\n", num, name);
  420. } //end of the function AAS_ShowNumReachabilities
  421. //===========================================================================
  422. //
  423. // Parameter: -
  424. // Returns: -
  425. // Changes Globals: -
  426. //===========================================================================
  427. void AAS_ShowTotals(void)
  428. {
  429. Log_Print("numvertexes = %d\r\n", aasworld.numvertexes);
  430. Log_Print("numplanes = %d\r\n", aasworld.numplanes);
  431. Log_Print("numedges = %d\r\n", aasworld.numedges);
  432. Log_Print("edgeindexsize = %d\r\n", aasworld.edgeindexsize);
  433. Log_Print("numfaces = %d\r\n", aasworld.numfaces);
  434. Log_Print("faceindexsize = %d\r\n", aasworld.faceindexsize);
  435. Log_Print("numareas = %d\r\n", aasworld.numareas);
  436. Log_Print("numareasettings = %d\r\n", aasworld.numareasettings);
  437. Log_Print("reachabilitysize = %d\r\n", aasworld.reachabilitysize);
  438. Log_Print("numnodes = %d\r\n", aasworld.numnodes);
  439. Log_Print("numportals = %d\r\n", aasworld.numportals);
  440. Log_Print("portalindexsize = %d\r\n", aasworld.portalindexsize);
  441. Log_Print("numclusters = %d\r\n", aasworld.numclusters);
  442. AAS_ShowNumReachabilities(TRAVEL_WALK, "walk");
  443. AAS_ShowNumReachabilities(TRAVEL_CROUCH, "crouch");
  444. AAS_ShowNumReachabilities(TRAVEL_BARRIERJUMP, "barrier jump");
  445. AAS_ShowNumReachabilities(TRAVEL_JUMP, "jump");
  446. AAS_ShowNumReachabilities(TRAVEL_LADDER, "ladder");
  447. AAS_ShowNumReachabilities(TRAVEL_WALKOFFLEDGE, "walk off ledge");
  448. AAS_ShowNumReachabilities(TRAVEL_SWIM, "swim");
  449. AAS_ShowNumReachabilities(TRAVEL_WATERJUMP, "water jump");
  450. AAS_ShowNumReachabilities(TRAVEL_TELEPORT, "teleport");
  451. AAS_ShowNumReachabilities(TRAVEL_ELEVATOR, "elevator");
  452. AAS_ShowNumReachabilities(TRAVEL_ROCKETJUMP, "rocket jump");
  453. AAS_ShowNumReachabilities(TRAVEL_BFGJUMP, "bfg jump");
  454. AAS_ShowNumReachabilities(TRAVEL_GRAPPLEHOOK, "grapple hook");
  455. AAS_ShowNumReachabilities(TRAVEL_DOUBLEJUMP, "double jump");
  456. AAS_ShowNumReachabilities(TRAVEL_RAMPJUMP, "ramp jump");
  457. AAS_ShowNumReachabilities(TRAVEL_STRAFEJUMP, "strafe jump");
  458. AAS_ShowNumReachabilities(TRAVEL_JUMPPAD, "jump pad");
  459. AAS_ShowNumReachabilities(TRAVEL_FUNCBOB, "func bob");
  460. } //end of the function AAS_ShowTotals
  461. //===========================================================================
  462. // aas data is useless after writing to file because it is byte swapped
  463. //
  464. // Parameter: -
  465. // Returns: -
  466. // Changes Globals: -
  467. //===========================================================================
  468. qboolean AAS_WriteAASFile(char *filename)
  469. {
  470. aas_header_t header;
  471. FILE *fp;
  472. Log_Print("writing %s\n", filename);
  473. AAS_ShowTotals();
  474. //swap the aas data
  475. AAS_SwapAASData();
  476. //initialize the file header
  477. memset(&header, 0, sizeof(aas_header_t));
  478. header.ident = LittleLong(AASID);
  479. header.version = LittleLong(AASVERSION);
  480. header.bspchecksum = LittleLong(aasworld.bspchecksum);
  481. //open a new file
  482. fp = fopen(filename, "wb");
  483. if (!fp)
  484. {
  485. Log_Print("error opening %s\n", filename);
  486. return false;
  487. } //end if
  488. //write the header
  489. if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
  490. {
  491. fclose(fp);
  492. return false;
  493. } //end if
  494. //add the data lumps to the file
  495. if (!AAS_WriteAASLump(fp, &header, AASLUMP_BBOXES, aasworld.bboxes,
  496. aasworld.numbboxes * sizeof(aas_bbox_t))) return false;
  497. if (!AAS_WriteAASLump(fp, &header, AASLUMP_VERTEXES, aasworld.vertexes,
  498. aasworld.numvertexes * sizeof(aas_vertex_t))) return false;
  499. if (!AAS_WriteAASLump(fp, &header, AASLUMP_PLANES, aasworld.planes,
  500. aasworld.numplanes * sizeof(aas_plane_t))) return false;
  501. if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGES, aasworld.edges,
  502. aasworld.numedges * sizeof(aas_edge_t))) return false;
  503. if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGEINDEX, aasworld.edgeindex,
  504. aasworld.edgeindexsize * sizeof(aas_edgeindex_t))) return false;
  505. if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACES, aasworld.faces,
  506. aasworld.numfaces * sizeof(aas_face_t))) return false;
  507. if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACEINDEX, aasworld.faceindex,
  508. aasworld.faceindexsize * sizeof(aas_faceindex_t))) return false;
  509. if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREAS, aasworld.areas,
  510. aasworld.numareas * sizeof(aas_area_t))) return false;
  511. if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREASETTINGS, aasworld.areasettings,
  512. aasworld.numareasettings * sizeof(aas_areasettings_t))) return false;
  513. if (!AAS_WriteAASLump(fp, &header, AASLUMP_REACHABILITY, aasworld.reachability,
  514. aasworld.reachabilitysize * sizeof(aas_reachability_t))) return false;
  515. if (!AAS_WriteAASLump(fp, &header, AASLUMP_NODES, aasworld.nodes,
  516. aasworld.numnodes * sizeof(aas_node_t))) return false;
  517. if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALS, aasworld.portals,
  518. aasworld.numportals * sizeof(aas_portal_t))) return false;
  519. if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALINDEX, aasworld.portalindex,
  520. aasworld.portalindexsize * sizeof(aas_portalindex_t))) return false;
  521. if (!AAS_WriteAASLump(fp, &header, AASLUMP_CLUSTERS, aasworld.clusters,
  522. aasworld.numclusters * sizeof(aas_cluster_t))) return false;
  523. //rewrite the header with the added lumps
  524. fseek(fp, 0, SEEK_SET);
  525. AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
  526. if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
  527. {
  528. fclose(fp);
  529. return false;
  530. } //end if
  531. //close the file
  532. fclose(fp);
  533. return true;
  534. } //end of the function AAS_WriteAASFile