/* =========================================================================== Return to Castle Wolfenstein single player GPL Source Code Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”). RTCW SP Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. RTCW SP Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RTCW SP Source Code. If not, see . 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. 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. =========================================================================== */ //=========================================================================== // // Name: aas_file.c // Function: AAS file loading and writing // Programmer: Mr Elusive (MrElusive@demigod.demon.nl) // Last update: 1997-12-04 // Tab Size: 3 //=========================================================================== #include "qbsp.h" #include "../botlib/aasfile.h" #include "aas_file.h" #include "aas_store.h" #include "aas_create.h" #define AAS_Error Error //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_SwapAASData( void ) { int i, j; //bounding boxes for ( i = 0; i < ( *aasworld ).numbboxes; i++ ) { ( *aasworld ).bboxes[i].presencetype = LittleLong( ( *aasworld ).bboxes[i].presencetype ); ( *aasworld ).bboxes[i].flags = LittleLong( ( *aasworld ).bboxes[i].flags ); for ( j = 0; j < 3; j++ ) { ( *aasworld ).bboxes[i].mins[j] = LittleLong( ( *aasworld ).bboxes[i].mins[j] ); ( *aasworld ).bboxes[i].maxs[j] = LittleLong( ( *aasworld ).bboxes[i].maxs[j] ); } //end for } //end for //vertexes for ( i = 0; i < ( *aasworld ).numvertexes; i++ ) { for ( j = 0; j < 3; j++ ) ( *aasworld ).vertexes[i][j] = LittleFloat( ( *aasworld ).vertexes[i][j] ); } //end for //planes for ( i = 0; i < ( *aasworld ).numplanes; i++ ) { for ( j = 0; j < 3; j++ ) ( *aasworld ).planes[i].normal[j] = LittleFloat( ( *aasworld ).planes[i].normal[j] ); ( *aasworld ).planes[i].dist = LittleFloat( ( *aasworld ).planes[i].dist ); ( *aasworld ).planes[i].type = LittleLong( ( *aasworld ).planes[i].type ); } //end for //edges for ( i = 0; i < ( *aasworld ).numedges; i++ ) { ( *aasworld ).edges[i].v[0] = LittleLong( ( *aasworld ).edges[i].v[0] ); ( *aasworld ).edges[i].v[1] = LittleLong( ( *aasworld ).edges[i].v[1] ); } //end for //edgeindex for ( i = 0; i < ( *aasworld ).edgeindexsize; i++ ) { ( *aasworld ).edgeindex[i] = LittleLong( ( *aasworld ).edgeindex[i] ); } //end for //faces for ( i = 0; i < ( *aasworld ).numfaces; i++ ) { ( *aasworld ).faces[i].planenum = LittleLong( ( *aasworld ).faces[i].planenum ); ( *aasworld ).faces[i].faceflags = LittleLong( ( *aasworld ).faces[i].faceflags ); ( *aasworld ).faces[i].numedges = LittleLong( ( *aasworld ).faces[i].numedges ); ( *aasworld ).faces[i].firstedge = LittleLong( ( *aasworld ).faces[i].firstedge ); ( *aasworld ).faces[i].frontarea = LittleLong( ( *aasworld ).faces[i].frontarea ); ( *aasworld ).faces[i].backarea = LittleLong( ( *aasworld ).faces[i].backarea ); } //end for //face index for ( i = 0; i < ( *aasworld ).faceindexsize; i++ ) { ( *aasworld ).faceindex[i] = LittleLong( ( *aasworld ).faceindex[i] ); } //end for //convex areas for ( i = 0; i < ( *aasworld ).numareas; i++ ) { ( *aasworld ).areas[i].areanum = LittleLong( ( *aasworld ).areas[i].areanum ); ( *aasworld ).areas[i].numfaces = LittleLong( ( *aasworld ).areas[i].numfaces ); ( *aasworld ).areas[i].firstface = LittleLong( ( *aasworld ).areas[i].firstface ); for ( j = 0; j < 3; j++ ) { ( *aasworld ).areas[i].mins[j] = LittleFloat( ( *aasworld ).areas[i].mins[j] ); ( *aasworld ).areas[i].maxs[j] = LittleFloat( ( *aasworld ).areas[i].maxs[j] ); ( *aasworld ).areas[i].center[j] = LittleFloat( ( *aasworld ).areas[i].center[j] ); } //end for } //end for //area settings for ( i = 0; i < ( *aasworld ).numareasettings; i++ ) { ( *aasworld ).areasettings[i].contents = LittleLong( ( *aasworld ).areasettings[i].contents ); ( *aasworld ).areasettings[i].areaflags = LittleLong( ( *aasworld ).areasettings[i].areaflags ); ( *aasworld ).areasettings[i].presencetype = LittleLong( ( *aasworld ).areasettings[i].presencetype ); ( *aasworld ).areasettings[i].cluster = LittleLong( ( *aasworld ).areasettings[i].cluster ); ( *aasworld ).areasettings[i].clusterareanum = LittleLong( ( *aasworld ).areasettings[i].clusterareanum ); ( *aasworld ).areasettings[i].numreachableareas = LittleLong( ( *aasworld ).areasettings[i].numreachableareas ); ( *aasworld ).areasettings[i].firstreachablearea = LittleLong( ( *aasworld ).areasettings[i].firstreachablearea ); // Ridah ( *aasworld ).areasettings[i].groundsteepness = LittleFloat( ( *aasworld ).areasettings[i].groundsteepness ); } //end for //area reachability for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ ) { ( *aasworld ).reachability[i].areanum = LittleLong( ( *aasworld ).reachability[i].areanum ); ( *aasworld ).reachability[i].facenum = LittleLong( ( *aasworld ).reachability[i].facenum ); ( *aasworld ).reachability[i].edgenum = LittleLong( ( *aasworld ).reachability[i].edgenum ); for ( j = 0; j < 3; j++ ) { ( *aasworld ).reachability[i].start[j] = LittleFloat( ( *aasworld ).reachability[i].start[j] ); ( *aasworld ).reachability[i].end[j] = LittleFloat( ( *aasworld ).reachability[i].end[j] ); } //end for ( *aasworld ).reachability[i].traveltype = LittleLong( ( *aasworld ).reachability[i].traveltype ); ( *aasworld ).reachability[i].traveltime = LittleShort( ( *aasworld ).reachability[i].traveltime ); } //end for //nodes for ( i = 0; i < ( *aasworld ).numnodes; i++ ) { ( *aasworld ).nodes[i].planenum = LittleLong( ( *aasworld ).nodes[i].planenum ); ( *aasworld ).nodes[i].children[0] = LittleLong( ( *aasworld ).nodes[i].children[0] ); ( *aasworld ).nodes[i].children[1] = LittleLong( ( *aasworld ).nodes[i].children[1] ); } //end for //cluster portals for ( i = 0; i < ( *aasworld ).numportals; i++ ) { ( *aasworld ).portals[i].areanum = LittleLong( ( *aasworld ).portals[i].areanum ); ( *aasworld ).portals[i].frontcluster = LittleLong( ( *aasworld ).portals[i].frontcluster ); ( *aasworld ).portals[i].backcluster = LittleLong( ( *aasworld ).portals[i].backcluster ); ( *aasworld ).portals[i].clusterareanum[0] = LittleLong( ( *aasworld ).portals[i].clusterareanum[0] ); ( *aasworld ).portals[i].clusterareanum[1] = LittleLong( ( *aasworld ).portals[i].clusterareanum[1] ); } //end for //cluster portal index for ( i = 0; i < ( *aasworld ).portalindexsize; i++ ) { ( *aasworld ).portalindex[i] = LittleLong( ( *aasworld ).portalindex[i] ); } //end for //cluster for ( i = 0; i < ( *aasworld ).numclusters; i++ ) { ( *aasworld ).clusters[i].numareas = LittleLong( ( *aasworld ).clusters[i].numareas ); ( *aasworld ).clusters[i].numportals = LittleLong( ( *aasworld ).clusters[i].numportals ); ( *aasworld ).clusters[i].firstportal = LittleLong( ( *aasworld ).clusters[i].firstportal ); } //end for } //end of the function AAS_SwapAASData //=========================================================================== // dump the current loaded aas file // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_DumpAASData( void ) { /* if ((*aasworld).vertexes) FreeMemory((*aasworld).vertexes); (*aasworld).vertexes = NULL; if ((*aasworld).planes) FreeMemory((*aasworld).planes); (*aasworld).planes = NULL; if ((*aasworld).edges) FreeMemory((*aasworld).edges); (*aasworld).edges = NULL; if ((*aasworld).edgeindex) FreeMemory((*aasworld).edgeindex); (*aasworld).edgeindex = NULL; if ((*aasworld).faces) FreeMemory((*aasworld).faces); (*aasworld).faces = NULL; if ((*aasworld).faceindex) FreeMemory((*aasworld).faceindex); (*aasworld).faceindex = NULL; if ((*aasworld).areas) FreeMemory((*aasworld).areas); (*aasworld).areas = NULL; if ((*aasworld).areasettings) FreeMemory((*aasworld).areasettings); (*aasworld).areasettings = NULL; if ((*aasworld).reachability) FreeMemory((*aasworld).reachability); (*aasworld).reachability = NULL; */ ( *aasworld ).loaded = false; } //end of the function AAS_DumpAASData //=========================================================================== // allocate memory and read a lump of a AAS file // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== char *AAS_LoadAASLump( FILE *fp, int offset, int length, void *buf ) { if ( !length ) { printf( "lump size 0\n" ); return buf; } //end if //seek to the data if ( fseek( fp, offset, SEEK_SET ) ) { AAS_Error( "can't seek to lump\n" ); AAS_DumpAASData(); fclose( fp ); return 0; } //end if //allocate memory if ( !buf ) { buf = (void *) GetClearedMemory( length ); } //read the data if ( fread( (char *) buf, 1, length, fp ) != length ) { AAS_Error( "can't read lump\n" ); FreeMemory( buf ); AAS_DumpAASData(); fclose( fp ); return NULL; } //end if return buf; } //end of the function AAS_LoadAASLump //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_DData( unsigned char *data, int size ) { int i; for ( i = 0; i < size; i++ ) { data[i] ^= (unsigned char) i * 119; } //end for } //end of the function AAS_DData //=========================================================================== // load an aas file // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean AAS_LoadAASFile( char *filename, int fpoffset, int fplength ) { FILE *fp; aas_header_t header; int offset, length; //dump current loaded aas file AAS_DumpAASData(); //open the file fp = fopen( filename, "rb" ); if ( !fp ) { AAS_Error( "can't open %s\n", filename ); return false; } //end if //seek to the correct position (in the pak file) if ( fseek( fp, fpoffset, SEEK_SET ) ) { AAS_Error( "can't seek to file %s\n" ); fclose( fp ); return false; } //end if //read the header if ( fread( &header, sizeof( aas_header_t ), 1, fp ) != 1 ) { AAS_Error( "can't read header of file %s\n", filename ); fclose( fp ); return false; } //end if //check header identification header.ident = LittleLong( header.ident ); if ( header.ident != AASID ) { AAS_Error( "%s is not an AAS file\n", filename ); fclose( fp ); return false; } //end if //check the version header.version = LittleLong( header.version ); if ( header.version != AASVERSION ) { AAS_Error( "%s is version %i, not %i\n", filename, header.version, AASVERSION ); fclose( fp ); return false; } //end if // if ( header.version == AASVERSION ) { AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 ); } //end if ( *aasworld ).bspchecksum = LittleLong( header.bspchecksum ); //load the lumps: //bounding boxes offset = fpoffset + LittleLong( header.lumps[AASLUMP_BBOXES].fileofs ); length = LittleLong( header.lumps[AASLUMP_BBOXES].filelen ); ( *aasworld ).bboxes = (aas_bbox_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).bboxes ); if ( !( *aasworld ).bboxes ) { return false; } ( *aasworld ).numbboxes = length / sizeof( aas_bbox_t ); //vertexes offset = fpoffset + LittleLong( header.lumps[AASLUMP_VERTEXES].fileofs ); length = LittleLong( header.lumps[AASLUMP_VERTEXES].filelen ); ( *aasworld ).vertexes = (aas_vertex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).vertexes ); if ( !( *aasworld ).vertexes ) { return false; } ( *aasworld ).numvertexes = length / sizeof( aas_vertex_t ); //planes offset = fpoffset + LittleLong( header.lumps[AASLUMP_PLANES].fileofs ); length = LittleLong( header.lumps[AASLUMP_PLANES].filelen ); ( *aasworld ).planes = (aas_plane_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).planes ); if ( !( *aasworld ).planes ) { return false; } ( *aasworld ).numplanes = length / sizeof( aas_plane_t ); //edges offset = fpoffset + LittleLong( header.lumps[AASLUMP_EDGES].fileofs ); length = LittleLong( header.lumps[AASLUMP_EDGES].filelen ); ( *aasworld ).edges = (aas_edge_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).edges ); if ( !( *aasworld ).edges ) { return false; } ( *aasworld ).numedges = length / sizeof( aas_edge_t ); //edgeindex offset = fpoffset + LittleLong( header.lumps[AASLUMP_EDGEINDEX].fileofs ); length = LittleLong( header.lumps[AASLUMP_EDGEINDEX].filelen ); ( *aasworld ).edgeindex = (aas_edgeindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).edgeindex ); if ( !( *aasworld ).edgeindex ) { return false; } ( *aasworld ).edgeindexsize = length / sizeof( aas_edgeindex_t ); //faces offset = fpoffset + LittleLong( header.lumps[AASLUMP_FACES].fileofs ); length = LittleLong( header.lumps[AASLUMP_FACES].filelen ); ( *aasworld ).faces = (aas_face_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).faces ); if ( !( *aasworld ).faces ) { return false; } ( *aasworld ).numfaces = length / sizeof( aas_face_t ); //faceindex offset = fpoffset + LittleLong( header.lumps[AASLUMP_FACEINDEX].fileofs ); length = LittleLong( header.lumps[AASLUMP_FACEINDEX].filelen ); ( *aasworld ).faceindex = (aas_faceindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).faceindex ); if ( !( *aasworld ).faceindex ) { return false; } ( *aasworld ).faceindexsize = length / sizeof( int ); //convex areas offset = fpoffset + LittleLong( header.lumps[AASLUMP_AREAS].fileofs ); length = LittleLong( header.lumps[AASLUMP_AREAS].filelen ); ( *aasworld ).areas = (aas_area_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).areas ); if ( !( *aasworld ).areas ) { return false; } ( *aasworld ).numareas = length / sizeof( aas_area_t ); //area settings offset = fpoffset + LittleLong( header.lumps[AASLUMP_AREASETTINGS].fileofs ); length = LittleLong( header.lumps[AASLUMP_AREASETTINGS].filelen ); ( *aasworld ).areasettings = (aas_areasettings_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).areasettings ); if ( !( *aasworld ).areasettings ) { return false; } ( *aasworld ).numareasettings = length / sizeof( aas_areasettings_t ); //reachability list offset = fpoffset + LittleLong( header.lumps[AASLUMP_REACHABILITY].fileofs ); length = LittleLong( header.lumps[AASLUMP_REACHABILITY].filelen ); ( *aasworld ).reachability = (aas_reachability_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).reachability ); if ( length && !( *aasworld ).reachability ) { return false; } ( *aasworld ).reachabilitysize = length / sizeof( aas_reachability_t ); //nodes offset = fpoffset + LittleLong( header.lumps[AASLUMP_NODES].fileofs ); length = LittleLong( header.lumps[AASLUMP_NODES].filelen ); ( *aasworld ).nodes = (aas_node_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).nodes ); if ( !( *aasworld ).nodes ) { return false; } ( *aasworld ).numnodes = length / sizeof( aas_node_t ); //cluster portals offset = fpoffset + LittleLong( header.lumps[AASLUMP_PORTALS].fileofs ); length = LittleLong( header.lumps[AASLUMP_PORTALS].filelen ); ( *aasworld ).portals = (aas_portal_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).portals ); if ( length && !( *aasworld ).portals ) { return false; } ( *aasworld ).numportals = length / sizeof( aas_portal_t ); //cluster portal index offset = fpoffset + LittleLong( header.lumps[AASLUMP_PORTALINDEX].fileofs ); length = LittleLong( header.lumps[AASLUMP_PORTALINDEX].filelen ); ( *aasworld ).portalindex = (aas_portalindex_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).portalindex ); if ( length && !( *aasworld ).portalindex ) { return false; } ( *aasworld ).portalindexsize = length / sizeof( aas_portalindex_t ); //clusters offset = fpoffset + LittleLong( header.lumps[AASLUMP_CLUSTERS].fileofs ); length = LittleLong( header.lumps[AASLUMP_CLUSTERS].filelen ); ( *aasworld ).clusters = (aas_cluster_t *) AAS_LoadAASLump( fp, offset, length, ( *aasworld ).clusters ); if ( length && !( *aasworld ).clusters ) { return false; } ( *aasworld ).numclusters = length / sizeof( aas_cluster_t ); //swap everything AAS_SwapAASData(); //aas file is loaded ( *aasworld ).loaded = true; //close the file fclose( fp ); return true; } //end of the function AAS_LoadAASFile //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== int AAS_WriteAASLump( FILE *fp, aas_header_t *h, int lumpnum, void *data, int length ) { aas_lump_t *lump; lump = &h->lumps[lumpnum]; lump->fileofs = LittleLong( ftell( fp ) ); lump->filelen = LittleLong( length ); if ( length > 0 ) { if ( fwrite( data, length, 1, fp ) < 1 ) { Log_Print( "error writing lump %s\n", lumpnum ); fclose( fp ); return false; } //end if } //end if return true; } //end of the function AAS_WriteAASLump //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ShowNumReachabilities( int tt, char *name ) { int i, num; num = 0; for ( i = 0; i < ( *aasworld ).reachabilitysize; i++ ) { if ( ( ( *aasworld ).reachability[i].traveltype & TRAVELTYPE_MASK ) == tt ) { num++; } } //end for Log_Print( "%6d %s\n", num, name ); } //end of the function AAS_ShowNumReachabilities //=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AAS_ShowTotals( void ) { Log_Print( "numvertexes = %d\r\n", ( *aasworld ).numvertexes ); Log_Print( "numplanes = %d\r\n", ( *aasworld ).numplanes ); Log_Print( "numedges = %d\r\n", ( *aasworld ).numedges ); Log_Print( "edgeindexsize = %d\r\n", ( *aasworld ).edgeindexsize ); Log_Print( "numfaces = %d\r\n", ( *aasworld ).numfaces ); Log_Print( "faceindexsize = %d\r\n", ( *aasworld ).faceindexsize ); Log_Print( "numareas = %d\r\n", ( *aasworld ).numareas ); Log_Print( "numareasettings = %d\r\n", ( *aasworld ).numareasettings ); Log_Print( "reachabilitysize = %d\r\n", ( *aasworld ).reachabilitysize ); Log_Print( "numnodes = %d\r\n", ( *aasworld ).numnodes ); Log_Print( "numportals = %d\r\n", ( *aasworld ).numportals ); Log_Print( "portalindexsize = %d\r\n", ( *aasworld ).portalindexsize ); Log_Print( "numclusters = %d\r\n", ( *aasworld ).numclusters ); AAS_ShowNumReachabilities( TRAVEL_WALK, "walk" ); AAS_ShowNumReachabilities( TRAVEL_CROUCH, "crouch" ); AAS_ShowNumReachabilities( TRAVEL_BARRIERJUMP, "barrier jump" ); AAS_ShowNumReachabilities( TRAVEL_JUMP, "jump" ); AAS_ShowNumReachabilities( TRAVEL_LADDER, "ladder" ); AAS_ShowNumReachabilities( TRAVEL_WALKOFFLEDGE, "walk off ledge" ); AAS_ShowNumReachabilities( TRAVEL_SWIM, "swim" ); AAS_ShowNumReachabilities( TRAVEL_WATERJUMP, "water jump" ); AAS_ShowNumReachabilities( TRAVEL_TELEPORT, "teleport" ); AAS_ShowNumReachabilities( TRAVEL_ELEVATOR, "elevator" ); AAS_ShowNumReachabilities( TRAVEL_ROCKETJUMP, "rocket jump" ); AAS_ShowNumReachabilities( TRAVEL_BFGJUMP, "bfg jump" ); AAS_ShowNumReachabilities( TRAVEL_GRAPPLEHOOK, "grapple hook" ); AAS_ShowNumReachabilities( TRAVEL_DOUBLEJUMP, "double jump" ); AAS_ShowNumReachabilities( TRAVEL_RAMPJUMP, "ramp jump" ); AAS_ShowNumReachabilities( TRAVEL_STRAFEJUMP, "strafe jump" ); AAS_ShowNumReachabilities( TRAVEL_JUMPPAD, "jump pad" ); AAS_ShowNumReachabilities( TRAVEL_FUNCBOB, "func bob" ); } //end of the function AAS_ShowTotals //=========================================================================== // aas data is useless after writing to file because it is byte swapped // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean AAS_WriteAASFile( char *filename ) { aas_header_t header; FILE *fp; Log_Print( "writing %s\n", filename ); AAS_ShowTotals(); //swap the aas data AAS_SwapAASData(); //initialize the file header memset( &header, 0, sizeof( aas_header_t ) ); header.ident = LittleLong( AASID ); header.version = LittleLong( AASVERSION ); header.bspchecksum = LittleLong( ( *aasworld ).bspchecksum ); //open a new file fp = fopen( filename, "wb" ); if ( !fp ) { Log_Print( "error opening %s\n", filename ); return false; } //end if //write the header if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) { fclose( fp ); return false; } //end if //add the data lumps to the file if ( !AAS_WriteAASLump( fp, &header, AASLUMP_BBOXES, ( *aasworld ).bboxes, ( *aasworld ).numbboxes * sizeof( aas_bbox_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_VERTEXES, ( *aasworld ).vertexes, ( *aasworld ).numvertexes * sizeof( aas_vertex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PLANES, ( *aasworld ).planes, ( *aasworld ).numplanes * sizeof( aas_plane_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGES, ( *aasworld ).edges, ( *aasworld ).numedges * sizeof( aas_edge_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGEINDEX, ( *aasworld ).edgeindex, ( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACES, ( *aasworld ).faces, ( *aasworld ).numfaces * sizeof( aas_face_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACEINDEX, ( *aasworld ).faceindex, ( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREAS, ( *aasworld ).areas, ( *aasworld ).numareas * sizeof( aas_area_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREASETTINGS, ( *aasworld ).areasettings, ( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_REACHABILITY, ( *aasworld ).reachability, ( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_NODES, ( *aasworld ).nodes, ( *aasworld ).numnodes * sizeof( aas_node_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALS, ( *aasworld ).portals, ( *aasworld ).numportals * sizeof( aas_portal_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALINDEX, ( *aasworld ).portalindex, ( *aasworld ).portalindexsize * sizeof( aas_portalindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_CLUSTERS, ( *aasworld ).clusters, ( *aasworld ).numclusters * sizeof( aas_cluster_t ) ) ) { return false; } //rewrite the header with the added lumps fseek( fp, 0, SEEK_SET ); AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 ); if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) { fclose( fp ); return false; } //end if //close the file fclose( fp ); return true; } //end of the function AAS_WriteAASFile