#include "StdInc.h" #include "CMap.h" #include "../CArtHandler.h" #include "../VCMI_Lib.h" #include "../CTownHandler.h" #include "../CHeroHandler.h" #include "../CDefObjInfoHandler.h" #include "../CSpellHandler.h" #include "CMapEditManager.h" SHeroName::SHeroName() : heroId(-1) { } PlayerInfo::PlayerInfo(): canHumanPlay(false), canComputerPlay(false), aiTactic(EAiTactic::RANDOM), isFactionRandom(false), mainCustomHeroPortrait(-1), mainCustomHeroId(-1), hasMainTown(false), generateHeroAtMainTown(false), team(255), hasRandomHero(false), /* following are unused */ generateHero(false), p7(0), powerPlaceholders(-1) { auto allowed = VLC->townh->getDefaultAllowed(); for (size_t i=0; iterType != ETerrainType::WATER : true, from ? from->terType == ETerrainType::WATER : true); } bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const { return terType != ETerrainType::ROCK && ((allowSea && terType == ETerrainType::WATER) || (allowLand && terType != ETerrainType::WATER)); } bool TerrainTile::isClear(const TerrainTile *from /*= nullptr*/) const { return entrableTerrain(from) && !blocked; } int TerrainTile::topVisitableId() const { return visitableObjects.size() ? visitableObjects.back()->ID : -1; } bool TerrainTile::isCoastal() const { return extTileFlags & 64; } bool TerrainTile::hasFavourableWinds() const { return extTileFlags & 128; } bool TerrainTile::isWater() const { return terType == ETerrainType::WATER; } const int CMapHeader::MAP_SIZE_SMALL = 36; const int CMapHeader::MAP_SIZE_MIDDLE = 72; const int CMapHeader::MAP_SIZE_LARGE = 108; const int CMapHeader::MAP_SIZE_XLARGE = 144; CMapHeader::CMapHeader() : version(EMapFormat::SOD), height(72), width(72), twoLevel(true), difficulty(1), levelLimit(0), howManyTeams(0), areAnyPlayers(false) { allowedHeroes = VLC->heroh->getDefaultAllowed(); players.resize(PlayerColor::PLAYER_LIMIT_I); } CMapHeader::~CMapHeader() { } CMap::CMap() : checksum(0), grailPos(-1, -1, -1), grailRadious(0), terrain(nullptr) { allHeroes.resize(allowedHeroes.size()); allowedAbilities = VLC->heroh->getDefaultAllowedAbilities(); allowedArtifact = VLC->arth->getDefaultAllowed(); allowedSpell = VLC->spellh->getDefaultAllowed(); } CMap::~CMap() { if(terrain) { for(int ii=0;iipos.x + fx - 7; int yVal = obj->pos.y + fy - 5; int zVal = obj->pos.z; if(xVal>=0 && xVal=0 && yValdefInfo->visitMap[fy] >> (7 - fx)) & 1)) { curt.visitableObjects -= obj; curt.visitable = curt.visitableObjects.size(); } if(total || !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)) { curt.blockingObjects -= obj; curt.blocked = curt.blockingObjects.size(); } } } } } void CMap::addBlockVisTiles(CGObjectInstance * obj) { for(int fx=0; fx<8; ++fx) { for(int fy=0; fy<6; ++fy) { int xVal = obj->pos.x + fx - 7; int yVal = obj->pos.y + fy - 5; int zVal = obj->pos.z; if(xVal>=0 && xVal=0 && yValdefInfo->visitMap[fy] >> (7 - fx)) & 1)) { curt.visitableObjects.push_back(obj); curt.visitable = true; } if(!((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)) { curt.blockingObjects.push_back(obj); curt.blocked = true; } } } } } CGHeroInstance * CMap::getHero(int heroID) { for(auto & elem : heroesOnMap) if(elem->subID == heroID) return elem; return nullptr; } bool CMap::isInTheMap(const int3 & pos) const { if(pos.x < 0 || pos.y < 0 || pos.z < 0 || pos.x >= width || pos.y >= height || pos.z > (twoLevel ? 1 : 0)) { return false; } else { return true; } } TerrainTile & CMap::getTile(const int3 & tile) { assert(isInTheMap(tile)); return terrain[tile.x][tile.y][tile.z]; } const TerrainTile & CMap::getTile(const int3 & tile) const { assert(isInTheMap(tile)); return terrain[tile.x][tile.y][tile.z]; } bool CMap::isWaterTile(const int3 &pos) const { return isInTheMap(pos) && getTile(pos).terType == ETerrainType::WATER; } const CGObjectInstance * CMap::getObjectiveObjectFrom(int3 pos, bool lookForHero) { const std::vector & objs = getTile(pos).visitableObjects; assert(objs.size()); if(objs.size() > 1 && lookForHero && objs.front()->ID != Obj::HERO) { assert(objs.back()->ID == Obj::HERO); return objs.back(); } else return objs.front(); } void CMap::checkForObjectives() { if(isInTheMap(victoryCondition.pos)) { victoryCondition.obj = getObjectiveObjectFrom(victoryCondition.pos, victoryCondition.condition == EVictoryConditionType::BEATHERO); } if(isInTheMap(lossCondition.pos)) { lossCondition.obj = getObjectiveObjectFrom(lossCondition.pos, lossCondition.typeOfLossCon == ELossConditionType::LOSSHERO); } } void CMap::addNewArtifactInstance(CArtifactInstance * art) { art->id = ArtifactInstanceID(artInstances.size()); artInstances.push_back(art); } void CMap::eraseArtifactInstance(CArtifactInstance * art) { assert(artInstances[art->id.getNum()] == art); artInstances[art->id.getNum()].dellNull(); } void CMap::addQuest(CGObjectInstance * quest) { auto q = dynamic_cast(quest); q->quest->qid = quests.size(); quests.push_back(q->quest); } void CMap::initTerrain() { terrain = new TerrainTile**[width]; for(int i = 0; i < width; ++i) { terrain[i] = new TerrainTile*[height]; for(int j = 0; j < height; ++j) { terrain[i][j] = new TerrainTile[twoLevel ? 2 : 1]; } } } CMapEditManager * CMap::getEditManager() { if(!editManager) editManager = make_unique(this); return editManager.get(); }