00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "qbsp.h"
00024 #include "../botlib/aasfile.h"
00025 #include "aas_file.h"
00026 #include "aas_store.h"
00027 #include "aas_create.h"
00028
00029 #define AAS_Error Error
00030
00031
00032
00033
00034
00035
00036
00037 void AAS_SwapAASData(void)
00038 {
00039 int i, j;
00040
00041 for (i = 0; i < aasworld.numbboxes; i++)
00042 {
00043 aasworld.bboxes[i].presencetype = LittleLong(aasworld.bboxes[i].presencetype);
00044 aasworld.bboxes[i].flags = LittleLong(aasworld.bboxes[i].flags);
00045 for (j = 0; j < 3; j++)
00046 {
00047 aasworld.bboxes[i].mins[j] = LittleLong(aasworld.bboxes[i].mins[j]);
00048 aasworld.bboxes[i].maxs[j] = LittleLong(aasworld.bboxes[i].maxs[j]);
00049 }
00050 }
00051
00052 for (i = 0; i < aasworld.numvertexes; i++)
00053 {
00054 for (j = 0; j < 3; j++)
00055 aasworld.vertexes[i][j] = LittleFloat(aasworld.vertexes[i][j]);
00056 }
00057
00058 for (i = 0; i < aasworld.numplanes; i++)
00059 {
00060 for (j = 0; j < 3; j++)
00061 aasworld.planes[i].normal[j] = LittleFloat(aasworld.planes[i].normal[j]);
00062 aasworld.planes[i].dist = LittleFloat(aasworld.planes[i].dist);
00063 aasworld.planes[i].type = LittleLong(aasworld.planes[i].type);
00064 }
00065
00066 for (i = 0; i < aasworld.numedges; i++)
00067 {
00068 aasworld.edges[i].v[0] = LittleLong(aasworld.edges[i].v[0]);
00069 aasworld.edges[i].v[1] = LittleLong(aasworld.edges[i].v[1]);
00070 }
00071
00072 for (i = 0; i < aasworld.edgeindexsize; i++)
00073 {
00074 aasworld.edgeindex[i] = LittleLong(aasworld.edgeindex[i]);
00075 }
00076
00077 for (i = 0; i < aasworld.numfaces; i++)
00078 {
00079 aasworld.faces[i].planenum = LittleLong(aasworld.faces[i].planenum);
00080 aasworld.faces[i].faceflags = LittleLong(aasworld.faces[i].faceflags);
00081 aasworld.faces[i].numedges = LittleLong(aasworld.faces[i].numedges);
00082 aasworld.faces[i].firstedge = LittleLong(aasworld.faces[i].firstedge);
00083 aasworld.faces[i].frontarea = LittleLong(aasworld.faces[i].frontarea);
00084 aasworld.faces[i].backarea = LittleLong(aasworld.faces[i].backarea);
00085 }
00086
00087 for (i = 0; i < aasworld.faceindexsize; i++)
00088 {
00089 aasworld.faceindex[i] = LittleLong(aasworld.faceindex[i]);
00090 }
00091
00092 for (i = 0; i < aasworld.numareas; i++)
00093 {
00094 aasworld.areas[i].areanum = LittleLong(aasworld.areas[i].areanum);
00095 aasworld.areas[i].numfaces = LittleLong(aasworld.areas[i].numfaces);
00096 aasworld.areas[i].firstface = LittleLong(aasworld.areas[i].firstface);
00097 for (j = 0; j < 3; j++)
00098 {
00099 aasworld.areas[i].mins[j] = LittleFloat(aasworld.areas[i].mins[j]);
00100 aasworld.areas[i].maxs[j] = LittleFloat(aasworld.areas[i].maxs[j]);
00101 aasworld.areas[i].center[j] = LittleFloat(aasworld.areas[i].center[j]);
00102 }
00103 }
00104
00105 for (i = 0; i < aasworld.numareasettings; i++)
00106 {
00107 aasworld.areasettings[i].contents = LittleLong(aasworld.areasettings[i].contents);
00108 aasworld.areasettings[i].areaflags = LittleLong(aasworld.areasettings[i].areaflags);
00109 aasworld.areasettings[i].presencetype = LittleLong(aasworld.areasettings[i].presencetype);
00110 aasworld.areasettings[i].cluster = LittleLong(aasworld.areasettings[i].cluster);
00111 aasworld.areasettings[i].clusterareanum = LittleLong(aasworld.areasettings[i].clusterareanum);
00112 aasworld.areasettings[i].numreachableareas = LittleLong(aasworld.areasettings[i].numreachableareas);
00113 aasworld.areasettings[i].firstreachablearea = LittleLong(aasworld.areasettings[i].firstreachablearea);
00114 }
00115
00116 for (i = 0; i < aasworld.reachabilitysize; i++)
00117 {
00118 aasworld.reachability[i].areanum = LittleLong(aasworld.reachability[i].areanum);
00119 aasworld.reachability[i].facenum = LittleLong(aasworld.reachability[i].facenum);
00120 aasworld.reachability[i].edgenum = LittleLong(aasworld.reachability[i].edgenum);
00121 for (j = 0; j < 3; j++)
00122 {
00123 aasworld.reachability[i].start[j] = LittleFloat(aasworld.reachability[i].start[j]);
00124 aasworld.reachability[i].end[j] = LittleFloat(aasworld.reachability[i].end[j]);
00125 }
00126 aasworld.reachability[i].traveltype = LittleLong(aasworld.reachability[i].traveltype);
00127 aasworld.reachability[i].traveltime = LittleShort(aasworld.reachability[i].traveltime);
00128 }
00129
00130 for (i = 0; i < aasworld.numnodes; i++)
00131 {
00132 aasworld.nodes[i].planenum = LittleLong(aasworld.nodes[i].planenum);
00133 aasworld.nodes[i].children[0] = LittleLong(aasworld.nodes[i].children[0]);
00134 aasworld.nodes[i].children[1] = LittleLong(aasworld.nodes[i].children[1]);
00135 }
00136
00137 for (i = 0; i < aasworld.numportals; i++)
00138 {
00139 aasworld.portals[i].areanum = LittleLong(aasworld.portals[i].areanum);
00140 aasworld.portals[i].frontcluster = LittleLong(aasworld.portals[i].frontcluster);
00141 aasworld.portals[i].backcluster = LittleLong(aasworld.portals[i].backcluster);
00142 aasworld.portals[i].clusterareanum[0] = LittleLong(aasworld.portals[i].clusterareanum[0]);
00143 aasworld.portals[i].clusterareanum[1] = LittleLong(aasworld.portals[i].clusterareanum[1]);
00144 }
00145
00146 for (i = 0; i < aasworld.portalindexsize; i++)
00147 {
00148 aasworld.portalindex[i] = LittleLong(aasworld.portalindex[i]);
00149 }
00150
00151 for (i = 0; i < aasworld.numclusters; i++)
00152 {
00153 aasworld.clusters[i].numareas = LittleLong(aasworld.clusters[i].numareas);
00154 aasworld.clusters[i].numportals = LittleLong(aasworld.clusters[i].numportals);
00155 aasworld.clusters[i].firstportal = LittleLong(aasworld.clusters[i].firstportal);
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 void AAS_DumpAASData(void)
00166 {
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 aasworld.loaded = false;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 char *AAS_LoadAASLump(FILE *fp, int offset, int length, void *buf)
00197 {
00198 if (!length)
00199 {
00200 printf("lump size 0\n");
00201 return buf;
00202 }
00203
00204 if (fseek(fp, offset, SEEK_SET))
00205 {
00206 AAS_Error("can't seek to lump\n");
00207 AAS_DumpAASData();
00208 fclose(fp);
00209 return 0;
00210 }
00211
00212 if (!buf) buf = (void *) GetClearedMemory(length);
00213
00214 if (fread((char *) buf, 1, length, fp) != length)
00215 {
00216 AAS_Error("can't read lump\n");
00217 FreeMemory(buf);
00218 AAS_DumpAASData();
00219 fclose(fp);
00220 return NULL;
00221 }
00222 return buf;
00223 }
00224
00225
00226
00227
00228
00229
00230 void AAS_DData(unsigned char *data, int size)
00231 {
00232 int i;
00233
00234 for (i = 0; i < size; i++)
00235 {
00236 data[i] ^= (unsigned char) i * 119;
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 qboolean AAS_LoadAASFile(char *filename, int fpoffset, int fplength)
00247 {
00248 FILE *fp;
00249 aas_header_t header;
00250 int offset, length;
00251
00252
00253 AAS_DumpAASData();
00254
00255 fp = fopen(filename, "rb");
00256 if (!fp)
00257 {
00258 AAS_Error("can't open %s\n", filename);
00259 return false;
00260 }
00261
00262 if (fseek(fp, fpoffset, SEEK_SET))
00263 {
00264 AAS_Error("can't seek to file %s\n");
00265 fclose(fp);
00266 return false;
00267 }
00268
00269 if (fread(&header, sizeof(aas_header_t), 1, fp) != 1)
00270 {
00271 AAS_Error("can't read header of file %s\n", filename);
00272 fclose(fp);
00273 return false;
00274 }
00275
00276 header.ident = LittleLong(header.ident);
00277 if (header.ident != AASID)
00278 {
00279 AAS_Error("%s is not an AAS file\n", filename);
00280 fclose(fp);
00281 return false;
00282 }
00283
00284 header.version = LittleLong(header.version);
00285 if (header.version != AASVERSION_OLD && header.version != AASVERSION)
00286 {
00287 AAS_Error("%s is version %i, not %i\n", filename, header.version, AASVERSION);
00288 fclose(fp);
00289 return false;
00290 }
00291
00292 if (header.version == AASVERSION)
00293 {
00294 AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
00295 }
00296 aasworld.bspchecksum = LittleLong(header.bspchecksum);
00297
00298
00299 offset = fpoffset + LittleLong(header.lumps[AASLUMP_BBOXES].fileofs);
00300 length = LittleLong(header.lumps[AASLUMP_BBOXES].filelen);
00301 aasworld.bboxes = (aas_bbox_t *) AAS_LoadAASLump(fp, offset, length, aasworld.bboxes);
00302 if (!aasworld.bboxes) return false;
00303 aasworld.numbboxes = length / sizeof(aas_bbox_t);
00304
00305 offset = fpoffset + LittleLong(header.lumps[AASLUMP_VERTEXES].fileofs);
00306 length = LittleLong(header.lumps[AASLUMP_VERTEXES].filelen);
00307 aasworld.vertexes = (aas_vertex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.vertexes);
00308 if (!aasworld.vertexes) return false;
00309 aasworld.numvertexes = length / sizeof(aas_vertex_t);
00310
00311 offset = fpoffset + LittleLong(header.lumps[AASLUMP_PLANES].fileofs);
00312 length = LittleLong(header.lumps[AASLUMP_PLANES].filelen);
00313 aasworld.planes = (aas_plane_t *) AAS_LoadAASLump(fp, offset, length, aasworld.planes);
00314 if (!aasworld.planes) return false;
00315 aasworld.numplanes = length / sizeof(aas_plane_t);
00316
00317 offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGES].fileofs);
00318 length = LittleLong(header.lumps[AASLUMP_EDGES].filelen);
00319 aasworld.edges = (aas_edge_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edges);
00320 if (!aasworld.edges) return false;
00321 aasworld.numedges = length / sizeof(aas_edge_t);
00322
00323 offset = fpoffset + LittleLong(header.lumps[AASLUMP_EDGEINDEX].fileofs);
00324 length = LittleLong(header.lumps[AASLUMP_EDGEINDEX].filelen);
00325 aasworld.edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.edgeindex);
00326 if (!aasworld.edgeindex) return false;
00327 aasworld.edgeindexsize = length / sizeof(aas_edgeindex_t);
00328
00329 offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACES].fileofs);
00330 length = LittleLong(header.lumps[AASLUMP_FACES].filelen);
00331 aasworld.faces = (aas_face_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faces);
00332 if (!aasworld.faces) return false;
00333 aasworld.numfaces = length / sizeof(aas_face_t);
00334
00335 offset = fpoffset + LittleLong(header.lumps[AASLUMP_FACEINDEX].fileofs);
00336 length = LittleLong(header.lumps[AASLUMP_FACEINDEX].filelen);
00337 aasworld.faceindex = (aas_faceindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.faceindex);
00338 if (!aasworld.faceindex) return false;
00339 aasworld.faceindexsize = length / sizeof(int);
00340
00341 offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREAS].fileofs);
00342 length = LittleLong(header.lumps[AASLUMP_AREAS].filelen);
00343 aasworld.areas = (aas_area_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areas);
00344 if (!aasworld.areas) return false;
00345 aasworld.numareas = length / sizeof(aas_area_t);
00346
00347 offset = fpoffset + LittleLong(header.lumps[AASLUMP_AREASETTINGS].fileofs);
00348 length = LittleLong(header.lumps[AASLUMP_AREASETTINGS].filelen);
00349 aasworld.areasettings = (aas_areasettings_t *) AAS_LoadAASLump(fp, offset, length, aasworld.areasettings);
00350 if (!aasworld.areasettings) return false;
00351 aasworld.numareasettings = length / sizeof(aas_areasettings_t);
00352
00353 offset = fpoffset + LittleLong(header.lumps[AASLUMP_REACHABILITY].fileofs);
00354 length = LittleLong(header.lumps[AASLUMP_REACHABILITY].filelen);
00355 aasworld.reachability = (aas_reachability_t *) AAS_LoadAASLump(fp, offset, length, aasworld.reachability);
00356 if (length && !aasworld.reachability) return false;
00357 aasworld.reachabilitysize = length / sizeof(aas_reachability_t);
00358
00359 offset = fpoffset + LittleLong(header.lumps[AASLUMP_NODES].fileofs);
00360 length = LittleLong(header.lumps[AASLUMP_NODES].filelen);
00361 aasworld.nodes = (aas_node_t *) AAS_LoadAASLump(fp, offset, length, aasworld.nodes);
00362 if (!aasworld.nodes) return false;
00363 aasworld.numnodes = length / sizeof(aas_node_t);
00364
00365 offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALS].fileofs);
00366 length = LittleLong(header.lumps[AASLUMP_PORTALS].filelen);
00367 aasworld.portals = (aas_portal_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portals);
00368 if (length && !aasworld.portals) return false;
00369 aasworld.numportals = length / sizeof(aas_portal_t);
00370
00371 offset = fpoffset + LittleLong(header.lumps[AASLUMP_PORTALINDEX].fileofs);
00372 length = LittleLong(header.lumps[AASLUMP_PORTALINDEX].filelen);
00373 aasworld.portalindex = (aas_portalindex_t *) AAS_LoadAASLump(fp, offset, length, aasworld.portalindex);
00374 if (length && !aasworld.portalindex) return false;
00375 aasworld.portalindexsize = length / sizeof(aas_portalindex_t);
00376
00377 offset = fpoffset + LittleLong(header.lumps[AASLUMP_CLUSTERS].fileofs);
00378 length = LittleLong(header.lumps[AASLUMP_CLUSTERS].filelen);
00379 aasworld.clusters = (aas_cluster_t *) AAS_LoadAASLump(fp, offset, length, aasworld.clusters);
00380 if (length && !aasworld.clusters) return false;
00381 aasworld.numclusters = length / sizeof(aas_cluster_t);
00382
00383 AAS_SwapAASData();
00384
00385 aasworld.loaded = true;
00386
00387 fclose(fp);
00388 return true;
00389 }
00390
00391
00392
00393
00394
00395
00396 int AAS_WriteAASLump(FILE *fp, aas_header_t *h, int lumpnum, void *data, int length)
00397 {
00398 aas_lump_t *lump;
00399
00400 lump = &h->lumps[lumpnum];
00401
00402 lump->fileofs = LittleLong(ftell(fp));
00403 lump->filelen = LittleLong(length);
00404
00405 if (length > 0)
00406 {
00407 if (fwrite(data, length, 1, fp) < 1)
00408 {
00409 Log_Print("error writing lump %s\n", lumpnum);
00410 fclose(fp);
00411 return false;
00412 }
00413 }
00414 return true;
00415 }
00416
00417
00418
00419
00420
00421
00422 void AAS_ShowNumReachabilities(int tt, char *name)
00423 {
00424 int i, num;
00425
00426 num = 0;
00427 for (i = 0; i < aasworld.reachabilitysize; i++)
00428 {
00429 if ((aasworld.reachability[i].traveltype & TRAVELTYPE_MASK) == tt)
00430 num++;
00431 }
00432 Log_Print("%6d %s\n", num, name);
00433 }
00434
00435
00436
00437
00438
00439
00440 void AAS_ShowTotals(void)
00441 {
00442 Log_Print("numvertexes = %d\r\n", aasworld.numvertexes);
00443 Log_Print("numplanes = %d\r\n", aasworld.numplanes);
00444 Log_Print("numedges = %d\r\n", aasworld.numedges);
00445 Log_Print("edgeindexsize = %d\r\n", aasworld.edgeindexsize);
00446 Log_Print("numfaces = %d\r\n", aasworld.numfaces);
00447 Log_Print("faceindexsize = %d\r\n", aasworld.faceindexsize);
00448 Log_Print("numareas = %d\r\n", aasworld.numareas);
00449 Log_Print("numareasettings = %d\r\n", aasworld.numareasettings);
00450 Log_Print("reachabilitysize = %d\r\n", aasworld.reachabilitysize);
00451 Log_Print("numnodes = %d\r\n", aasworld.numnodes);
00452 Log_Print("numportals = %d\r\n", aasworld.numportals);
00453 Log_Print("portalindexsize = %d\r\n", aasworld.portalindexsize);
00454 Log_Print("numclusters = %d\r\n", aasworld.numclusters);
00455 AAS_ShowNumReachabilities(TRAVEL_WALK, "walk");
00456 AAS_ShowNumReachabilities(TRAVEL_CROUCH, "crouch");
00457 AAS_ShowNumReachabilities(TRAVEL_BARRIERJUMP, "barrier jump");
00458 AAS_ShowNumReachabilities(TRAVEL_JUMP, "jump");
00459 AAS_ShowNumReachabilities(TRAVEL_LADDER, "ladder");
00460 AAS_ShowNumReachabilities(TRAVEL_WALKOFFLEDGE, "walk off ledge");
00461 AAS_ShowNumReachabilities(TRAVEL_SWIM, "swim");
00462 AAS_ShowNumReachabilities(TRAVEL_WATERJUMP, "water jump");
00463 AAS_ShowNumReachabilities(TRAVEL_TELEPORT, "teleport");
00464 AAS_ShowNumReachabilities(TRAVEL_ELEVATOR, "elevator");
00465 AAS_ShowNumReachabilities(TRAVEL_ROCKETJUMP, "rocket jump");
00466 AAS_ShowNumReachabilities(TRAVEL_BFGJUMP, "bfg jump");
00467 AAS_ShowNumReachabilities(TRAVEL_GRAPPLEHOOK, "grapple hook");
00468 AAS_ShowNumReachabilities(TRAVEL_DOUBLEJUMP, "double jump");
00469 AAS_ShowNumReachabilities(TRAVEL_RAMPJUMP, "ramp jump");
00470 AAS_ShowNumReachabilities(TRAVEL_STRAFEJUMP, "strafe jump");
00471 AAS_ShowNumReachabilities(TRAVEL_JUMPPAD, "jump pad");
00472 AAS_ShowNumReachabilities(TRAVEL_FUNCBOB, "func bob");
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 qboolean AAS_WriteAASFile(char *filename)
00482 {
00483 aas_header_t header;
00484 FILE *fp;
00485
00486 Log_Print("writing %s\n", filename);
00487 AAS_ShowTotals();
00488
00489 AAS_SwapAASData();
00490
00491 memset(&header, 0, sizeof(aas_header_t));
00492 header.ident = LittleLong(AASID);
00493 header.version = LittleLong(AASVERSION);
00494 header.bspchecksum = LittleLong(aasworld.bspchecksum);
00495
00496 fp = fopen(filename, "wb");
00497 if (!fp)
00498 {
00499 Log_Print("error opening %s\n", filename);
00500 return false;
00501 }
00502
00503 if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
00504 {
00505 fclose(fp);
00506 return false;
00507 }
00508
00509 if (!AAS_WriteAASLump(fp, &header, AASLUMP_BBOXES, aasworld.bboxes,
00510 aasworld.numbboxes * sizeof(aas_bbox_t))) return false;
00511 if (!AAS_WriteAASLump(fp, &header, AASLUMP_VERTEXES, aasworld.vertexes,
00512 aasworld.numvertexes * sizeof(aas_vertex_t))) return false;
00513 if (!AAS_WriteAASLump(fp, &header, AASLUMP_PLANES, aasworld.planes,
00514 aasworld.numplanes * sizeof(aas_plane_t))) return false;
00515 if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGES, aasworld.edges,
00516 aasworld.numedges * sizeof(aas_edge_t))) return false;
00517 if (!AAS_WriteAASLump(fp, &header, AASLUMP_EDGEINDEX, aasworld.edgeindex,
00518 aasworld.edgeindexsize * sizeof(aas_edgeindex_t))) return false;
00519 if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACES, aasworld.faces,
00520 aasworld.numfaces * sizeof(aas_face_t))) return false;
00521 if (!AAS_WriteAASLump(fp, &header, AASLUMP_FACEINDEX, aasworld.faceindex,
00522 aasworld.faceindexsize * sizeof(aas_faceindex_t))) return false;
00523 if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREAS, aasworld.areas,
00524 aasworld.numareas * sizeof(aas_area_t))) return false;
00525 if (!AAS_WriteAASLump(fp, &header, AASLUMP_AREASETTINGS, aasworld.areasettings,
00526 aasworld.numareasettings * sizeof(aas_areasettings_t))) return false;
00527 if (!AAS_WriteAASLump(fp, &header, AASLUMP_REACHABILITY, aasworld.reachability,
00528 aasworld.reachabilitysize * sizeof(aas_reachability_t))) return false;
00529 if (!AAS_WriteAASLump(fp, &header, AASLUMP_NODES, aasworld.nodes,
00530 aasworld.numnodes * sizeof(aas_node_t))) return false;
00531 if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALS, aasworld.portals,
00532 aasworld.numportals * sizeof(aas_portal_t))) return false;
00533 if (!AAS_WriteAASLump(fp, &header, AASLUMP_PORTALINDEX, aasworld.portalindex,
00534 aasworld.portalindexsize * sizeof(aas_portalindex_t))) return false;
00535 if (!AAS_WriteAASLump(fp, &header, AASLUMP_CLUSTERS, aasworld.clusters,
00536 aasworld.numclusters * sizeof(aas_cluster_t))) return false;
00537
00538 fseek(fp, 0, SEEK_SET);
00539 AAS_DData((unsigned char *) &header + 8, sizeof(aas_header_t) - 8);
00540 if (fwrite(&header, sizeof(aas_header_t), 1, fp) < 1)
00541 {
00542 fclose(fp);
00543 return false;
00544 }
00545
00546 fclose(fp);
00547 return true;
00548 }
00549