/* * Copyright 2010 OpenXcom Developers. * * This file is part of OpenXcom. * * OpenXcom 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. * * OpenXcom 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 OpenXcom. If not, see . */ #include "MapDataSet.h" #include "MapData.h" #include #include #include "../Engine/Exception.h" #include "../Engine/SurfaceSet.h" #include "../Engine/CrossPlatform.h" #include "../Resource/ResourcePack.h" namespace OpenXcom { MapData *MapDataSet::_blankTile = 0; MapData *MapDataSet::_scourgedTile = 0; /** * MapDataSet construction. */ MapDataSet::MapDataSet(std::string name, int size) : _name(name), _size(size), _objects(), _surfaceSet(0), _loaded(false) { } /** * MapDataSet DESTRUCTION. */ MapDataSet::~MapDataSet() { unload(); } /** * Gets the MapDataSet name (string). * @return name. */ std::string MapDataSet::getName() const { return _name; } /** * Gets the MapDataSet size. * @return size in number of records. */ int MapDataSet::getSize() const { return _size; } /** * @return pointer to the objects */ std::vector *MapDataSet::getObjects() { return &_objects; } /** * @return pointer to the surfaceset */ SurfaceSet *MapDataSet::getSurfaceset() const { return _surfaceSet; } /** * Loads terraindata in X-Com format (MCD & PCK files) * @param res The resourcepack. * @sa http://www.ufopaedia.org/index.php?title=MCD */ void MapDataSet::load(ResourcePack *res) { // prevents loading twice if (_loaded) return; _loaded = true; int objNumber = 0; // the struct below helps to read the xcom file format struct MCD { unsigned char Frame[8]; unsigned char LOFT[12]; unsigned short ScanG; unsigned char u23; unsigned char u24; unsigned char u25; unsigned char u26; unsigned char u27; unsigned char u28; unsigned char u29; unsigned char u30; unsigned char UFO_Door; unsigned char Stop_LOS; unsigned char No_Floor; unsigned char Big_Wall; unsigned char Gravlift; unsigned char Door; unsigned char Block_Fire; unsigned char Block_Smoke; unsigned char u39; unsigned char TU_Walk; unsigned char TU_Fly; unsigned char TU_Slide; unsigned char Armor; unsigned char HE_Block; unsigned char Die_MCD; unsigned char Flammable; unsigned char Alt_MCD; unsigned char u48; signed char T_Level; unsigned char P_Level; unsigned char u51; unsigned char Light_Block; unsigned char Footstep; unsigned char Tile_Type; unsigned char HE_Type; unsigned char HE_Strength; unsigned char Smoke_Blockage; unsigned char Fuel; unsigned char Light_Source; unsigned char Target_Type; unsigned char u61; unsigned char u62; }; MCD mcd; // Load Terrain Data from MCD file std::stringstream s; s << "TERRAIN/" << _name << ".MCD"; // Load file std::ifstream mapFile (CrossPlatform::getDataFile(s.str()).c_str(), std::ios::in | std::ios::binary); if (!mapFile) { throw Exception("Failed to load MCD"); } while (mapFile.read((char*)&mcd, sizeof(MCD))) { MapData *to = new MapData(this); _objects.push_back(to); // set all the terrainobject properties: for (int frame = 0; frame < 8; frame++) { to->setSprite(frame,(int)mcd.Frame[frame]); } to->setYOffset((int)mcd.P_Level); to->setSpecialType((int)mcd.Target_Type, (int)mcd.Tile_Type); to->setTUCosts((int)mcd.TU_Walk, (int)mcd.TU_Fly, (int)mcd.TU_Slide); to->setFlags(mcd.UFO_Door == 1, mcd.Stop_LOS == 1, mcd.No_Floor == 1, mcd.Big_Wall == 1, mcd.Gravlift == 1, mcd.Door == 1, mcd.Block_Fire == 1, mcd.Block_Smoke == 1); to->setTerrainLevel((int)mcd.T_Level); to->setFootstepSound((int)mcd.Footstep); to->setAltMCD((int)(mcd.Alt_MCD)); to->setDieMCD((int)(mcd.Die_MCD)); to->setBlockValue((int)mcd.Light_Block, (int)mcd.Stop_LOS, (int)mcd.HE_Block, (int)mcd.Block_Smoke, (int)mcd.Block_Fire, (int)mcd.Block_Smoke); to->setLightSource((int)mcd.Light_Source); to->setArmor((int)mcd.Armor); to->setFlammable((int)mcd.Flammable); to->setFuel((int)mcd.Fuel); to->setExplosive((int)mcd.HE_Strength); for (int layer = 0; layer < 12; layer++) { int loft = (int)mcd.LOFT[layer]; to->setLoftID(loft, layer); } // store the 2 tiles of blanks in a static - so they are accesible everywhere if (_name.compare("BLANKS") == 0) { if (objNumber == 0) MapDataSet::_blankTile = to; else if (objNumber == 1) MapDataSet::_scourgedTile = to; } objNumber++; } if (!mapFile.eof()) { throw Exception("Invalid data from file"); } mapFile.close(); // Load terrain sprites/surfaces/PCK files into a surfaceset std::stringstream s1,s2; s1 << "TERRAIN/" << _name << ".PCK"; s2 << "TERRAIN/" << _name << ".TAB"; _surfaceSet = new SurfaceSet(32, 40); _surfaceSet->loadPck(CrossPlatform::getDataFile(s1.str()), CrossPlatform::getDataFile(s2.str())); } void MapDataSet::unload() { if (_loaded) { for (std::vector::iterator i = _objects.begin(); i != _objects.end(); ++i) { delete *i; } delete _surfaceSet; } } /** * loadLOFTEMPS loads the LOFTEMPS.DAT into the ruleset voxeldata * @param filename * @param voxelData */ void MapDataSet::loadLOFTEMPS(const std::string &filename, std::vector *voxelData) { // Load file std::ifstream mapFile (filename.c_str(), std::ios::in | std::ios::binary); if (!mapFile) { throw Exception("Failed to load DAT"); } Uint16 value; while (mapFile.read((char*)&value, sizeof(value))) { voxelData->push_back(value); } if (!mapFile.eof()) { throw Exception("Invalid data from file"); } mapFile.close(); } MapData *MapDataSet::getBlankFloorTile() { return MapDataSet::_blankTile; } MapData *MapDataSet::getScourgedEarthTile() { return MapDataSet::_scourgedTile; } }