bool C3Sav::Impl::loadCity( std::fstream& f, Game& game ) { uint32_t tmp; // need to rewrite better std::vector<short int> graphicGrid; graphicGrid.resize( 26244, 0 ); std::vector<unsigned char> edgeGrid; edgeGrid.resize( 26244, 0 ); std::vector<short int> terrainGrid; terrainGrid.resize( 26244, 0 ); std::vector<unsigned char> rndmTerGrid; rndmTerGrid.resize(26244, 0); std::vector<unsigned char> randomGrid; randomGrid.resize( 26244, 0 ); std::vector<unsigned char> zeroGrid; zeroGrid.resize( 26244, 0 ); if( !f.is_open() ) { Logger::warning( "GameLoaderC3Sav: can't open file " ); return false; } f.read( (char*)&tmp, 4); // read dummy std::string cityName = LoaderHelper::getDefaultCityName( tmp ); game.city()->setName( cityName ); f.read((char*)&tmp, 4); // read scenario flag try { f.read((char*)&tmp, 4); // read length of compressed chunk Logger::warning( "GameLoaderC3Sav: length of compressed ids is %d", tmp ); PKWareInputStream *pk = new PKWareInputStream(&f, false, tmp); for (int i = 0; i < 162 * 162; i++) { graphicGrid[i] = pk->readShort(); } pk->empty(); delete pk; f.read((char*)&tmp, 4); // read length of compressed chunk Logger::warning( "GameLoaderC3Sav: length of compressed egdes is %d", tmp ); pk = new PKWareInputStream(&f, false, tmp); for (int i = 0; i < 162 * 162; i++) { edgeGrid[i] = pk->readByte(); } pk->empty(); delete pk; SkipCompressed(f); // skip building ids f.read((char*)&tmp, 4); // read length of compressed chunk Logger::warning( "GameLoaderC3Sav: length of compressed terraindata is %d", tmp ); pk = new PKWareInputStream(&f, false, tmp); for (int i = 0; i < 162 * 162; i++) { terrainGrid[i] = pk->readShort(); } pk->empty(); delete pk; SkipCompressed(f); SkipCompressed(f); SkipCompressed(f); SkipCompressed(f); f.read((char*)&randomGrid[0], 26244); SkipCompressed(f); SkipCompressed(f); SkipCompressed(f); SkipCompressed(f); SkipCompressed(f); // here goes walkers array f.read((char*)&tmp, 4); // read length of compressed chunk Logger::warning( "GameLoaderC3Sav: length of compressed walkers data is %d", tmp ); pk = new PKWareInputStream(&f, false, tmp); for (int j = 0; j < 1000; j++) { pk->skip(10); pk->readShort(); pk->skip(8); pk->readByte(); pk->readByte(); pk->skip(106); } pk->empty(); delete pk; int length; f.read((char*)&length, 4); // read next length :-) if (length <= 0) f.seekg(1200, std::ios::cur); else f.seekg(length, std::ios::cur); SkipCompressed(f); SkipCompressed(f); // 3x int f.read((char*)&tmp, 4); f.read((char*)&tmp, 4); f.read((char*)&tmp, 4); SkipCompressed(f); f.seekg(70, std::ios::cur); SkipCompressed(f); // skip building list f.seekg(208, std::ios::cur); SkipCompressed(f); // skip unknown f.seekg(788, std::ios::cur); // skip unused data f.read((char*)&tmp, 4); //mapsize int size = tmp; PlayerCityPtr oCity = game.city(); Tilemap& oTilemap = oCity->tilemap(); oCity->resize(size); oCity->setCameraPos( TilePos( 0, 0 ) ); initEntryExit( f, game.city() ); f.seekg(1312, std::ios::cur); char climate; f.read(&climate, 1); oCity->setClimate((ClimateType)climate); // here goes the WORK! // loads the graphics map int border_size = (162 - size) / 2; std::map< int, std::map< int, unsigned char > > edgeData; game.city()->setCameraPos( TilePos( size/2, size/2 ) ); for (int itA = 0; itA < size; ++itA) { for (int itB = 0; itB < size; ++itB) { int i = itB; int j = size - itA - 1; int index = 162 * (border_size + itA) + border_size + itB; Tile& tile = oTilemap.at(i, j); unsigned int imgId = graphicGrid[index]; Picture pic = imgid::toPicture( imgId ); if( pic.isValid() ) { tile.setPicture( pic ); tile.setOriginalImgId( imgId ); } else { TileOverlay::Type ovType = LoaderHelper::convImgId2ovrType( imgId ); if( ovType == constants::objects::unknown ) { Logger::warning( "!!! GameLoaderC3Sav: Unknown building %x at [%d,%d]", imgId, i, j ); } baseBuildings[ tile.pos() ] = imgId; pic = Picture::load( ResourceGroup::land1a, 230 + math::random( 57 ) ); tile.setPicture( pic ); tile.setOriginalImgId( imgid::fromResource( pic.name() ) ); } edgeData[ i ][ j ] = edgeGrid[index]; tile::decode( tile, terrainGrid[index] ); tile::fixPlateauFlags( tile ); } } for (int i = 0; i < size; ++i) { for (int j = 0; j < size; ++j) { unsigned char ed = edgeData[ i][ j ]; if( ed == 0x00) { int size = 1; { int dj; try { // find size, 5 is maximal size for building for (dj = 0; dj < 5; ++dj) { int edd = edgeData[ i ][ j - dj ]; // find bottom left corner if (edd == 8 * dj + 0x40) { size = dj + 1; break; } } } catch(...) { size = dj + 1; } } Tile& master = oTilemap.at(i, j - size + 1); //Logger::warning( "Master will be at (%d,%d)", master.i(), master.j() ); for (int di = 0; di < size; ++di) { for (int dj = 0; dj < size; ++dj) { oTilemap.at(master.i() + di, master.j() + dj).setMasterTile(&master); } } } // Check if it is building and type of building //if (ttile.getMasterTile() == NULL) std::map<TilePos, unsigned int>::iterator bbIt = baseBuildings.find( TilePos( i, j ) ); unsigned int bbImgId = bbIt == baseBuildings.end() ? 0 : bbIt->second; Tile& tile = oTilemap.at( i, j ); Tile* masterTile = tile.masterTile(); if( !masterTile ) masterTile = &tile; if( masterTile->overlay().isNull() ) { LoaderHelper::decodeTerrain( *masterTile, oCity, bbImgId ); } } } } catch(PKException) { THROW("fatal error when unpacking"); } return true; }
void C3Map::Impl::loadCity(std::fstream& f, PlayerCityPtr oCity) { Tilemap& oTilemap = oCity->tilemap(); /* get number of city */ f.seekg(kLocation, std::ios::beg); unsigned int location=0; f.read((char*)&location, 1); Logger::warning( "C3MapLoader: location of city is %d", (int)(location) ); std::string cityName = LoaderHelper::getDefaultCityName( location ); oCity->setName( cityName ); f.seekg(kSize, std::ios::beg); int map_size; // 32bits int size_2; f.read((char*)&map_size, 4); f.read((char*)&size_2, 4); Logger::warning( "C3MapLoader: map size is %d", map_size ); if (map_size != size_2) { THROW("Horizontal and vertical map sizes are different!"); } oCity->resize(map_size); // need to rewrite better ScopedArrayPtr<short> pGraphicGrid( new short[tilemap::c3mapSizeSq] ); ScopedArrayPtr<unsigned char> pEdgeGrid( new unsigned char[tilemap::c3mapSizeSq] ); ScopedArrayPtr<short> pTerrainGrid( new short[tilemap::c3mapSizeSq] ); ScopedArrayPtr<unsigned char> pRndmTerGrid( new unsigned char[tilemap::c3mapSizeSq] ); ScopedArrayPtr<unsigned char> pRandomGrid( new unsigned char[tilemap::c3mapSizeSq] ); ScopedArrayPtr<unsigned char> pElevationGrid( new unsigned char[tilemap::c3mapSizeSq] ); if( pGraphicGrid.isNull() || pEdgeGrid.isNull() || pTerrainGrid.isNull() || pRndmTerGrid.isNull() || pRandomGrid.isNull() || pElevationGrid.isNull() ) { THROW("NOT ENOUGH MEMORY!!!! FATAL"); } // here also make copy of original arrays in memory f.seekg(kGraphicGrid, std::ios::beg); f.read((char*)pGraphicGrid.data(), tilemap::c3mapSizeSq*2); f.seekg(kEdgeGrid, std::ios::beg); f.read((char*)pEdgeGrid.data(), tilemap::c3mapSizeSq); f.seekg(kTerrainGrid, std::ios::beg); f.read((char*)pTerrainGrid.data(), tilemap::c3mapSizeSq*2); f.seekg(kRndmTerGrid, std::ios::beg); f.read((char*)pRndmTerGrid.data(), tilemap::c3mapSizeSq); f.seekg(kRandomGrid, std::ios::beg); f.read((char*)pRandomGrid.data(), tilemap::c3mapSizeSq); f.seekg(kElevationGrid, std::ios::beg); f.read((char*)pElevationGrid.data(), tilemap::c3mapSizeSq); std::map< int, std::map< int, unsigned char > > edgeData; // loads the graphics map int border_size = (gfx::tilemap::c3mapSize - map_size) / 2; for (int itA = 0; itA < map_size; ++itA) { for (int itB = 0; itB < map_size; ++itB) { int i = itB; int j = map_size - itA - 1; int index = gfx::tilemap::c3mapSize * (border_size + itA) + border_size + itB; Tile& tile = oTilemap.at(i, j); tile.setPicture( imgid::toResource( pGraphicGrid.data()[index] ) ); tile.setOriginalImgId( pGraphicGrid.data()[index] ); //tile.setHeight( pElevationGrid.data()[ index ] ); edgeData[ i ][ j ] = pEdgeGrid.data()[index]; tile::decode( tile, pTerrainGrid.data()[index] ); tile::fixPlateauFlags( tile ); } } for (int i = 0; i < map_size; ++i) { for (int j = 0; j < map_size; ++j) { unsigned char ed = edgeData[ i ][ j ]; if( ed == 0x00) { int size = 1; { int dj; try { // find size, 5 is maximal size for building for (dj = 0; dj < gfx::tilemap::c3bldSize; ++dj) { int edd = edgeData[ i ][ j - dj ]; // find bottom left corner if (edd == 8 * dj + 0x40) { size = dj + 1; break; } } } catch(...) { size = dj + 1; } } Tile& master = oTilemap.at(i, j - size + 1); for (int di = 0; di < size; ++di) { for (int dj = 0; dj < size; ++dj) { oTilemap.at(master.pos() + TilePos( di, dj ) ).setMasterTile(&master); } } } // Check if it is building and type of building //if (ttile.getMasterTile() == NULL) LoaderHelper::decodeTerrain( oTilemap.at( i, j ), oCity ); } } }