From b20f649521943787fe483ba4549207baf52c9086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Mon, 19 Sep 2022 16:13:58 +0200 Subject: [PATCH 01/74] stash --- client/CMusicHandler.cpp | 4 +- client/mapHandler.cpp | 2 +- client/widgets/AdventureMapClasses.cpp | 2 +- lib/CGeneralTextHandler.cpp | 2 +- lib/CHeroHandler.cpp | 6 +- lib/CPathfinder.cpp | 2 +- lib/GameConstants.h | 23 +++ lib/Terrain.cpp | 197 ++++++++++++------------- lib/Terrain.h | 149 +++++++++++-------- lib/mapObjects/ObjectTemplate.cpp | 8 +- lib/rmg/CRmgTemplate.cpp | 6 +- lib/rmg/Functions.cpp | 4 +- 12 files changed, 221 insertions(+), 184 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 894b76124..4ca15ed85 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -113,7 +113,7 @@ CSoundHandler::CSoundHandler(): { horseSounds[Terrain::createTerrainTypeH3M(h3mTerrId++)] = snd; } - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { //since all sounds are hardcoded, let's keep it if(vstd::contains(horseSounds, terrain)) @@ -364,7 +364,7 @@ CMusicHandler::CMusicHandler(): addEntryToSet("enemy-turn", file.getName(), file.getName()); } - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { auto & entry = Terrain::Manager::getInfo(terrain); addEntryToSet("terrain", terrain, "Music/" + entry.musicFilename); diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 973143854..1ca0953de 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -189,7 +189,7 @@ void CMapHandler::initTerrainGraphics() }; std::map terrainFiles; - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { terrainFiles[terrain] = Terrain::Manager::getInfo(terrain).tilesFilename; } diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index eac733371..8a32353c9 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -499,7 +499,7 @@ std::map > CMinimap::loadColors() { std::map > ret; - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { auto & m = Terrain::Manager::getInfo(terrain); SDL_Color normal = diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp index aa19fdfb3..2d645fc09 100644 --- a/lib/CGeneralTextHandler.cpp +++ b/lib/CGeneralTextHandler.cpp @@ -338,7 +338,7 @@ CGeneralTextHandler::CGeneralTextHandler() { terrainNames[Terrain::createTerrainTypeH3M(i)] = h3mTerrainNames[i]; } - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { if(!Terrain::Manager::getInfo(terrain).terrainText.empty()) terrainNames[terrain] = Terrain::Manager::getInfo(terrain).terrainText; diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 890189eeb..bdf8b9137 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -344,9 +344,9 @@ CHeroHandler::~CHeroHandler() = default; CHeroHandler::CHeroHandler() { loadTerrains(); - for(int i = 0; i < Terrain::Manager::terrains().size(); ++i) + for(int i = 0; i < VLC->terrainTypeHandler::terrains().size(); ++i) { - VLC->modh->identifiers.registerObject("core", "terrain", Terrain::Manager::terrains()[i], i); + VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler::terrains()[i], i); } loadBallistics(); loadExperience(); @@ -972,7 +972,7 @@ ui64 CHeroHandler::reqExp (ui32 level) const void CHeroHandler::loadTerrains() { - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { terrCosts[terrain] = Terrain::Manager::getInfo(terrain).moveCost; } diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 6ae919db0..42ed781f7 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1008,7 +1008,7 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl) { - for(int i = 0; i < Terrain::Manager::terrains().size(); ++i) + for(int i = 0; i < VLC->terrainTypeHandler::terrains().size(); ++i) { noTerrainPenalty.push_back(static_cast( bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(i))))); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index d86c760ce..4bf3c986f 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -832,6 +832,28 @@ public: ID_LIKE_OPERATORS(Obj, Obj::EObj) +namespace Terrain +{ + enum ETerrain : TTerrain + { + ANY_TERRAIN = -3, + WRONG = -2, + BORDER = -1, + FIRST_REGULAR_TERRAIN = 0, + DIRT = 0, + SAND, + GRASS, + SNOW, + SWAMP, + ROUGH, + SUBTERRANEAN, + LAVA, + WATER, + ROCK, + ORIGINAL_TERRAIN_COUNT + }; +} + namespace SecSkillLevel { enum SecSkillLevel @@ -1183,6 +1205,7 @@ typedef si64 TExpType; typedef std::pair TDmgRange; typedef si32 TBonusSubtype; typedef si32 TQuantity; +typedef ui8 TTerrain; typedef int TRmgTemplateZoneId; diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 142355961..035b859ee 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -17,31 +17,15 @@ //("allowedTerrain"\s*:\s*\[.*)9(.*\],\n) //\1"rock"\2 -const Terrain Terrain::ANY("ANY"); - -Terrain Terrain::createTerrainTypeH3M(int tId) -{ - static std::array terrainsH3M - { - "dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock" - }; - return Terrain(terrainsH3M.at(tId)); -} - -Terrain Terrain::createTerrainByCode(const std::string & typeCode) -{ - for(const auto & terrain : Manager::terrains()) - { - if(Manager::getInfo(terrain).typeCode == typeCode) - return terrain; - } - return Terrain::ANY; -} - -Terrain::Manager::Manager() +TerrainTypeHandler::TerrainTypeHandler() { auto allConfigs = VLC->modh->getActiveMods(); allConfigs.insert(allConfigs.begin(), "core"); + + std::vector> resolveLater; + + objects.resize(Terrain::ORIGINAL_TERRAIN_COUNT, nullptr); //make space for original terrains + for(auto & mod : allConfigs) { if(!CResourceHandler::get(mod)->existsResource(ResourceID("config/terrains.json"))) @@ -50,10 +34,11 @@ Terrain::Manager::Manager() JsonNode terrs(mod, ResourceID("config/terrains.json")); for(auto & terr : terrs.Struct()) { - Terrain::Info info; - info.moveCost = terr.second["moveCost"].Integer(); + auto * info = new TerrainType(terr.first); + + info->moveCost = terr.second["moveCost"].Integer(); const JsonVector &unblockedVec = terr.second["minimapUnblocked"].Vector(); - info.minimapUnblocked = + info->minimapUnblocked = { ui8(unblockedVec[0].Float()), ui8(unblockedVec[1].Float()), @@ -61,75 +46,75 @@ Terrain::Manager::Manager() }; const JsonVector &blockedVec = terr.second["minimapBlocked"].Vector(); - info.minimapBlocked = + info->minimapBlocked = { ui8(blockedVec[0].Float()), ui8(blockedVec[1].Float()), ui8(blockedVec[2].Float()) }; - info.musicFilename = terr.second["music"].String(); - info.tilesFilename = terr.second["tiles"].String(); + info->musicFilename = terr.second["music"].String(); + info->tilesFilename = terr.second["tiles"].String(); if(terr.second["type"].isNull()) { - info.type = Terrain::Info::Type::Land; + info->passabilityType = TerrainType::PassabilityType::LAND; } else { auto s = terr.second["type"].String(); - if(s == "LAND") info.type = Terrain::Info::Type::Land; - if(s == "WATER") info.type = Terrain::Info::Type::Water; - if(s == "ROCK") info.type = Terrain::Info::Type::Rock; - if(s == "SUB") info.type = Terrain::Info::Type::Subterranean; + if(s == "LAND") info->passabilityType = TerrainType::PassabilityType::LAND; + if(s == "WATER") info->passabilityType = TerrainType::PassabilityType::WATER; + if(s == "ROCK") info->passabilityType = TerrainType::PassabilityType::ROCK; + if(s == "SUB") info->passabilityType = TerrainType::PassabilityType::SUBTERRANEAN; } if(terr.second["rockTerrain"].isNull()) { - info.rockTerrain = "rock"; + info->rockTerrain = "rock"; } else { - info.rockTerrain = terr.second["rockTerrain"].String(); + info->rockTerrain = terr.second["rockTerrain"].String(); } if(terr.second["river"].isNull()) { - info.river = RIVER_NAMES[0]; + info->river = RIVER_NAMES[0]; } else { - info.river = terr.second["river"].String(); + info->river = terr.second["river"].String(); } if(terr.second["horseSoundId"].isNull()) { - info.horseSoundId = 9; //rock sound as default + info->horseSoundId = 9; //rock sound as default } else { - info.horseSoundId = terr.second["horseSoundId"].Integer(); + info->horseSoundId = terr.second["horseSoundId"].Integer(); } if(!terr.second["text"].isNull()) { - info.terrainText = terr.second["text"].String(); + info->terrainText = terr.second["text"].String(); } if(terr.second["code"].isNull()) { - info.typeCode = terr.first.substr(0, 2); + info->typeCode = terr.first.substr(0, 2); } else { - info.typeCode = terr.second["code"].String(); - assert(info.typeCode.length() == 2); + info->typeCode = terr.second["code"].String(); + assert(info->typeCode.length() == 2); } if(!terr.second["battleFields"].isNull()) { for(auto & t : terr.second["battleFields"].Vector()) { - info.battleFields.emplace_back(t.String()); + info->battleFields.emplace_back(t.String()); } } @@ -137,123 +122,133 @@ Terrain::Manager::Manager() { for(auto & t : terr.second["prohibitTransitions"].Vector()) { - info.prohibitTransitions.emplace_back(t.String()); + info->prohibitTransitions.emplace_back(t.String()); } } - info.transitionRequired = false; + info->transitionRequired = false; if(!terr.second["transitionRequired"].isNull()) { - info.transitionRequired = terr.second["transitionRequired"].Bool(); + info->transitionRequired = terr.second["transitionRequired"].Bool(); } - info.terrainViewPatterns = "normal"; + info->terrainViewPatterns = "normal"; if(!terr.second["terrainViewPatterns"].isNull()) { - info.terrainViewPatterns = terr.second["terrainViewPatterns"].String(); + info->terrainViewPatterns = terr.second["terrainViewPatterns"].String(); } + + //TODO: handle 10 origina terrains - terrainInfo[terr.first] = info; - if(!terrainId.count(terr.first)) + terrainInfoByName[terr.first] = info; + terrainInfoByCode[info->typeCode] = info; + terrainInfoById[info->id] = info; + + TTerrain id; + if(!terr.second["originalTerrainId"].isNull()) { - terrainId[terr.first] = terrainVault.size(); - terrainVault.push_back(terr.first); + //place in reserved slot + id = (TTerrain)(terr.second["originalTerrainId"].Float()); + objects[id] = info; + } + else + { + //append at the end + id = objects.size(); + objects.push_back(info); } } } + + for (size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++) + { + //Make sure that original terrains are loaded + assert(objects(i)); + } + + //TODO: add ids to resolve + for (auto& functor : resolveLater) + { + functor(); + } } -Terrain::Manager & Terrain::Manager::get() +const std::vector & TerrainTypeHandler::terrains() { - static Terrain::Manager manager; - return manager; + return objects; } -const std::vector & Terrain::Manager::terrains() +const TerrainType* TerrainTypeHandler::getInfoByName(const std::string& terrainName) const { - return Terrain::Manager::get().terrainVault; + } -int Terrain::Manager::id(const Terrain & terrain) +const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainName) const { - if(terrain.name == "ANY") return -3; - if(terrain.name == "WRONG") return -2; - if(terrain.name == "BORDER") return -1; - - return Terrain::Manager::get().terrainId.at(terrain); + } -const Terrain::Info & Terrain::Manager::getInfo(const Terrain & terrain) +const TerrainType* TerrainTypeHandler::getInfoById(TTerrain id) const { - return Terrain::Manager::get().terrainInfo.at(static_cast(terrain)); + } -std::ostream & operator<<(std::ostream & os, const Terrain terrainType) +std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType) { return os << static_cast(terrainType); } -Terrain::operator std::string() const +TerrainType::operator std::string() const { return name; } -Terrain::Terrain(const std::string & _name) : name(_name) +TerrainType::TerrainType(const std::string & _name) : name(_name) {} -Terrain& Terrain::operator=(const Terrain & _name) +TerrainType& TerrainType::operator=(const TerrainType & other) { - name = _name.name; + //TODO + name = other.name; return *this; } -Terrain& Terrain::operator=(const std::string & _name) +bool TerrainType::operator==(const TerrainType& other) { - name = _name; - return *this; + return id == other.id; } -bool operator==(const Terrain & l, const Terrain & r) +bool TerrainType::operator!=(const TerrainType& other) { - return l.name == r.name; + return id != other.id; } -bool operator!=(const Terrain & l, const Terrain & r) +bool TerrainType::operator<(const TerrainType& other) { - return l.name != r.name; + return id < other.id; } -bool operator<(const Terrain & l, const Terrain & r) -{ - return l.name < r.name; -} - -int Terrain::id() const -{ - return Terrain::Manager::id(*this); -} - -bool Terrain::isLand() const +bool TerrainType::isLand() const { return !isWater(); } -bool Terrain::isWater() const + +bool TerrainType::isWater() const { - return Terrain::Manager::getInfo(*this).type == Terrain::Info::Type::Water; + return passabilityType == PassabilityType::WATER; } -bool Terrain::isPassable() const + +bool TerrainType::isPassable() const { - return Terrain::Manager::getInfo(*this).type != Terrain::Info::Type::Rock; + return passabilityType != PassabilityType::ROCK; } -bool Terrain::isUnderground() const + +bool TerrainType::isUnderground() const { - return Terrain::Manager::getInfo(*this).type == Terrain::Info::Type::Subterranean; + return passabilityType != PassabilityType::SUBTERRANEAN; } -bool Terrain::isNative() const + +bool TerrainType::isTransitionRequired() const { - return name.empty(); -} -bool Terrain::isTransitionRequired() const -{ - return Terrain::Manager::getInfo(*this).transitionRequired; + return transitionRequired; } diff --git a/lib/Terrain.h b/lib/Terrain.h index d270090e5..3f2844823 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -15,92 +15,111 @@ #include "JsonNode.h" -class DLL_LINKAGE Terrain +class DLL_LINKAGE TerrainType { public: - friend class Manager; - - struct Info + enum class PassabilityType { - enum class Type - { - Land, Water, Subterranean, Rock - }; - - int moveCost; - bool transitionRequired; - std::array minimapBlocked; - std::array minimapUnblocked; - std::string musicFilename; - std::string tilesFilename; - std::string terrainText; - std::string typeCode; - std::string terrainViewPatterns; - std::string rockTerrain; - std::string river; - int horseSoundId; - Type type; - std::vector battleFields; - std::vector prohibitTransitions; + LAND, + WATER, + SUBTERRANEAN, + ROCK }; - class DLL_LINKAGE Manager - { - public: - static const std::vector & terrains(); - static const Info & getInfo(const Terrain &); - static int id(const Terrain &); - - private: - static Manager & get(); - Manager(); - - std::unordered_map terrainInfo; - std::vector terrainVault; - std::map terrainId; - }; + std::vector battleFields; + std::vector prohibitTransitions; + std::array minimapBlocked; + std::array minimapUnblocked; + std::string name; + std::string musicFilename; + std::string tilesFilename; + std::string terrainText; + std::string typeCode; + std::string terrainViewPatterns; + std::string rockTerrain; + std::string river; + + TTerrain id; + int moveCost; + int horseSoundId; + PassabilityType passabilityType; + bool transitionRequired; - /*enum EETerrainType - { - ANY_TERRAIN = -3, - WRONG = -2, BORDER = -1, DIRT, SAND, GRASS, SNOW, SWAMP, - ROUGH, SUBTERRANEAN, LAVA, WATER, ROCK // ROCK is also intended to be max value. - };*/ + TerrainType(const std::string & _type = ""); - Terrain(const std::string & _type = ""); - static Terrain createTerrainTypeH3M(int tId); - static Terrain createTerrainByCode(const std::string & typeCode); + TerrainType& operator=(const TerrainType & _type); - int id() const; //TODO: has to be completely removed - - Terrain& operator=(const Terrain & _type); - Terrain& operator=(const std::string & _type); - - DLL_LINKAGE friend bool operator==(const Terrain & l, const Terrain & r); - DLL_LINKAGE friend bool operator!=(const Terrain & l, const Terrain & r); - DLL_LINKAGE friend bool operator<(const Terrain & l, const Terrain & r); - - static const Terrain ANY; + bool operator==(const TerrainType & other); + bool operator!=(const TerrainType & other); + bool operator<(const TerrainType & other); bool isLand() const; bool isWater() const; bool isPassable() const; //ROCK bool isUnderground() const; - bool isNative() const; bool isTransitionRequired() const; - operator std::string() const; template void serialize(Handler &h, const int version) { + h & battleFields; + h & prohibitTransitions; + h & minimapBlocked; + h & minimapUnblocked; h & name; + h & musicFilename; + h & tilesFilename; + h & terrainText; + h & typeCode; + h & terrainViewPatterns; + h & rockTerrain; + h & river; + + h & id; + h & moveCost; + h & horseSoundId; + h & passabilityType; + h & transitionRequired; } - -protected: - - std::string name; }; -DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const Terrain terrainType); +DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType); + +class DLL_LINKAGE TerrainTypeHandler //TODO: handlerBase +{ +public: + + TerrainTypeHandler(); + + const std::vector & terrains(); + const TerrainType * getInfoByName(const std::string & terrainName) const; + const TerrainType * getInfoByCode(const std::string & terrainName) const; + const TerrainType * getInfoById(TTerrain id) const; + + //TODO: road, river types? + +private: + + std::vector objects; + + std::unordered_map terrainInfoByName; + std::unordered_map terrainInfoByCode; + std::unordered_map terrainInfoById; + + template void serialize(Handler &h, const int version) + { + h & name; + + if (!saving) + { + //TODO: recreate at load + } + /* + h & terrainInfoByName; + h & terrainInfoByCode; + h & terrainInfoById; + */ + } +}; diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 40f9693df..16a126483 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -165,7 +165,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) //assuming that object can be placed on other land terrains if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water"))) { - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { if(terrain.isLand() && terrain.isPassable()) allowedTerrains.insert(terrain); @@ -238,7 +238,7 @@ void ObjectTemplate::readMap(CBinaryReader & reader) //assuming that object can be placed on other land terrains if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water"))) { - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) { if(terrain.isLand() && terrain.isPassable()) allowedTerrains.insert(terrain); @@ -289,7 +289,7 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) } else { - for(auto & i : Terrain::Manager::terrains()) + for(auto & i : VLC->terrainTypeHandler::terrains()) { if(!i.isPassable() || i.isWater()) continue; @@ -369,7 +369,7 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const if(withTerrain) { //assumed that ROCK and WATER terrains are not included - if(allowedTerrains.size() < (Terrain::Manager::terrains().size() - 2)) + if(allowedTerrains.size() < (VLC->terrainTypeHandler::terrains().size() - 2)) { JsonVector & data = node["allowedTerrains"].Vector(); diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index 1025ff874..57077aca6 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -67,12 +67,12 @@ class TerrainEncoder public: static si32 decode(const std::string & identifier) { - return vstd::find_pos(Terrain::Manager::terrains(), identifier); + return vstd::find_pos(VLC->terrainTypeHandler::terrains(), identifier); } static std::string encode(const si32 index) { - return (index >=0 && index < Terrain::Manager::terrains().size()) ? static_cast(Terrain::Manager::terrains()[index]) : ""; + return (index >=0 && index < VLC->terrainTypeHandler::terrains().size()) ? static_cast(VLC->terrainTypeHandler::terrains()[index]) : ""; } }; @@ -149,7 +149,7 @@ ZoneOptions::ZoneOptions() terrainTypeLikeZone(NO_ZONE), treasureLikeZone(NO_ZONE) { - for(auto & terr : Terrain::Manager::terrains()) + for(auto & terr : VLC->terrainTypeHandler::terrains()) if(terr.isLand() && terr.isPassable()) terrainTypes.insert(terr); } diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 210bf9fe2..21dccf349 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -117,7 +117,7 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) { //collect all water terrain types std::vector waterTerrains; - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) if(terrain.isWater()) waterTerrains.push_back(terrain); @@ -142,7 +142,7 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) { //collect all underground terrain types std::vector undegroundTerrains; - for(auto & terrain : Terrain::Manager::terrains()) + for(auto & terrain : VLC->terrainTypeHandler::terrains()) if(terrain.isUnderground()) undegroundTerrains.push_back(terrain); From 494b0f02268d0cd7734865741ea5faf8578468d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 11:34:23 +0200 Subject: [PATCH 02/74] First version that compiles --- AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 4 +- AI/VCAI/Pathfinding/AINodeStorage.cpp | 4 +- client/CGameInfo.cpp | 1 + client/CGameInfo.h | 2 + client/CMusicHandler.cpp | 35 +++++++------ client/CMusicHandler.h | 2 +- client/CPlayerInterface.cpp | 8 +-- client/battle/CBattleInterface.cpp | 4 +- client/mapHandler.cpp | 14 +++-- client/widgets/AdventureMapClasses.cpp | 26 ++++----- client/widgets/AdventureMapClasses.h | 4 +- client/windows/CAdvmapInterface.cpp | 2 +- config/terrains.json | 10 ++++ lib/CCreatureHandler.cpp | 16 +++--- lib/CCreatureHandler.h | 4 +- lib/CGameInfoCallback.cpp | 2 +- lib/CGameState.cpp | 8 +-- lib/CGeneralTextHandler.cpp | 8 +-- lib/CGeneralTextHandler.h | 2 +- lib/CHeroHandler.cpp | 8 +-- lib/CHeroHandler.h | 2 +- lib/CPathfinder.cpp | 22 ++++---- lib/CPathfinder.h | 2 +- lib/CStack.cpp | 4 +- lib/CStack.h | 4 +- lib/CTownHandler.cpp | 12 ++--- lib/CTownHandler.h | 10 ++-- lib/GameConstants.h | 5 +- lib/HeroBonus.cpp | 22 +++++--- lib/HeroBonus.h | 4 +- lib/IGameCallback.cpp | 6 +-- lib/NetPacksLib.cpp | 8 +-- lib/ObstacleHandler.cpp | 4 +- lib/ObstacleHandler.h | 4 +- lib/PathfinderUtil.h | 4 +- lib/Terrain.cpp | 58 ++++++++++++++------- lib/Terrain.h | 36 ++++++------- lib/VCMI_Lib.cpp | 2 + lib/VCMI_Lib.h | 3 ++ lib/battle/BattleInfo.cpp | 4 +- lib/battle/BattleInfo.h | 7 ++- lib/battle/BattleProxy.cpp | 2 +- lib/battle/BattleProxy.h | 2 +- lib/battle/CBattleInfoEssentials.cpp | 4 +- lib/battle/CBattleInfoEssentials.h | 2 +- lib/battle/IBattleInfoCallback.h | 4 +- lib/battle/IBattleState.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 23 ++++---- lib/mapObjects/CGHeroInstance.h | 2 +- lib/mapObjects/CGTownInstance.cpp | 3 +- lib/mapObjects/CObjectClassesHandler.cpp | 4 +- lib/mapObjects/CObjectClassesHandler.h | 4 +- lib/mapObjects/CObjectHandler.cpp | 6 +-- lib/mapObjects/CommonConstructors.cpp | 2 +- lib/mapObjects/ObjectTemplate.cpp | 40 +++++++------- lib/mapObjects/ObjectTemplate.h | 5 +- lib/mapping/CMap.cpp | 21 +++++--- lib/mapping/CMapDefines.h | 2 +- lib/mapping/CMapEditManager.cpp | 2 +- lib/mapping/CMapEditManager.h | 2 +- lib/mapping/CMapOperation.cpp | 43 ++++++++------- lib/mapping/CMapOperation.h | 4 +- lib/mapping/MapEditUtils.cpp | 8 +-- lib/mapping/MapEditUtils.h | 4 +- lib/mapping/MapFormatH3M.cpp | 5 +- lib/mapping/MapFormatJson.cpp | 4 +- lib/rmg/CMapGenerator.cpp | 4 +- lib/rmg/CMapGenerator.h | 4 +- lib/rmg/CRmgTemplate.cpp | 17 +++--- lib/rmg/CRmgTemplate.h | 6 +-- lib/rmg/CZonePlacer.cpp | 6 +-- lib/rmg/ConnectionsPlacer.cpp | 5 +- lib/rmg/Functions.cpp | 29 ++++++----- lib/rmg/Functions.h | 4 +- lib/rmg/RiverPlacer.cpp | 6 +-- lib/rmg/RmgMap.cpp | 2 +- lib/rmg/RmgObject.cpp | 19 ++++--- lib/rmg/RmgObject.h | 5 +- lib/rmg/RockPlacer.cpp | 8 +-- lib/rmg/RockPlacer.h | 2 +- lib/rmg/TileInfo.cpp | 6 +-- lib/rmg/TileInfo.h | 6 +-- lib/rmg/TreasurePlacer.cpp | 2 +- lib/rmg/TreasurePlacer.h | 2 +- lib/rmg/WaterProxy.cpp | 2 +- lib/rmg/Zone.cpp | 6 +-- lib/rmg/Zone.h | 6 +-- scripting/lua/api/BattleCb.cpp | 2 +- server/CGameHandler.cpp | 14 ++--- test/game/CGameStateTest.cpp | 2 +- test/map/CMapEditManagerTest.cpp | 34 ++++++------ test/mock/mock_IBattleInfoCallback.h | 2 +- test/mock/mock_battle_IBattleState.h | 2 +- 93 files changed, 431 insertions(+), 359 deletions(-) diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index a5e302557..05865e0b4 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -89,10 +89,10 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta for(pos.y = 0; pos.y < sizes.y; ++pos.y) { const TerrainTile* tile = &gs->map->getTile(pos); - if (!tile->terType.isPassable()) + if (!tile->terType->isPassable()) continue; - if (tile->terType.isWater()) + if (tile->terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if (useFlying) diff --git a/AI/VCAI/Pathfinding/AINodeStorage.cpp b/AI/VCAI/Pathfinding/AINodeStorage.cpp index ed43721be..1a0e08316 100644 --- a/AI/VCAI/Pathfinding/AINodeStorage.cpp +++ b/AI/VCAI/Pathfinding/AINodeStorage.cpp @@ -44,10 +44,10 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta for(pos.y=0; pos.y < sizes.y; ++pos.y) { const TerrainTile * tile = &gs->map->getTile(pos); - if(!tile->terType.isPassable()) + if(!tile->terType->isPassable()) continue; - if(tile->terType.isWater()) + if(tile->terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) diff --git a/client/CGameInfo.cpp b/client/CGameInfo.cpp index d8c58296a..95687c828 100644 --- a/client/CGameInfo.cpp +++ b/client/CGameInfo.cpp @@ -37,6 +37,7 @@ void CGameInfo::setFromLib() spellh = VLC->spellh; skillh = VLC->skillh; objtypeh = VLC->objtypeh; + terrainTypeHandler = VLC->terrainTypeHandler; battleFieldHandler = VLC->battlefieldsHandler; obstacleHandler = VLC->obstacleHandler; } diff --git a/client/CGameInfo.h b/client/CGameInfo.h index 70b56905c..6e2570f2d 100644 --- a/client/CGameInfo.h +++ b/client/CGameInfo.h @@ -33,6 +33,7 @@ class IMainVideoPlayer; class CServerHandler; class BattleFieldHandler; class ObstacleHandler; +class TerrainTypeHandler; class CMap; @@ -78,6 +79,7 @@ public: ConstTransitivePtr spellh; ConstTransitivePtr skillh; ConstTransitivePtr objh; + ConstTransitivePtr terrainTypeHandler; ConstTransitivePtr objtypeh; ConstTransitivePtr obstacleHandler; CGeneralTextHandler * generaltexth; diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 4ca15ed85..955318be7 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -102,24 +102,28 @@ CSoundHandler::CSoundHandler(): //predefine terrain set //TODO: need refactoring - support custom sounds for new terrains and load from json - int h3mTerrId = 0; - for(auto snd : + horseSounds = { - soundBase::horseDirt, soundBase::horseSand, soundBase::horseGrass, - soundBase::horseSnow, soundBase::horseSwamp, soundBase::horseRough, - soundBase::horseSubterranean, soundBase::horseLava, - soundBase::horseWater, soundBase::horseRock - }) - { - horseSounds[Terrain::createTerrainTypeH3M(h3mTerrId++)] = snd; - } - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + {Terrain::DIRT, soundBase::horseDirt}, + {Terrain::SAND, soundBase::horseSand}, + {Terrain::GRASS, soundBase::horseGrass}, + {Terrain::SNOW, soundBase::horseSnow}, + {Terrain::SWAMP, soundBase::horseSwamp}, + {Terrain::ROUGH, soundBase::horseRough}, + {Terrain::SUBTERRANEAN, soundBase::horseSubterranean}, + {Terrain::LAVA, soundBase::horseLava}, + {Terrain::WATER, soundBase::horseWater}, + {Terrain::ROCK, soundBase::horseRock} + }; + auto terrains = CGI->terrainTypeHandler->terrains(); + for(const auto * terrain : terrains) { //since all sounds are hardcoded, let's keep it - if(vstd::contains(horseSounds, terrain)) + if(vstd::contains(horseSounds, terrain->id)) continue; - horseSounds[terrain] = horseSounds.at(Terrain::createTerrainTypeH3M(Terrain::Manager::getInfo(terrain).horseSoundId)); + //Use already existing horse sound + horseSounds[terrain->id] = horseSounds.at(terrains[terrain->id]->horseSoundId); } }; @@ -364,10 +368,9 @@ CMusicHandler::CMusicHandler(): addEntryToSet("enemy-turn", file.getName(), file.getName()); } - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : CGI->terrainTypeHandler->terrains()) { - auto & entry = Terrain::Manager::getInfo(terrain); - addEntryToSet("terrain", terrain, "Music/" + entry.musicFilename); + addEntryToSet("terrain", terrain->name, "Music/" + terrain->musicFilename); } } diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index ddcca0d17..03255f01a 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -83,7 +83,7 @@ public: // Sets std::vector pickupSounds; std::vector battleIntroSounds; - std::map horseSounds; + std::map horseSounds; }; // Helper //now it looks somewhat useless diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 62463f048..5c8555e17 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -274,7 +274,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose) { updateAmbientSounds(); //We may need to change music - select new track, music handler will change it if needed - CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType, true); + CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true); if(details.result == TryMoveHero::TELEPORTATION) { @@ -2742,8 +2742,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path) { path.convert(0); - Terrain currentTerrain = Terrain("BORDER"); // not init yet - Terrain newTerrain; + TTerrain currentTerrain = Terrain::BORDER; // not init yet + TTerrain newTerrain; int sh = -1; auto canStop = [&](CGPathNode * node) -> bool @@ -2798,7 +2798,7 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path) sh = CCS->soundh->playSound(soundBase::horseFlying, -1); #endif { - newTerrain = cb->getTile(CGHeroInstance::convertPosition(currentCoord, false))->terType; + newTerrain = cb->getTile(CGHeroInstance::convertPosition(currentCoord, false))->terType->id; if(newTerrain != currentTerrain) { CCS->soundh->stopSound(sh); diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 50d41a8c3..7cdf0cc0a 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -456,8 +456,8 @@ CBattleInterface::~CBattleInterface() if (adventureInt && adventureInt->selection) { - auto & terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType; - CCS->musich->playMusicFromSet("terrain", terrain, true); + const auto * terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType; + CCS->musich->playMusicFromSet("terrain", terrain->name, true); } animsAreDisplayed.setn(false); } diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 1ca0953de..fd84d274f 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -188,10 +188,11 @@ void CMapHandler::initTerrainGraphics() } }; + //TODO: use if as a key std::map terrainFiles; - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - terrainFiles[terrain] = Terrain::Manager::getInfo(terrain).tilesFilename; + terrainFiles[terrain->name] = terrain->tilesFilename; } loadFlipped(terrainAnimations, terrainImages, terrainFiles); @@ -609,10 +610,13 @@ void CMapHandler::CMapBlitter::drawTileTerrain(SDL_Surface * targetSurf, const T ui8 rotation = tinfo.extTileFlags % 4; - if(parent->terrainImages[tinfo.terType].size()<=tinfo.terView) + //TODO: use ui8 instead of string key + auto terrainName = tinfo.terType->name; + + if(parent->terrainImages[terrainName].size()<=tinfo.terView) return; - drawElement(EMapCacheType::TERRAIN, parent->terrainImages[tinfo.terType][tinfo.terView][rotation], nullptr, targetSurf, &destRect); + drawElement(EMapCacheType::TERRAIN, parent->terrainImages[terrainName][tinfo.terView][rotation], nullptr, targetSurf, &destRect); } void CMapHandler::CMapWorldViewBlitter::init(const MapDrawingInfo * drawingInfo) @@ -1390,7 +1394,7 @@ void CMapHandler::getTerrainDescr(const int3 & pos, std::string & out, bool isRM } } if(!isTile2Terrain || out.empty()) - out = CGI->generaltexth->terrainNames[t.terType]; + out = CGI->generaltexth->terrainNames[t.terType->id]; if(t.getDiggingStatus(false) == EDiggingStatus::CAN_DIG) { diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 8a32353c9..55766a41c 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -391,10 +391,11 @@ const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos) } // else - use terrain color (blocked version or normal) + auto colorPair = parent->colors.find(tile->terType->id)->second; if (tile->blocked && (!tile->visitable)) - return parent->colors.find(tile->terType)->second.second; + return colorPair.second; else - return parent->colors.find(tile->terType)->second.first; + return colorPair.first; } void CMinimapInstance::tileToPixels (const int3 &tile, int &x, int &y, int toX, int toY) { @@ -495,30 +496,29 @@ void CMinimapInstance::showAll(SDL_Surface * to) } } -std::map > CMinimap::loadColors() +std::map > CMinimap::loadColors() { - std::map > ret; + std::map > ret; - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - auto & m = Terrain::Manager::getInfo(terrain); SDL_Color normal = { - ui8(m.minimapUnblocked[0]), - ui8(m.minimapUnblocked[1]), - ui8(m.minimapUnblocked[2]), + ui8(terrain->minimapUnblocked[0]), + ui8(terrain->minimapUnblocked[1]), + ui8(terrain->minimapUnblocked[2]), ui8(255) }; SDL_Color blocked = { - ui8(m.minimapBlocked[0]), - ui8(m.minimapBlocked[1]), - ui8(m.minimapBlocked[2]), + ui8(terrain->minimapBlocked[0]), + ui8(terrain->minimapBlocked[1]), + ui8(terrain->minimapBlocked[2]), ui8(255) }; - ret[terrain] = std::make_pair(normal, blocked); + ret[terrain->id] = std::make_pair(normal, blocked); } return ret; } diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index de9b98c8b..75540c81a 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -217,7 +217,7 @@ protected: int level; //to initialize colors - std::map > loadColors(); + std::map > loadColors(); void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; @@ -228,7 +228,7 @@ protected: public: // terrainID -> (normal color, blocked color) - const std::map > colors; + const std::map > colors; CMinimap(const Rect & position); diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index a060780b2..bbeba9cb2 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -1413,7 +1413,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView) auto pos = sel->visitablePos(); auto tile = LOCPLINT->cb->getTile(pos); if(tile) - CCS->musich->playMusicFromSet("terrain", tile->terType, true); + CCS->musich->playMusicFromSet("terrain", tile->terType->name, true); } if(centerView) centerOn(sel); diff --git a/config/terrains.json b/config/terrains.json index 45a40c974..7699146b0 100644 --- a/config/terrains.json +++ b/config/terrains.json @@ -1,6 +1,7 @@ { "dirt" : { + "originalTerrainId": 0, "moveCost" : 100, "minimapUnblocked" : [ 82, 56, 8 ], "minimapBlocked" : [ 57, 40, 8 ], @@ -14,6 +15,7 @@ }, "sand" : { + "originalTerrainId": 1, "moveCost" : 150, "minimapUnblocked" : [ 222, 207, 140 ], "minimapBlocked" : [ 165, 158, 107 ], @@ -28,6 +30,7 @@ }, "grass" : { + "originalTerrainId": 2, "moveCost" : 100, "minimapUnblocked" : [ 0, 65, 0 ], "minimapBlocked" : [ 0, 48, 0 ], @@ -40,6 +43,7 @@ }, "snow" : { + "originalTerrainId": 3, "moveCost" : 150, "minimapUnblocked" : [ 181, 199, 198 ], "minimapBlocked" : [ 140, 158, 156 ], @@ -52,6 +56,7 @@ }, "swamp" : { + "originalTerrainId": 4, "moveCost" : 175, "minimapUnblocked" : [ 74, 134, 107 ], "minimapBlocked" : [ 33, 89, 66 ], @@ -64,6 +69,7 @@ }, "rough" : { + "originalTerrainId": 5, "moveCost" : 125, "minimapUnblocked" : [ 132, 113, 49 ], "minimapBlocked" : [ 99, 81, 33 ], @@ -76,6 +82,7 @@ }, "subterra" : { + "originalTerrainId": 6, "moveCost" : 100, "minimapUnblocked" : [ 132, 48, 0 ], "minimapBlocked" : [ 90, 8, 0 ], @@ -90,6 +97,7 @@ }, "lava" : { + "originalTerrainId": 7, "moveCost" : 100, "minimapUnblocked" : [ 74, 73, 74 ], "minimapBlocked" : [ 41, 40, 41 ], @@ -103,6 +111,7 @@ }, "water" : { + "originalTerrainId": 8, "moveCost" : 100, "minimapUnblocked" : [ 8, 81, 148 ], "minimapBlocked" : [ 8, 81, 148 ], @@ -120,6 +129,7 @@ }, "rock" : { + "originalTerrainId": 9, "moveCost" : -1, "minimapUnblocked" : [ 0, 0, 0 ], "minimapBlocked" : [ 0, 0, 0 ], diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 709b40242..3aeb8706d 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -283,22 +283,22 @@ std::string CCreature::nodeName() const return "\"" + namePl + "\""; } -bool CCreature::isItNativeTerrain(const Terrain & terrain) const +bool CCreature::isItNativeTerrain(TTerrain terrain) const { auto native = getNativeTerrain(); - return native == terrain || native == Terrain::ANY; + return native == terrain || native == Terrain::ANY_TERRAIN; } -Terrain CCreature::getNativeTerrain() const +TTerrain CCreature::getNativeTerrain() const { - const std::string cachingStringBlocksRetaliation = "type_NO_TERRAIN_PENALTY"; - static const auto selectorBlocksRetaliation = Selector::type()(Bonus::NO_TERRAIN_PENALTY); + const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY"; + static const auto selectorNoTerrainPenalty = Selector::type()(Bonus::NO_TERRAIN_PENALTY); //this code is used in the CreatureTerrainLimiter::limit to setup battle bonuses //and in the CGHeroInstance::getNativeTerrain() to setup mevement bonuses or/and penalties. - return hasBonus(selectorBlocksRetaliation, selectorBlocksRetaliation) - ? Terrain::ANY - : (Terrain)(*VLC->townh)[faction]->nativeTerrain; + return hasBonus(selectorNoTerrainPenalty, selectorNoTerrainPenalty) + ? Terrain::ANY_TERRAIN + : (*VLC->townh)[faction]->nativeTerrain; } void CCreature::updateFrom(const JsonNode & data) diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 66f652a59..d64803fb9 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -119,14 +119,14 @@ public: ArtifactID warMachine; - bool isItNativeTerrain(const Terrain & terrain) const; + bool isItNativeTerrain(TTerrain terrain) const; /** Returns creature native terrain considering some terrain bonuses. @param considerBonus is used to avoid Dead Lock when this method is called inside getAllBonuses considerBonus = true is called from Pathfinder and fills actual nativeTerrain considering bonus(es). considerBonus = false is called on Battle init and returns already prepared nativeTerrain without Bonus system calling. */ - Terrain getNativeTerrain() const; + TTerrain getNativeTerrain() const; int32_t getIndex() const override; int32_t getIconIndex() const override; const std::string & getName() const override; diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 0d0a8d6b0..09e029aac 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -575,7 +575,7 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow { const TerrainTile *tile = getTile(t->bestLocation(), false); - if(!tile || tile->terType.isLand()) + if(!tile || tile->terType->isLand()) return EBuildingState::NO_WATER; //lack of water } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index c81a760c6..40c3dc169 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -964,8 +964,8 @@ void CGameState::initGrailPosition() const TerrainTile &t = map->getTile(int3(x, y, z)); if(!t.blocked && !t.visitable - && t.terType.isLand() - && t.terType.isPassable() + && t.terType->isLand() + && t.terType->isPassable() && (int)map->grailPos.dist2dSQ(int3(x, y, z)) <= (map->grailRadius * map->grailRadius)) allowedPos.push_back(int3(x,y,z)); } @@ -1919,7 +1919,7 @@ BattleField CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r return BattleField::fromString("sand_shore"); return BattleField::fromString( - *RandomGeneratorUtil::nextItem(Terrain::Manager::getInfo(t.terType).battleFields, rand)); + *RandomGeneratorUtil::nextItem(t.terType->battleFields, rand)); } UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack) @@ -2101,7 +2101,7 @@ void CGameState::updateRumor() rumorId = *RandomGeneratorUtil::nextItem(sRumorTypes, rand); if(rumorId == RumorState::RUMOR_GRAIL) { - rumorExtra = getTile(map->grailPos)->terType.id(); + rumorExtra = getTile(map->grailPos)->terType->id; break; } diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp index 2d645fc09..f4ad41280 100644 --- a/lib/CGeneralTextHandler.cpp +++ b/lib/CGeneralTextHandler.cpp @@ -336,12 +336,12 @@ CGeneralTextHandler::CGeneralTextHandler() for(int i = 0; i < h3mTerrainNames.size(); ++i) { - terrainNames[Terrain::createTerrainTypeH3M(i)] = h3mTerrainNames[i]; + terrainNames[i] = h3mTerrainNames[i]; } - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - if(!Terrain::Manager::getInfo(terrain).terrainText.empty()) - terrainNames[terrain] = Terrain::Manager::getInfo(terrain).terrainText; + if(!terrain->terrainText.empty()) + terrainNames[terrain->id] = terrain->terrainText; } diff --git a/lib/CGeneralTextHandler.h b/lib/CGeneralTextHandler.h index 58feed9ce..97a7010e1 100644 --- a/lib/CGeneralTextHandler.h +++ b/lib/CGeneralTextHandler.h @@ -122,7 +122,7 @@ public: std::vector advobtxt; std::vector xtrainfo; std::vector restypes; //names of resources - std::map terrainNames; + std::map terrainNames; std::vector randsign; std::vector> mines; //first - name; second - event description std::vector seerEmpty; diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index bdf8b9137..a215f27f4 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -344,9 +344,9 @@ CHeroHandler::~CHeroHandler() = default; CHeroHandler::CHeroHandler() { loadTerrains(); - for(int i = 0; i < VLC->terrainTypeHandler::terrains().size(); ++i) + for(int i = 0; i < VLC->terrainTypeHandler->terrains().size(); ++i) { - VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler::terrains()[i], i); + VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler->terrains()[i]->name, i); } loadBallistics(); loadExperience(); @@ -972,9 +972,9 @@ ui64 CHeroHandler::reqExp (ui32 level) const void CHeroHandler::loadTerrains() { - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - terrCosts[terrain] = Terrain::Manager::getInfo(terrain).moveCost; + terrCosts[terrain->id] = terrain->moveCost; } } diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index 87da89149..418439eab 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -265,7 +265,7 @@ public: CHeroClassHandler classes; //default costs of going through terrains. -1 means terrain is impassable - std::map terrCosts; + std::map terrCosts; struct SBallisticsLevelInfo { diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 42ed781f7..92e7ce265 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -46,7 +46,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState for(pos.y=0; pos.y < sizes.y; ++pos.y) { const TerrainTile * tile = &gs->map->getTile(pos); - if(tile->terType.isWater()) + if(tile->terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) @@ -54,7 +54,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState if(useWaterWalking) resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); } - if(tile->terType.isLand()) + if(tile->terType->isLand()) { resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) @@ -1008,10 +1008,10 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl) { - for(int i = 0; i < VLC->terrainTypeHandler::terrains().size(); ++i) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { noTerrainPenalty.push_back(static_cast( - bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(i))))); + bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(terrain->id))))); } freeShipBoarding = static_cast(bl->getFirst(Selector::type()(Bonus::FREE_SHIP_BOARDING))); @@ -1027,7 +1027,7 @@ TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn) { bonuses = hero->getAllBonuses(Selector::days(turn), Selector::all, nullptr, ""); bonusCache = make_unique(bonuses); - nativeTerrain = hero->getNativeTerrain(); + nativeTerrain = VLC->terrainTypeHandler->terrains()[hero->getNativeTerrain()]; } bool TurnInfo::isLayerAvailable(const EPathfindingLayer layer) const @@ -1178,7 +1178,7 @@ void CPathfinderHelper::getNeighbours( continue; const TerrainTile & hlpt = map->getTile(hlp); - if(!hlpt.terType.isPassable()) + if(!hlpt.terType->isPassable()) continue; // //we cannot visit things from blocked tiles @@ -1188,18 +1188,18 @@ void CPathfinderHelper::getNeighbours( // } /// Following condition let us avoid diagonal movement over coast when sailing - if(srct.terType.isWater() && limitCoastSailing && hlpt.terType.isWater() && dir.x && dir.y) //diagonal move through water + if(srct.terType->isWater() && limitCoastSailing && hlpt.terType->isWater() && dir.x && dir.y) //diagonal move through water { int3 hlp1 = tile, hlp2 = tile; hlp1.x += dir.x; hlp2.y += dir.y; - if(map->getTile(hlp1).terType.isLand() || map->getTile(hlp2).terType.isLand()) + if(map->getTile(hlp1).terType->isLand() || map->getTile(hlp2).terType->isLand()) continue; } - if(indeterminate(onLand) || onLand == hlpt.terType.isLand()) + if(indeterminate(onLand) || onLand == hlpt.terType->isLand()) { vec.push_back(hlp); } @@ -1237,7 +1237,7 @@ int CPathfinderHelper::getMovementCost( { ret = static_cast(ret * (100.0 + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)) / 100.0); } - else if(dt->terType.isWater()) + else if(dt->terType->isWater()) { if(hero->boat && ct->hasFavorableWinds() && dt->hasFavorableWinds()) ret = static_cast(ret * 0.666); @@ -1265,7 +1265,7 @@ int CPathfinderHelper::getMovementCost( { std::vector vec; vec.reserve(8); //optimization - getNeighbours(*dt, dst, vec, ct->terType.isLand(), true); + getNeighbours(*dt, dst, vec, ct->terType->isLand(), true); for(auto & elem : vec) { int fcost = getMovementCost(dst, elem, nullptr, nullptr, left, false); diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 2bd7e5790..fc12c853c 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -523,7 +523,7 @@ struct DLL_LINKAGE TurnInfo TConstBonusListPtr bonuses; mutable int maxMovePointsLand; mutable int maxMovePointsWater; - Terrain nativeTerrain; + const TerrainType * nativeTerrain; TurnInfo(const CGHeroInstance * Hero, const int Turn = 0); bool isLayerAvailable(const EPathfindingLayer layer) const; diff --git a/lib/CStack.cpp b/lib/CStack.cpp index 64c5e98f8..7abb32067 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -328,11 +328,11 @@ bool CStack::canBeHealed() const bool CStack::isOnNativeTerrain() const { //this code is called from CreatureTerrainLimiter::limit on battle start - auto res = nativeTerrain == Terrain::ANY || nativeTerrain == battle->getTerrainType(); + auto res = nativeTerrain == Terrain::ANY_TERRAIN || nativeTerrain == battle->getTerrainType(); return res; } -bool CStack::isOnTerrain(const Terrain & terrain) const +bool CStack::isOnTerrain(TTerrain terrain) const { return battle->getTerrainType() == terrain; } diff --git a/lib/CStack.h b/lib/CStack.h index f969efab3..09109e1ec 100644 --- a/lib/CStack.h +++ b/lib/CStack.h @@ -29,7 +29,7 @@ public: ui32 ID; //unique ID of stack const CCreature * type; - Terrain nativeTerrain; //tmp variable to save native terrain value on battle init + TTerrain nativeTerrain; //tmp variable to save native terrain value on battle init ui32 baseAmount; PlayerColor owner; //owner - player color (255 for neutrals) @@ -51,7 +51,7 @@ public: bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines bool isOnNativeTerrain() const; - bool isOnTerrain(const Terrain & terrain) const; + bool isOnTerrain(TTerrain terrain) const; ui32 level() const; si32 magicResistance() const override; //include aura of resistance diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index bb5085f2b..88be8b956 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -26,9 +26,9 @@ const int NAMES_PER_TOWN=16; // number of town names per faction in H3 files. Json can define any number -const Terrain CTownHandler::defaultGoodTerrain{"grass"}; -const Terrain CTownHandler::defaultEvilTerrain{"lava"}; -const Terrain CTownHandler::defaultNeutralTerrain{"rough"}; +const TTerrain CTownHandler::defaultGoodTerrain(Terrain::GRASS); +const TTerrain CTownHandler::defaultEvilTerrain(Terrain::LAVA); +const TTerrain CTownHandler::defaultNeutralTerrain(Terrain::ROUGH); const std::map CBuilding::MODES = { @@ -942,9 +942,9 @@ void CTownHandler::loadPuzzle(CFaction &faction, const JsonNode &source) assert(faction.puzzleMap.size() == GameConstants::PUZZLE_MAP_PIECES); } -Terrain CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const +TTerrain CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const { - Terrain terrain = defaultGoodTerrain; + TTerrain terrain = defaultGoodTerrain; switch(alignment) { @@ -983,7 +983,7 @@ CFaction * CTownHandler::loadFromJson(const std::string & scope, const JsonNode auto nativeTerrain = source["nativeTerrain"]; faction->nativeTerrain = nativeTerrain.isNull() ? getDefaultTerrainForAlignment(faction->alignment) - : Terrain(nativeTerrain.String()); + : VLC->terrainTypeHandler->getInfoByName(nativeTerrain.String())->id; if (!source["town"].isNull()) { diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 7728d2992..52f56e323 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -185,7 +185,7 @@ public: TFaction index; - Terrain nativeTerrain; + TTerrain nativeTerrain; EAlignment::EAlignment alignment; bool preferUndergroundPlacement; @@ -358,9 +358,9 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase requirementsToLoad; std::vector overriddenBidsToLoad; //list of buildings, which bonuses should be overridden. - const static Terrain defaultGoodTerrain; - const static Terrain defaultEvilTerrain; - const static Terrain defaultNeutralTerrain; + const static TTerrain defaultGoodTerrain; + const static TTerrain defaultEvilTerrain; + const static TTerrain defaultNeutralTerrain; static TPropagatorPtr & emptyPropagator(); @@ -391,7 +391,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase TDmgRange; typedef si32 TBonusSubtype; typedef si32 TQuantity; -typedef ui8 TTerrain; +typedef si8 TTerrain; typedef int TRmgTemplateZoneId; diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 081d874f7..042c0f526 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -2107,9 +2107,13 @@ bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest) } CreatureTerrainLimiter::CreatureTerrainLimiter() - : terrainType() + : terrainType(Terrain::NATIVE_TERRAIN) { +} +CreatureTerrainLimiter::CreatureTerrainLimiter(TTerrain terrain): + terrainType(terrain) +{ } int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const @@ -2117,9 +2121,14 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const const CStack *stack = retrieveStackBattle(&context.node); if(stack) { - if(terrainType.isNative())//terrainType not specified = native + if (terrainType == Terrain::NATIVE_TERRAIN)//terrainType not specified = native + { return !stack->isOnNativeTerrain(); - return !stack->isOnTerrain(terrainType); + } + else + { + return !stack->isOnTerrain(terrainType); + } } return true; //TODO neutral creatues @@ -2128,7 +2137,8 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const std::string CreatureTerrainLimiter::toString() const { boost::format fmt("CreatureTerrainLimiter(terrainType=%s)"); - fmt % (terrainType.isNative() ? "native" : static_cast(terrainType)); + auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType]->name; + fmt % (terrainType == Terrain::NATIVE_TERRAIN ? "native" : terrainName); return fmt.str(); } @@ -2137,8 +2147,8 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const JsonNode root(JsonNode::JsonType::DATA_STRUCT); root["type"].String() = "CREATURE_TERRAIN_LIMITER"; - if(!terrainType.isNative()) - root["parameters"].Vector().push_back(JsonUtils::stringNode(terrainType)); + auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType]->name; + root["parameters"].Vector().push_back(JsonUtils::stringNode(terrainName)); return root; } diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 61941c27a..f1ff8a950 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -1060,9 +1060,9 @@ public: class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain { public: - Terrain terrainType; + TTerrain terrainType; CreatureTerrainLimiter(); - CreatureTerrainLimiter(const Terrain& terrain); + CreatureTerrainLimiter(TTerrain terrain); int limit(const BonusLimitationContext &context) const override; virtual std::string toString() const override; diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index cf1d235f3..08643e1ba 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -50,7 +50,7 @@ void CPrivilegedInfoCallback::getFreeTiles(std::vector & tiles) const for (int yd = 0; yd < gs->map->height; yd++) { tinfo = getTile(int3 (xd,yd,zd)); - if (tinfo->terType.isLand() && tinfo->terType.isPassable() && !tinfo->blocked) //land and free + if (tinfo->terType->isLand() && tinfo->terType->isPassable() && !tinfo->blocked) //land and free tiles.push_back (int3 (xd,yd,zd)); } } @@ -117,8 +117,8 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set & { for (int yd = 0; yd < gs->map->height; yd++) { - if ((getTile (int3 (xd,yd,zd))->terType.isWater() && water) - || (getTile (int3 (xd,yd,zd))->terType.isLand() && land)) + if ((getTile (int3 (xd,yd,zd))->terType->isWater() && water) + || (getTile (int3 (xd,yd,zd))->terType->isLand() && land)) tiles.insert(int3(xd,yd,zd)); } } diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 3fa981434..5024a0d09 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -701,13 +701,13 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs) DLL_LINKAGE void NewObject::applyGs(CGameState *gs) { - Terrain terrainType; + TTerrain terrainType = Terrain::BORDER; if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not { CGObjectInstance testObject = CGObjectInstance(); testObject.pos = pos; - testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(Terrain("water")).front(); + testObject.appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(Terrain::WATER).front(); const int3 previousXAxisTile = int3(pos.x - 1, pos.y, pos.z); assert(gs->isInTheMap(previousXAxisTile) && (testObject.visitablePos() == previousXAxisTile)); @@ -716,7 +716,7 @@ DLL_LINKAGE void NewObject::applyGs(CGameState *gs) else { const TerrainTile & t = gs->map->getTile(pos); - terrainType = t.terType; + terrainType = t.terType->id; } CGObjectInstance *o = nullptr; @@ -724,7 +724,7 @@ DLL_LINKAGE void NewObject::applyGs(CGameState *gs) { case Obj::BOAT: o = new CGBoat(); - terrainType = Terrain("water"); //TODO: either boat should only spawn on water, or all water objects should be handled this way + terrainType = Terrain::WATER; //TODO: either boat should only spawn on water, or all water objects should be handled this way break; case Obj::MONSTER: //probably more options will be needed o = new CGCreature(); diff --git a/lib/ObstacleHandler.cpp b/lib/ObstacleHandler.cpp index a55fe0678..69918e64e 100644 --- a/lib/ObstacleHandler.cpp +++ b/lib/ObstacleHandler.cpp @@ -66,7 +66,7 @@ std::vector ObstacleInfo::getBlocked(BattleHex hex) const return ret; } -bool ObstacleInfo::isAppropriate(const Terrain & terrainType, const BattleField & battlefield) const +bool ObstacleInfo::isAppropriate(const TTerrain terrainType, const BattleField & battlefield) const { auto bgInfo = battlefield.getInfo(); @@ -84,7 +84,7 @@ ObstacleInfo * ObstacleHandler::loadFromJson(const std::string & scope, const Js info->width = json["width"].Integer(); info->height = json["height"].Integer(); for(auto & t : json["allowedTerrain"].Vector()) - info->allowedTerrains.emplace_back(t.String()); + info->allowedTerrains.emplace_back(VLC->terrainTypeHandler->getInfoByName(t.String())->id); for(auto & t : json["specialBattlefields"].Vector()) info->allowedSpecialBfields.emplace_back(t.String()); info->blockedTiles = json["blockedTiles"].convertTo>(); diff --git a/lib/ObstacleHandler.h b/lib/ObstacleHandler.h index 7075d140b..e870265c9 100644 --- a/lib/ObstacleHandler.h +++ b/lib/ObstacleHandler.h @@ -31,7 +31,7 @@ public: si32 iconIndex; std::string identifier; std::string appearAnimation, animation, dissapearAnimation; - std::vector allowedTerrains; + std::vector allowedTerrains; std::vector allowedSpecialBfields; //TODO: here is extra field to implement it's logic in the future but save backward compatibility @@ -50,7 +50,7 @@ public: std::vector getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex' - bool isAppropriate(const Terrain & terrainType, const BattleField & specialBattlefield) const; + bool isAppropriate(const TTerrain terrainType, const BattleField & specialBattlefield) const; template void serialize(Handler &h, const int version) { diff --git a/lib/PathfinderUtil.h b/lib/PathfinderUtil.h index 0e750e9d4..063f97820 100644 --- a/lib/PathfinderUtil.h +++ b/lib/PathfinderUtil.h @@ -59,13 +59,13 @@ namespace PathfinderUtil break; case ELayer::WATER: - if(tinfo->blocked || tinfo->terType.isLand()) + if(tinfo->blocked || tinfo->terType->isLand()) return CGPathNode::BLOCKED; break; case ELayer::AIR: - if(tinfo->blocked || tinfo->terType.isLand()) + if(tinfo->blocked || tinfo->terType->isLand()) return CGPathNode::FLYABLE; break; diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 035b859ee..42011a3dc 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -34,7 +34,7 @@ TerrainTypeHandler::TerrainTypeHandler() JsonNode terrs(mod, ResourceID("config/terrains.json")); for(auto & terr : terrs.Struct()) { - auto * info = new TerrainType(terr.first); + auto * info = new TerrainType(terr.first); //set name info->moveCost = terr.second["moveCost"].Integer(); const JsonVector &unblockedVec = terr.second["minimapUnblocked"].Vector(); @@ -70,11 +70,15 @@ TerrainTypeHandler::TerrainTypeHandler() if(terr.second["rockTerrain"].isNull()) { - info->rockTerrain = "rock"; + info->rockTerrain = Terrain::ROCK; } else { - info->rockTerrain = terr.second["rockTerrain"].String(); + auto rockTerrainType = terr.second["rockTerrain"].String(); + resolveLater.push_back([this, rockTerrainType, info]() + { + info->rockTerrain = getInfoByName(rockTerrainType)->id; + }); } if(terr.second["river"].isNull()) @@ -122,7 +126,11 @@ TerrainTypeHandler::TerrainTypeHandler() { for(auto & t : terr.second["prohibitTransitions"].Vector()) { - info->prohibitTransitions.emplace_back(t.String()); + std::string prohibitedTerrainName = t.String(); + resolveLater.push_back([this, prohibitedTerrainName, info]() + { + info->prohibitTransitions.emplace_back(getInfoByName(prohibitedTerrainName)->id); + }); } } @@ -138,13 +146,7 @@ TerrainTypeHandler::TerrainTypeHandler() info->terrainViewPatterns = terr.second["terrainViewPatterns"].String(); } - //TODO: handle 10 origina terrains - - terrainInfoByName[terr.first] = info; - terrainInfoByCode[info->typeCode] = info; - terrainInfoById[info->id] = info; - - TTerrain id; + TTerrain id = Terrain::WRONG; if(!terr.second["originalTerrainId"].isNull()) { //place in reserved slot @@ -173,24 +175,34 @@ TerrainTypeHandler::TerrainTypeHandler() } } -const std::vector & TerrainTypeHandler::terrains() +void TerrainTypeHandler::recreateTerrainMaps() +{ + for (const TerrainType * terrainInfo : objects) + { + terrainInfoByName[terrainInfo->name] = terrainInfo; + terrainInfoByCode[terrainInfo->typeCode] = terrainInfo; + terrainInfoById[terrainInfo->id] = terrainInfo; + } +} + +const std::vector & TerrainTypeHandler::terrains() const { return objects; } const TerrainType* TerrainTypeHandler::getInfoByName(const std::string& terrainName) const { - + return terrainInfoByName.at(terrainName); } -const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainName) const +const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainCode) const { - + return terrainInfoByCode.at(terrainCode); } const TerrainType* TerrainTypeHandler::getInfoById(TTerrain id) const { - + return terrainInfoById.at(id); } std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType) @@ -202,10 +214,18 @@ TerrainType::operator std::string() const { return name; } - -TerrainType::TerrainType(const std::string & _name) : name(_name) -{} +TerrainType::TerrainType(const std::string& _name): + name(name), + id(Terrain::WRONG), + rockTerrain(Terrain::ROCK), + moveCost(100), + horseSoundId(0), + passabilityType(PassabilityType::LAND), + transitionRequired(false) +{ +} + TerrainType& TerrainType::operator=(const TerrainType & other) { //TODO diff --git a/lib/Terrain.h b/lib/Terrain.h index 3f2844823..ace2a74e2 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -37,17 +37,17 @@ public: std::string terrainText; std::string typeCode; std::string terrainViewPatterns; - std::string rockTerrain; std::string river; TTerrain id; + TTerrain rockTerrain; int moveCost; int horseSoundId; PassabilityType passabilityType; bool transitionRequired; - TerrainType(const std::string & _type = ""); - + TerrainType(const std::string & name = ""); + TerrainType& operator=(const TerrainType & _type); bool operator==(const TerrainType & other); @@ -87,19 +87,29 @@ public: DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType); -class DLL_LINKAGE TerrainTypeHandler //TODO: handlerBase +class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? { public: TerrainTypeHandler(); - const std::vector & terrains(); + const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; - const TerrainType * getInfoByCode(const std::string & terrainName) const; + const TerrainType * getInfoByCode(const std::string & terrainCode) const; const TerrainType * getInfoById(TTerrain id) const; //TODO: road, river types? + template void serialize(Handler &h, const int version) + { + h & objects; + + if (!h.saving) + { + recreateTerrainMaps(); + } + } + private: std::vector objects; @@ -108,18 +118,6 @@ private: std::unordered_map terrainInfoByCode; std::unordered_map terrainInfoById; - template void serialize(Handler &h, const int version) - { - h & name; + void recreateTerrainMaps(); - if (!saving) - { - //TODO: recreate at load - } - /* - h & terrainInfoByName; - h & terrainInfoByCode; - h & terrainInfoById; - */ - } }; diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 81fd2bd99..99477eaab 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -195,6 +195,8 @@ void LibClasses::init(bool onlyEssential) createHandler(generaltexth, "General text", pomtime); + createHandler(terrainTypeHandler, "Terrain", pomtime); + createHandler(heroh, "Hero", pomtime); createHandler(arth, "Artifact", pomtime); diff --git a/lib/VCMI_Lib.h b/lib/VCMI_Lib.h index 774db316d..bff62add2 100644 --- a/lib/VCMI_Lib.h +++ b/lib/VCMI_Lib.h @@ -27,6 +27,7 @@ class CContentHandler; class BattleFieldHandler; class IBonusTypeHandler; class CBonusTypeHandler; +class TerrainTypeHandler; class ObstacleHandler; class CTerrainViewPatternConfig; class CRmgTemplateStorage; @@ -78,6 +79,7 @@ public: CTownHandler * townh; CGeneralTextHandler * generaltexth; CModHandler * modh; + TerrainTypeHandler * terrainTypeHandler; CTerrainViewPatternConfig * terviewh; CRmgTemplateStorage * tplh; BattleFieldHandler * battlefieldsHandler; @@ -112,6 +114,7 @@ public: h & skillh; h & battlefieldsHandler; h & obstacleHandler; + h & terrainTypeHandler; if(!h.saving) { diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index f49d1e9a6..7bf2100d5 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -189,7 +189,7 @@ struct RangeGenerator std::function myRand; }; -BattleInfo * BattleInfo::setupBattle(const int3 & tile, const Terrain & terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) +BattleInfo * BattleInfo::setupBattle(const int3 & tile, TTerrain terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) { CMP_stack cmpst; auto curB = new BattleInfo(); @@ -563,7 +563,7 @@ BattleField BattleInfo::getBattlefieldType() const return battlefieldType; } -Terrain BattleInfo::getTerrainType() const +TTerrain BattleInfo::getTerrainType() const { return terrainType; } diff --git a/lib/battle/BattleInfo.h b/lib/battle/BattleInfo.h index 1d0c128cc..b72fa24c0 100644 --- a/lib/battle/BattleInfo.h +++ b/lib/battle/BattleInfo.h @@ -18,7 +18,6 @@ class CStack; class CStackInstance; class CStackBasicDescriptor; -class Terrain; class BattleField; class DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallback, public IBattleState @@ -38,7 +37,7 @@ public: SiegeInfo si; BattleField battlefieldType; //like !!BA:B - Terrain terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) + TTerrain terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) ui8 tacticsSide; //which side is requested to play tactics phase ui8 tacticDistance; //how many hexes we can go forward (1 = only hexes adjacent to margin line) @@ -74,7 +73,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - Terrain getTerrainType() const override; + TTerrain getTerrainType() const override; ObstacleCList getAllObstacles() const override; @@ -139,7 +138,7 @@ public: const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player void localInit(); - static BattleInfo * setupBattle(const int3 & tile, const Terrain & terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); + static BattleInfo * setupBattle(const int3 & tile, TTerrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); ui8 whatSide(PlayerColor player) const; diff --git a/lib/battle/BattleProxy.cpp b/lib/battle/BattleProxy.cpp index 83df1520a..18bbc328c 100644 --- a/lib/battle/BattleProxy.cpp +++ b/lib/battle/BattleProxy.cpp @@ -47,7 +47,7 @@ BattleField BattleProxy::getBattlefieldType() const return subject->battleGetBattlefieldType(); } -Terrain BattleProxy::getTerrainType() const +TTerrain BattleProxy::getTerrainType() const { return subject->battleTerrainType(); } diff --git a/lib/battle/BattleProxy.h b/lib/battle/BattleProxy.h index b756dadea..9972fe071 100644 --- a/lib/battle/BattleProxy.h +++ b/lib/battle/BattleProxy.h @@ -30,7 +30,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - Terrain getTerrainType() const override; + TTerrain getTerrainType() const override; ObstacleCList getAllObstacles() const override; diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index 9d0370a1f..512ed414c 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -14,9 +14,9 @@ #include "../NetPacks.h" #include "../mapObjects/CGTownInstance.h" -Terrain CBattleInfoEssentials::battleTerrainType() const +TTerrain CBattleInfoEssentials::battleTerrainType() const { - RETURN_IF_NOT_BATTLE(Terrain()); + RETURN_IF_NOT_BATTLE(TTerrain()); return getBattle()->getTerrainType(); } diff --git a/lib/battle/CBattleInfoEssentials.h b/lib/battle/CBattleInfoEssentials.h index bc354ab78..89b1fb90c 100644 --- a/lib/battle/CBattleInfoEssentials.h +++ b/lib/battle/CBattleInfoEssentials.h @@ -46,7 +46,7 @@ public: BattlePerspective::BattlePerspective battleGetMySide() const; const IBonusBearer * getBattleNode() const; - Terrain battleTerrainType() const override; + TTerrain battleTerrainType() const override; BattleField battleGetBattlefieldType() const override; int32_t battleGetEnchanterCounter(ui8 side) const; diff --git a/lib/battle/IBattleInfoCallback.h b/lib/battle/IBattleInfoCallback.h index ad3d0e6e4..08d2cf3c4 100644 --- a/lib/battle/IBattleInfoCallback.h +++ b/lib/battle/IBattleInfoCallback.h @@ -10,11 +10,11 @@ #pragma once +#include "GameConstants.h" #include "BattleHex.h" struct CObstacleInstance; class BattleField; -class Terrain; namespace battle { @@ -34,7 +34,7 @@ class DLL_LINKAGE IBattleInfoCallback public: virtual scripting::Pool * getContextPool() const = 0; - virtual Terrain battleTerrainType() const = 0; + virtual TTerrain battleTerrainType() const = 0; virtual BattleField battleGetBattlefieldType() const = 0; ///return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw diff --git a/lib/battle/IBattleState.h b/lib/battle/IBattleState.h index 02f21d935..89c0f3cc3 100644 --- a/lib/battle/IBattleState.h +++ b/lib/battle/IBattleState.h @@ -42,7 +42,7 @@ public: virtual battle::Units getUnitsIf(battle::UnitFilter predicate) const = 0; virtual BattleField getBattlefieldType() const = 0; - virtual Terrain getTerrainType() const = 0; + virtual TTerrain getTerrainType() const = 0; virtual ObstacleCList getAllObstacles() const = 0; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 903de00dd..f0038a696 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -98,13 +98,13 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f break; } } - else if(ti->nativeTerrain != from.terType //the terrain is not native - && ti->nativeTerrain != Terrain::ANY //no special creature bonus - && !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType.id()) //no special movement bonus + else if(ti->nativeTerrain->id != from.terType->id //the terrain is not native + && ti->nativeTerrain != nullptr //no special creature bonus + && !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType->id) //no special movement bonus ) { - ret = VLC->heroh->terrCosts[from.terType]; + ret = VLC->heroh->terrCosts[from.terType->id]; ret -= ti->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::PATHFINDING); if(ret < GameConstants::BASE_MOVEMENT_COST) ret = GameConstants::BASE_MOVEMENT_COST; @@ -112,7 +112,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f return (ui32)ret; } -Terrain CGHeroInstance::getNativeTerrain() const +TTerrain CGHeroInstance::getNativeTerrain() const { // NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army. // This is clearly bug in H3 however intended behaviour is not clear. @@ -120,18 +120,18 @@ Terrain CGHeroInstance::getNativeTerrain() const // will always have best penalty without any influence from player-defined stacks order // TODO: What should we do if all hero stacks are neutral creatures? - Terrain nativeTerrain("BORDER"); + TTerrain nativeTerrain = Terrain::BORDER; for(auto stack : stacks) { - Terrain stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. + TTerrain stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. - if(stackNativeTerrain == Terrain("BORDER")) + if(stackNativeTerrain == Terrain::BORDER) //where does this value come from? continue; - if(nativeTerrain == Terrain("BORDER")) + if(nativeTerrain == Terrain::BORDER) //FIXME: this statement is always true nativeTerrain = stackNativeTerrain; else if(nativeTerrain != stackNativeTerrain) - return Terrain("BORDER"); + return Terrain::BORDER; } return nativeTerrain; } @@ -529,7 +529,8 @@ void CGHeroInstance::initObj(CRandomGenerator & rand) if (ID != Obj::PRISON) { - auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->getIndex())->getOverride(cb->gameState()->getTile(visitablePos())->terType, this); + auto terrain = cb->gameState()->getTile(visitablePos())->terType->id; + auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->getIndex())->getOverride(terrain, this); if (customApp) appearance = customApp; } diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index ea88e41b9..a0443bb4c 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -155,7 +155,7 @@ public: bool needsLastStack()const override; ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling - Terrain getNativeTerrain() const; + TTerrain getNativeTerrain() const; ui32 getLowestCreatureSpeed() const; int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index 42cd5c2d2..9c6f1c67c 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -1130,8 +1130,9 @@ void CGTownInstance::setType(si32 ID, si32 subID) void CGTownInstance::updateAppearance() { + auto terrain = cb->gameState()->getTile(visitablePos())->terType->id; //FIXME: not the best way to do this - auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this); + auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(terrain, this); if (app) appearance = app; } diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index 4a3e8ad12..d9474bd07 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -581,7 +581,7 @@ BattleField AObjectTypeHandler::getBattlefield() const return battlefield ? BattleField::fromString(battlefield.get()) : BattleField::NONE; } -std::vector>AObjectTypeHandler::getTemplates(const Terrain & terrainType) const +std::vector>AObjectTypeHandler::getTemplates(TTerrain terrainType) const { std::vector> templates = getTemplates(); std::vector> filtered; @@ -598,7 +598,7 @@ std::vector>AObjectTypeHandler::getTemplat return filtered; } -std::shared_ptr AObjectTypeHandler::getOverride(const Terrain & terrainType, const CGObjectInstance * object) const +std::shared_ptr AObjectTypeHandler::getOverride(TTerrain terrainType, const CGObjectInstance * object) const { std::vector> ret = getTemplates(terrainType); for (const auto & tmpl: ret) diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index cff16a715..83ff1b5f3 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -182,11 +182,11 @@ public: /// returns all templates matching parameters std::vector> getTemplates() const; - std::vector> getTemplates(const Terrain & terrainType) const; + std::vector> getTemplates(const TTerrain terrainType) const; /// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle) /// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server) - std::shared_ptr getOverride(const Terrain & terrainType, const CGObjectInstance * object) const; + std::shared_ptr getOverride(TTerrain terrainType, const CGObjectInstance * object) const; BattleField getBattlefield() const; diff --git a/lib/mapObjects/CObjectHandler.cpp b/lib/mapObjects/CObjectHandler.cpp index 35904fb65..1482e5124 100644 --- a/lib/mapObjects/CObjectHandler.cpp +++ b/lib/mapObjects/CObjectHandler.cpp @@ -206,8 +206,8 @@ void CGObjectInstance::setType(si32 ID, si32 subID) logGlobal->error("Unknown object type %d:%d at %s", ID, subID, visitablePos().toString()); return; } - if(!handler->getTemplates(tile.terType).empty()) - appearance = handler->getTemplates(tile.terType)[0]; + if(!handler->getTemplates(tile.terType->id).empty()) + appearance = handler->getTemplates(tile.terType->id)[0]; else appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash if (ID == Obj::HERO) @@ -434,7 +434,7 @@ int3 IBoatGenerator::bestLocation() const { if(const TerrainTile *tile = IObjectInterface::cb->getTile(o->pos + offset, false)) //tile is in the map { - if(tile->terType.isWater() && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat + if(tile->terType->isWater() && (!tile->blocked || tile->blockingObjects.front()->ID == Obj::BOAT)) //and is water and is not blocked or is blocked by boat return o->pos + offset; } } diff --git a/lib/mapObjects/CommonConstructors.cpp b/lib/mapObjects/CommonConstructors.cpp index 3b870847a..1db7b3e87 100644 --- a/lib/mapObjects/CommonConstructors.cpp +++ b/lib/mapObjects/CommonConstructors.cpp @@ -78,7 +78,7 @@ CGObjectInstance * CTownInstanceConstructor::create(std::shared_ptrcb->getTile(object->pos)->terType, object); + auto templ = getOverride(object->cb->getTile(object->pos)->terType->id, object); if(templ) object->appearance = templ; } diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 16a126483..0d0be8980 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -155,20 +155,20 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) // so these two fields can be interpreted as "strong affinity" and "weak affinity" towards terrains std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain - assert(terrStr.size() == 9); // all terrains but rock - for(size_t i = 0; i < 9; i++) + assert(terrStr.size() == Terrain::ROCK - 1); // all terrains but rock + for(TTerrain i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) { if (terrStr[8-i] == '1') - allowedTerrains.insert(Terrain::createTerrainTypeH3M(i)); + allowedTerrains.insert(i); } //assuming that object can be placed on other land terrains - if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water"))) + if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER)) { - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - if(terrain.isLand() && terrain.isPassable()) - allowedTerrains.insert(terrain); + if(terrain->isLand() && terrain->isPassable()) + allowedTerrains.insert(terrain->id); } } @@ -229,19 +229,19 @@ void ObjectTemplate::readMap(CBinaryReader & reader) reader.readUInt16(); ui16 terrMask = reader.readUInt16(); - for(size_t i = 0; i < 9; i++) + for(size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) { if (((terrMask >> i) & 1 ) != 0) - allowedTerrains.insert(Terrain::createTerrainTypeH3M(i)); + allowedTerrains.insert(i); } //assuming that object can be placed on other land terrains - if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain("water"))) + if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER)) { - for(auto & terrain : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - if(terrain.isLand() && terrain.isPassable()) - allowedTerrains.insert(terrain); + if(terrain->isLand() && terrain->isPassable()) + allowedTerrains.insert(terrain->id); } } @@ -285,15 +285,15 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) if(withTerrain && !node["allowedTerrains"].isNull()) { for (auto & entry : node["allowedTerrains"].Vector()) - allowedTerrains.insert(entry.String()); + allowedTerrains.insert(VLC->terrainTypeHandler->getInfoByName(entry.String())->id); } else { - for(auto & i : VLC->terrainTypeHandler::terrains()) + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { - if(!i.isPassable() || i.isWater()) + if(!terrain->isPassable() || terrain->isWater()) continue; - allowedTerrains.insert(i); + allowedTerrains.insert(terrain->id); } } @@ -369,7 +369,7 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const if(withTerrain) { //assumed that ROCK and WATER terrains are not included - if(allowedTerrains.size() < (VLC->terrainTypeHandler::terrains().size() - 2)) + if(allowedTerrains.size() < (VLC->terrainTypeHandler->terrains().size() - 2)) { JsonVector & data = node["allowedTerrains"].Vector(); @@ -556,9 +556,9 @@ void ObjectTemplate::calculateVisitableOffset() visitableOffset = int3(0, 0, 0); } -bool ObjectTemplate::canBePlacedAt(Terrain terrain) const +bool ObjectTemplate::canBePlacedAt(TTerrain terrain) const { - return allowedTerrains.count(terrain) != 0; + return vstd::contains(allowedTerrains, terrain); } void ObjectTemplate::recalculate() diff --git a/lib/mapObjects/ObjectTemplate.h b/lib/mapObjects/ObjectTemplate.h index e10f1efad..e1b9c2c1b 100644 --- a/lib/mapObjects/ObjectTemplate.h +++ b/lib/mapObjects/ObjectTemplate.h @@ -16,7 +16,6 @@ class CBinaryReader; class CLegacyConfigParser; class JsonNode; class int3; -class Terrain; class DLL_LINKAGE ObjectTemplate { @@ -32,7 +31,7 @@ class DLL_LINKAGE ObjectTemplate /// directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7) ui8 visitDir; /// list of terrains on which this object can be placed - std::set allowedTerrains; + std::set allowedTerrains; void afterLoadFixup(); @@ -99,7 +98,7 @@ public: }; // Checks if object can be placed on specific terrain - bool canBePlacedAt(Terrain terrain) const; + bool canBePlacedAt(TTerrain terrain) const; ObjectTemplate(); //custom copy constructor is required diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 742e709a8..b7c658d17 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -123,8 +123,15 @@ CCastleEvent::CCastleEvent() : town(nullptr) } -TerrainTile::TerrainTile() : terType("BORDER"), terView(0), riverType(RIVER_NAMES[0]), - riverDir(0), roadType(ROAD_NAMES[0]), roadDir(0), extTileFlags(0), visitable(false), +TerrainTile::TerrainTile(): + terType(nullptr), + terView(0), + riverType(RIVER_NAMES[0]), + riverDir(0), + roadType(ROAD_NAMES[0]), + roadDir(0), + extTileFlags(0), + visitable(false), blocked(false) { @@ -132,13 +139,13 @@ TerrainTile::TerrainTile() : terType("BORDER"), terView(0), riverType(RIVER_NAME bool TerrainTile::entrableTerrain(const TerrainTile * from) const { - return entrableTerrain(from ? from->terType.isLand() : true, from ? from->terType.isWater() : true); + return entrableTerrain(from ? from->terType->isLand() : true, from ? from->terType->isWater() : true); } bool TerrainTile::entrableTerrain(bool allowLand, bool allowSea) const { - return terType.isPassable() - && ((allowSea && terType.isWater()) || (allowLand && terType.isLand())); + return terType->isPassable() + && ((allowSea && terType->isWater()) || (allowLand && terType->isLand())); } bool TerrainTile::isClear(const TerrainTile * from) const @@ -164,7 +171,7 @@ CGObjectInstance * TerrainTile::topVisitableObj(bool excludeTop) const EDiggingStatus TerrainTile::getDiggingStatus(const bool excludeTop) const { - if(terType.isWater() || !terType.isPassable()) + if(terType->isWater() || !terType->isPassable()) return EDiggingStatus::WRONG_TERRAIN; int allowedBlocked = excludeTop ? 1 : 0; @@ -181,7 +188,7 @@ bool TerrainTile::hasFavorableWinds() const bool TerrainTile::isWater() const { - return terType.isWater(); + return terType->isWater(); } void CMapHeader::setupEvents() diff --git a/lib/mapping/CMapDefines.h b/lib/mapping/CMapDefines.h index dbaf97f30..dc057be5b 100644 --- a/lib/mapping/CMapDefines.h +++ b/lib/mapping/CMapDefines.h @@ -80,7 +80,7 @@ struct DLL_LINKAGE TerrainTile EDiggingStatus getDiggingStatus(const bool excludeTop = true) const; bool hasFavorableWinds() const; - Terrain terType; + TerrainType * terType; ui8 terView; std::string riverType; ui8 riverDir; diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 2f8d44af9..09a23067c 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -124,7 +124,7 @@ void CMapEditManager::clearTerrain(CRandomGenerator * gen) execute(make_unique(map, gen ? gen : &(this->gen))); } -void CMapEditManager::drawTerrain(Terrain terType, CRandomGenerator * gen) +void CMapEditManager::drawTerrain(TTerrain terType, CRandomGenerator * gen) { execute(make_unique(map, terrainSel, terType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 7fe216d16..99c84a011 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -70,7 +70,7 @@ public: void clearTerrain(CRandomGenerator * gen = nullptr); /// Draws terrain at the current terrain selection. The selection will be cleared automatically. - void drawTerrain(Terrain terType, CRandomGenerator * gen = nullptr); + void drawTerrain(TTerrain terType, CRandomGenerator * gen = nullptr); /// Draws roads at the current terrain selection. The selection will be cleared automatically. void drawRoad(const std::string & roadType, CRandomGenerator * gen = nullptr); diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 4e00496c1..4882e0101 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -81,8 +81,11 @@ void CComposedOperation::addOperation(std::unique_ptr&& operation operations.push_back(std::move(operation)); } -CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, Terrain terType, CRandomGenerator* gen) - : CMapOperation(map), terrainSel(terrainSel), terType(terType), gen(gen) +CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, TTerrain terType, CRandomGenerator* gen): + CMapOperation(map), + terrainSel(terrainSel), + terType(terType), + gen(gen) { } @@ -92,7 +95,7 @@ void CDrawTerrainOperation::execute() for(const auto & pos : terrainSel.getSelectedItems()) { auto & tile = map->getTile(pos); - tile.terType = terType; + tile.terType = VLC->terrainTypeHandler->terrains()[terType]; invalidateTerrainViews(pos); } @@ -149,7 +152,7 @@ void CDrawTerrainOperation::updateTerrainTypes() rect.forEach([&](const int3& posToTest) { auto & terrainTile = map->getTile(posToTest); - if(centerTile.terType != terrainTile.terType) + if(centerTile.terType->id != terrainTile.terType->id) { auto formerTerType = terrainTile.terType; terrainTile.terType = centerTile.terType; @@ -252,7 +255,7 @@ void CDrawTerrainOperation::updateTerrainViews() { for(const auto & pos : invalidatedTerViews) { - const auto & patterns = VLC->terviewh->getTerrainViewPatterns(map->getTile(pos).terType); + const auto & patterns = VLC->terviewh->getTerrainViewPatterns(map->getTile(pos).terType->id); // Detect a pattern which fits best int bestPattern = -1; @@ -340,7 +343,7 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi int cy = pos.y + (i / 3) - 1; int3 currentPos(cx, cy, pos.z); bool isAlien = false; - Terrain terType; + TerrainType * terType = nullptr; if(!map->isInTheMap(currentPos)) { // position is not in the map, so take the ter type from the neighbor tile @@ -373,7 +376,7 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi else { terType = map->getTile(currentPos).terType; - if(terType != centerTerType && (terType.isPassable() || centerTerType.isPassable())) + if(terType != centerTerType && (terType->isPassable() || centerTerType->isPassable())) { isAlien = true; } @@ -388,9 +391,9 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi { if(recDepth == 0 && map->isInTheMap(currentPos)) { - if(terType == centerTerType) + if(terType->id == centerTerType->id) { - const auto & patternForRule = VLC->terviewh->getTerrainViewPatternsById(centerTerType, rule.name); + const auto & patternForRule = VLC->terviewh->getTerrainViewPatternsById(centerTerType->id, rule.name); if(auto p = patternForRule) { auto rslt = validateTerrainView(currentPos, &(*p), 1); @@ -417,18 +420,18 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi bool nativeTestOk, nativeTestStrongOk; nativeTestOk = nativeTestStrongOk = (rule.isNativeStrong() || rule.isNativeRule()) && !isAlien; - if(centerTerType == Terrain("dirt")) + if(centerTerType->id == Terrain::DIRT) { - nativeTestOk = rule.isNativeRule() && !terType.isTransitionRequired(); + nativeTestOk = rule.isNativeRule() && !terType->isTransitionRequired(); bool sandTestOk = (rule.isSandRule() || rule.isTransition()) - && terType.isTransitionRequired(); + && terType->isTransitionRequired(); applyValidationRslt(rule.isAnyRule() || sandTestOk || nativeTestOk || nativeTestStrongOk); } - else if(centerTerType == Terrain("sand")) + else if(centerTerType->id == Terrain::SAND) { applyValidationRslt(true); } - else if(centerTerType.isTransitionRequired()) //water, rock and some special terrains require sand transition + else if(centerTerType->isTransitionRequired()) //water, rock and some special terrains require sand transition { bool sandTestOk = (rule.isSandRule() || rule.isTransition()) && isAlien; @@ -437,9 +440,9 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi else { bool dirtTestOk = (rule.isDirtRule() || rule.isTransition()) - && isAlien && !terType.isTransitionRequired(); + && isAlien && !terType->isTransitionRequired(); bool sandTestOk = (rule.isSandRule() || rule.isTransition()) - && terType.isTransitionRequired(); + && terType->isTransitionRequired(); if(transitionReplacement.empty() && rule.isTransition() && (dirtTestOk || sandTestOk)) @@ -502,7 +505,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const auto valid = validateTerrainView(pos, ptrConfig->getTerrainTypePatternById("n1")).result; // Special validity check for rock & water - if(valid && (terType.isWater() || !terType.isPassable())) + if(valid && (terType->isWater() || !terType->isPassable())) { static const std::string patternIds[] = { "s1", "s2" }; for(auto & patternId : patternIds) @@ -512,7 +515,7 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const } } // Additional validity check for non rock OR water - else if(!valid && (terType.isLand() && terType.isPassable())) + else if(!valid && (terType->isLand() && terType->isPassable())) { static const std::string patternIds[] = { "n2", "n3" }; for (auto & patternId : patternIds) @@ -546,12 +549,12 @@ CClearTerrainOperation::CClearTerrainOperation(CMap* map, CRandomGenerator* gen) { CTerrainSelection terrainSel(map); terrainSel.selectRange(MapRect(int3(0, 0, 0), map->width, map->height)); - addOperation(make_unique(map, terrainSel, Terrain("water"), gen)); + addOperation(make_unique(map, terrainSel, Terrain::WATER, gen)); if(map->twoLevel) { terrainSel.clearSelection(); terrainSel.selectRange(MapRect(int3(0, 0, 1), map->width, map->height)); - addOperation(make_unique(map, terrainSel, Terrain("rock"), gen)); + addOperation(make_unique(map, terrainSel, Terrain::ROCK, gen)); } } diff --git a/lib/mapping/CMapOperation.h b/lib/mapping/CMapOperation.h index 921832470..0c3f851ff 100644 --- a/lib/mapping/CMapOperation.h +++ b/lib/mapping/CMapOperation.h @@ -61,7 +61,7 @@ private: class CDrawTerrainOperation : public CMapOperation { public: - CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, Terrain terType, CRandomGenerator * gen); + CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, TTerrain terType, CRandomGenerator * gen); void execute() override; void undo() override; @@ -98,7 +98,7 @@ private: ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const; CTerrainSelection terrainSel; - Terrain terType; + TTerrain terType; CRandomGenerator* gen; std::set invalidatedTerViews; }; diff --git a/lib/mapping/MapEditUtils.cpp b/lib/mapping/MapEditUtils.cpp index 489954356..513e05f1a 100644 --- a/lib/mapping/MapEditUtils.cpp +++ b/lib/mapping/MapEditUtils.cpp @@ -268,9 +268,9 @@ CTerrainViewPatternConfig::~CTerrainViewPatternConfig() } -const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(const Terrain & terrain) const +const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TTerrain terrain) const { - auto iter = terrainViewPatterns.find(Terrain::Manager::getInfo(terrain).terrainViewPatterns); + auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain]->terrainViewPatterns); if (iter == terrainViewPatterns.end()) return terrainViewPatterns.at("normal"); return iter->second; @@ -293,7 +293,7 @@ boost::optional CTerrainViewPatternConfig::getTerrai return boost::optional(); } -boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(const Terrain & terrain, const std::string & id) const +boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(TTerrain terrain, const std::string & id) const { const std::vector & groupPatterns = getTerrainViewPatterns(terrain); for (const TVPVector & patternFlips : groupPatterns) @@ -355,7 +355,7 @@ void CTerrainViewPatternUtils::printDebuggingInfoAboutTile(const CMap * map, int { auto debugTile = map->getTile(debugPos); - std::string terType = static_cast(debugTile.terType).substr(0, 6); + std::string terType = debugTile.terType->name.substr(0, 6); line += terType; line.insert(line.end(), PADDED_LENGTH - terType.size(), ' '); } diff --git a/lib/mapping/MapEditUtils.h b/lib/mapping/MapEditUtils.h index 6df777a3d..6a6e44962 100644 --- a/lib/mapping/MapEditUtils.h +++ b/lib/mapping/MapEditUtils.h @@ -215,9 +215,9 @@ public: CTerrainViewPatternConfig(); ~CTerrainViewPatternConfig(); - const std::vector & getTerrainViewPatterns(const Terrain & terrain) const; + const std::vector & getTerrainViewPatterns(TTerrain terrain) const; boost::optional getTerrainViewPatternById(std::string patternId, const std::string & id) const; - boost::optional getTerrainViewPatternsById(const Terrain & terrain, const std::string & id) const; + boost::optional getTerrainViewPatternsById(TTerrain terrain, const std::string & id) const; const TVPVector * getTerrainTypePatternById(const std::string & id) const; void flipPattern(TerrainViewPattern & pattern, int flip) const; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 26faf348b..c3a7c0df3 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -921,6 +921,7 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot) void CMapLoaderH3M::readTerrain() { map->initTerrain(); + const auto terrains = VLC->terrainTypeHandler->terrains(); // Read terrain int3 pos; @@ -937,14 +938,14 @@ void CMapLoaderH3M::readTerrain() for(pos.x = 0; pos.x < map->width; pos.x++) { auto & tile = map->getTile(pos); - tile.terType = Terrain::createTerrainTypeH3M(reader.readUInt8()); + tile.terType = terrains[reader.readUInt8()]; tile.terView = reader.readUInt8(); tile.riverType = RIVER_NAMES[reader.readUInt8()]; tile.riverDir = reader.readUInt8(); tile.roadType = ROAD_NAMES[reader.readUInt8()]; tile.roadDir = reader.readUInt8(); tile.extTileFlags = reader.readUInt8(); - tile.blocked = ((!tile.terType.isPassable() || tile.terType == Terrain("BORDER") ) ? true : false); //underground tiles are always blocked + tile.blocked = ((!tile.terType->isPassable() || tile.terType->id == Terrain::BORDER ) ? true : false); //underground tiles are always blocked tile.visitable = 0; } } diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index e14de101b..961721740 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -945,7 +945,7 @@ void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile using namespace TerrainDetail; {//terrain type const std::string typeCode = src.substr(0, 2); - tile.terType = Terrain::createTerrainByCode(typeCode); + tile.terType = const_cast(VLC->terrainTypeHandler->getInfoByCode(typeCode)); } int startPos = 2; //0+typeCode fixed length {//terrain view @@ -1276,7 +1276,7 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile) out.setf(std::ios::dec, std::ios::basefield); out.unsetf(std::ios::showbase); - out << Terrain::Manager::getInfo(tile.terType).typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4]; + out << tile.terType->typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4]; if(tile.roadType != ROAD_NAMES[0]) out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4]; diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 60f54eee1..5edeb4da1 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -49,12 +49,12 @@ void CMapGenerator::loadConfig() for(auto& s : randomMapJson["terrain"]["undergroundAllow"].Vector()) { if(!s.isNull()) - config.terrainUndergroundAllowed.emplace_back(s.String()); + config.terrainUndergroundAllowed.emplace_back(VLC->terrainTypeHandler->getInfoByName(s.String())->id); } for(auto& s : randomMapJson["terrain"]["groundProhibit"].Vector()) { if(!s.isNull()) - config.terrainGroundProhibit.emplace_back(s.String()); + config.terrainGroundProhibit.emplace_back(VLC->terrainTypeHandler->getInfoByName(s.String())->id); } config.shipyardGuard = randomMapJson["waterZone"]["shipyard"]["value"].Integer(); for(auto & treasure : randomMapJson["waterZone"]["treasure"].Vector()) diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index 96c52ce98..fd4887e44 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -32,8 +32,8 @@ class DLL_LINKAGE CMapGenerator: public Load::Progress public: struct Config { - std::vector terrainUndergroundAllowed; - std::vector terrainGroundProhibit; + std::vector terrainUndergroundAllowed; + std::vector terrainGroundProhibit; std::vector waterTreasure; int shipyardGuard; int mineExtraResources; diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index 57077aca6..74a376508 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -67,12 +67,13 @@ class TerrainEncoder public: static si32 decode(const std::string & identifier) { - return vstd::find_pos(VLC->terrainTypeHandler::terrains(), identifier); + return VLC->terrainTypeHandler->getInfoByCode(identifier)->id; } static std::string encode(const si32 index) { - return (index >=0 && index < VLC->terrainTypeHandler::terrains().size()) ? static_cast(VLC->terrainTypeHandler::terrains()[index]) : ""; + const auto& terrains = VLC->terrainTypeHandler->terrains(); + return (index >=0 && index < terrains.size()) ? terrains[index]->name : ""; } }; @@ -149,9 +150,9 @@ ZoneOptions::ZoneOptions() terrainTypeLikeZone(NO_ZONE), treasureLikeZone(NO_ZONE) { - for(auto & terr : VLC->terrainTypeHandler::terrains()) - if(terr.isLand() && terr.isPassable()) - terrainTypes.insert(terr); + for(const auto * terr : VLC->terrainTypeHandler->terrains()) + if(terr->isLand() && terr->isPassable()) + terrainTypes.insert(terr->id); } ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other) @@ -214,12 +215,12 @@ boost::optional ZoneOptions::getOwner() const return owner; } -const std::set & ZoneOptions::getTerrainTypes() const +const std::set & ZoneOptions::getTerrainTypes() const { return terrainTypes; } -void ZoneOptions::setTerrainTypes(const std::set & value) +void ZoneOptions::setTerrainTypes(const std::set & value) { //assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() && // value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end()); @@ -374,7 +375,7 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler) terrainTypes.clear(); for(auto ttype : node.Vector()) { - terrainTypes.emplace(ttype.String()); + terrainTypes.emplace(VLC->terrainTypeHandler->getInfoByName(ttype.String())->id); } } } diff --git a/lib/rmg/CRmgTemplate.h b/lib/rmg/CRmgTemplate.h index 2637d8c5a..3007a9988 100644 --- a/lib/rmg/CRmgTemplate.h +++ b/lib/rmg/CRmgTemplate.h @@ -103,8 +103,8 @@ public: void setSize(int value); boost::optional getOwner() const; - const std::set & getTerrainTypes() const; - void setTerrainTypes(const std::set & value); + const std::set & getTerrainTypes() const; + void setTerrainTypes(const std::set & value); const CTownInfo & getPlayerTowns() const; const CTownInfo & getNeutralTowns() const; @@ -144,7 +144,7 @@ protected: CTownInfo playerTowns; CTownInfo neutralTowns; bool matchTerrainToTown; - std::set terrainTypes; + std::set terrainTypes; bool townsAreSameType; std::set townTypes; diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index 8200895a7..6a5fb8acb 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -191,14 +191,14 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const else { auto & tt = (*VLC->townh)[faction]->nativeTerrain; - if(tt == Terrain("dirt")) + if(tt == Terrain::DIRT) { //any / random zonesToPlace.push_back(zone); } else { - if(tt.isUnderground()) + if(VLC->terrainTypeHandler->terrains()[tt]->isUnderground()) { //underground zonesOnLevel[1]++; @@ -571,7 +571,7 @@ void CZonePlacer::assignZones(CRandomGenerator * rand) //make sure that terrain inside zone is not a rock //FIXME: reorder actions? - paintZoneTerrain(*zone.second, *rand, map, Terrain("subterra")); + paintZoneTerrain(*zone.second, *rand, map, Terrain::SUBTERRANEAN); } } logGlobal->info("Finished zone colouring"); diff --git a/lib/rmg/ConnectionsPlacer.cpp b/lib/rmg/ConnectionsPlacer.cpp index bd4633398..9886bf4c3 100644 --- a/lib/rmg/ConnectionsPlacer.cpp +++ b/lib/rmg/ConnectionsPlacer.cpp @@ -82,8 +82,9 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con //1. Try to make direct connection //Do if it's not prohibited by terrain settings - bool directProhibited = vstd::contains(Terrain::Manager::getInfo(zone.getTerrainType()).prohibitTransitions, otherZone->getTerrainType()) - || vstd::contains(Terrain::Manager::getInfo(otherZone->getTerrainType()).prohibitTransitions, zone.getTerrainType()); + const auto& terrains = VLC->terrainTypeHandler->terrains(); + bool directProhibited = vstd::contains(terrains[zone.getTerrainType()]->prohibitTransitions, otherZone->getTerrainType()) + || vstd::contains(terrains[otherZone->getTerrainType()]->prohibitTransitions, zone.getTerrainType()); auto directConnectionIterator = dNeighbourZones.find(otherZoneId); if(!directProhibited && directConnectionIterator != dNeighbourZones.end()) { diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 21dccf349..96ff11a6f 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -93,14 +93,14 @@ void createBorder(RmgMap & gen, Zone & zone) } } -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, const Terrain & terrainType) +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrain terrain) { auto v = zone.getArea().getTilesVector(); map.getEditManager()->getTerrainSelection().setSelection(v); - map.getEditManager()->drawTerrain(terrainType, &generator); + map.getEditManager()->drawTerrain(terrain, &generator); } -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, const Terrain & terrain) +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrain terrain) { auto factories = VLC->objtypeh->knownSubObjects(ObjID); vstd::erase_if(factories, [ObjID, &terrain](si32 f) @@ -116,10 +116,10 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) if(zone.getType()==ETemplateZoneType::WATER) { //collect all water terrain types - std::vector waterTerrains; - for(auto & terrain : VLC->terrainTypeHandler::terrains()) - if(terrain.isWater()) - waterTerrains.push_back(terrain); + std::vector waterTerrains; + for(auto & terrain : VLC->terrainTypeHandler->terrains()) + if(terrain->isWater()) + waterTerrains.push_back(terrain->id); zone.setTerrainType(*RandomGeneratorUtil::nextItem(waterTerrains, gen.rand)); } @@ -141,18 +141,19 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) if(!vstd::contains(gen.getConfig().terrainUndergroundAllowed, zone.getTerrainType())) { //collect all underground terrain types - std::vector undegroundTerrains; - for(auto & terrain : VLC->terrainTypeHandler::terrains()) - if(terrain.isUnderground()) - undegroundTerrains.push_back(terrain); + std::vector undegroundTerrains; + for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + if(terrain->isUnderground()) + undegroundTerrains.push_back(terrain->id); zone.setTerrainType(*RandomGeneratorUtil::nextItem(undegroundTerrains, gen.rand)); } } else { - if(vstd::contains(gen.getConfig().terrainGroundProhibit, zone.getTerrainType()) || zone.getTerrainType().isUnderground()) - zone.setTerrainType(Terrain("dirt")); + const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; + if(vstd::contains(gen.getConfig().terrainGroundProhibit, zone.getTerrainType()) || terrainType->isUnderground()) + zone.setTerrainType(Terrain::DIRT); } } } @@ -168,7 +169,7 @@ void createObstaclesCommon2(RmgMap & map, CRandomGenerator & generator) for(int y = 0; y < map.map().height; y++) { int3 tile(x, y, 1); - if(!map.map().getTile(tile).terType.isPassable()) + if(!map.map().getTile(tile).terType->isPassable()) { map.setOccupied(tile, ETileType::USED); } diff --git a/lib/rmg/Functions.h b/lib/rmg/Functions.h index 0be072e84..db340c3f7 100644 --- a/lib/rmg/Functions.h +++ b/lib/rmg/Functions.h @@ -40,9 +40,9 @@ rmg::Tileset collectDistantTiles(const Zone & zone, int distance); void createBorder(RmgMap & gen, Zone & zone); -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, const Terrain & terrainType); +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrain terrainType); void initTerrainType(Zone & zone, CMapGenerator & gen); -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, const Terrain & terrain); +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrain terrain); diff --git a/lib/rmg/RiverPlacer.cpp b/lib/rmg/RiverPlacer.cpp index 599c1cded..fd0a5ba6a 100644 --- a/lib/rmg/RiverPlacer.cpp +++ b/lib/rmg/RiverPlacer.cpp @@ -91,7 +91,7 @@ void RiverPlacer::init() void RiverPlacer::drawRivers() { map.getEditManager()->getTerrainSelection().setSelection(rivers.getTilesVector()); - map.getEditManager()->drawRiver(Terrain::Manager::getInfo(zone.getTerrainType()).river, &generator.rand); + map.getEditManager()->drawRiver(VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river, &generator.rand); } char RiverPlacer::dump(const int3 & t) @@ -200,7 +200,7 @@ void RiverPlacer::preprocess() //calculate delta positions if(connectedToWaterZoneId > -1) { - auto river = Terrain::Manager::getInfo(zone.getTerrainType()).river; + auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; auto & a = neighbourZonesTiles[connectedToWaterZoneId]; auto availableArea = zone.areaPossible() + zone.freePaths(); for(auto & tileToProcess : availableArea.getTilesVector()) @@ -326,7 +326,7 @@ void RiverPlacer::preprocess() void RiverPlacer::connectRiver(const int3 & tile) { - auto river = Terrain::Manager::getInfo(zone.getTerrainType()).river; + auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; if(river.empty() || river == RIVER_NAMES[0]) return; diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index 95c40acbb..e50f991b9 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -82,7 +82,7 @@ void RmgMap::initTiles(CMapGenerator & generator) getEditManager()->clearTerrain(&generator.rand); getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight())); - getEditManager()->drawTerrain(Terrain("grass"), &generator.rand); + getEditManager()->drawTerrain(Terrain::GRASS, &generator.rand); auto tmpl = mapGenOptions.getMapTemplate(); zones.clear(); diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index 9635daf53..a1f117559 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -103,13 +103,17 @@ void Object::Instance::setPositionRaw(const int3 & position) dObject.pos = dPosition + dParent.getPosition(); } -void Object::Instance::setTemplate(const Terrain & terrain) +void Object::Instance::setTemplate(const TTerrain & terrain) { if(dObject.appearance->id == Obj::NO_OBJ) { auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain); - if(templates.empty()) - throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % dObject.ID % dObject.subID % static_cast(terrain))); + auto terrainName = VLC->terrainTypeHandler->terrains()[terrain]->name; + if (templates.empty()) + { + throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % + dObject.ID % dObject.subID % terrainName)); + } dObject.appearance = templates.front(); } @@ -253,7 +257,7 @@ void Object::setPosition(const int3 & position) i.setPositionRaw(i.getPosition()); } -void Object::setTemplate(const Terrain & terrain) +void Object::setTemplate(const TTerrain & terrain) { for(auto& i : dInstances) i.setTemplate(terrain); @@ -289,11 +293,12 @@ void Object::Instance::finalize(RmgMap & map) if (dObject.appearance->id == Obj::NO_OBJ) { auto terrainType = map.map().getTile(getPosition(true)).terType; - auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType); + auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrainType->id); if (templates.empty()) - throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % dObject.ID % dObject.subID % getPosition(true).toString() % terrainType)); + throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") % + dObject.ID % dObject.subID % getPosition(true).toString() % terrainType->name)); - setTemplate(terrainType); + setTemplate(terrainType->id); } for(auto & tile : getBlockedArea().getTilesVector()) diff --git a/lib/rmg/RmgObject.h b/lib/rmg/RmgObject.h index e418631c3..7a72126c4 100644 --- a/lib/rmg/RmgObject.h +++ b/lib/rmg/RmgObject.h @@ -16,7 +16,6 @@ class CGObjectInstance; class RmgMap; -class Terrain; namespace rmg { class Object @@ -34,7 +33,7 @@ public: int3 getVisitablePosition() const; bool isVisitableFrom(const int3 & tile) const; const Area & getAccessibleArea() const; - void setTemplate(const Terrain & terrain); //cache invalidation + void setTemplate(const TTerrain & terrain); //cache invalidation int3 getPosition(bool isAbsolute = false) const; void setPosition(const int3 & position); //cache invalidation @@ -70,7 +69,7 @@ public: const int3 & getPosition() const; void setPosition(const int3 & position); - void setTemplate(const Terrain & terrain); + void setTemplate(const TTerrain & terrain); const Area & getArea() const; //lazy cache invalidation diff --git a/lib/rmg/RockPlacer.cpp b/lib/rmg/RockPlacer.cpp index 7688c690c..358a4269d 100644 --- a/lib/rmg/RockPlacer.cpp +++ b/lib/rmg/RockPlacer.cpp @@ -22,8 +22,8 @@ void RockPlacer::process() { - rockTerrain = Terrain::Manager::getInfo(zone.getTerrainType()).rockTerrain; - assert(!rockTerrain.isPassable()); + rockTerrain = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->rockTerrain; + assert(!VLC->terrainTypeHandler->terrains()[rockTerrain]->isPassable()); accessibleArea = zone.freePaths() + zone.areaUsed(); if(auto * m = zone.getModificator()) @@ -76,7 +76,7 @@ void RockPlacer::postProcess() //finally mark rock tiles as occupied, spawn no obstacles there rockArea = zone.area().getSubarea([this](const int3 & t) { - return !map.map().getTile(t).terType.isPassable(); + return !map.map().getTile(t).terType->isPassable(); }); zone.areaUsed().unite(rockArea); @@ -95,7 +95,7 @@ void RockPlacer::init() char RockPlacer::dump(const int3 & t) { - if(!map.map().getTile(t).terType.isPassable()) + if(!map.map().getTile(t).terType->isPassable()) { return zone.area().contains(t) ? 'R' : 'E'; } diff --git a/lib/rmg/RockPlacer.h b/lib/rmg/RockPlacer.h index c7217674f..1163a7cdd 100644 --- a/lib/rmg/RockPlacer.h +++ b/lib/rmg/RockPlacer.h @@ -26,5 +26,5 @@ public: protected: rmg::Area rockArea, accessibleArea; - Terrain rockTerrain; + TTerrain rockTerrain; }; diff --git a/lib/rmg/TileInfo.cpp b/lib/rmg/TileInfo.cpp index 9070333d3..d53281bac 100644 --- a/lib/rmg/TileInfo.cpp +++ b/lib/rmg/TileInfo.cpp @@ -61,14 +61,14 @@ ETileType::ETileType TileInfo::getTileType() const return occupied; } -Terrain TileInfo::getTerrainType() const +TTerrain TileInfo::getTerrainType() const { return terrain; } -void TileInfo::setTerrainType(Terrain value) +void TileInfo::setTerrainType(TTerrain type) { - terrain = value; + terrain = type; } void TileInfo::setRoadType(const std::string & value) diff --git a/lib/rmg/TileInfo.h b/lib/rmg/TileInfo.h index 30ed5d90f..b3a1da1cc 100644 --- a/lib/rmg/TileInfo.h +++ b/lib/rmg/TileInfo.h @@ -28,14 +28,14 @@ public: bool isUsed() const; bool isRoad() const; void setOccupied(ETileType::ETileType value); - Terrain getTerrainType() const; + TTerrain getTerrainType() const; ETileType::ETileType getTileType() const; - void setTerrainType(Terrain value); + void setTerrainType(TTerrain value); void setRoadType(const std::string & value); private: float nearestObjectDistance; ETileType::ETileType occupied; - Terrain terrain; + TTerrain terrain; std::string roadType; }; diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index cf1d58abb..801c6b994 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -811,7 +811,7 @@ ObjectInfo::ObjectInfo() } -void ObjectInfo::setTemplate(si32 type, si32 subtype, Terrain terrainType) +void ObjectInfo::setTemplate(si32 type, si32 subtype, TTerrain terrainType) { auto templHandler = VLC->objtypeh->getHandlerFor(type, subtype); if(!templHandler) diff --git a/lib/rmg/TreasurePlacer.h b/lib/rmg/TreasurePlacer.h index 457ef35a8..9d005b224 100644 --- a/lib/rmg/TreasurePlacer.h +++ b/lib/rmg/TreasurePlacer.h @@ -26,7 +26,7 @@ struct ObjectInfo //ui32 maxPerMap; //unused std::function generateObject; - void setTemplate(si32 type, si32 subtype, Terrain terrain); + void setTemplate(si32 type, si32 subtype, TTerrain terrain); ObjectInfo(); diff --git a/lib/rmg/WaterProxy.cpp b/lib/rmg/WaterProxy.cpp index 777cf8c11..8274fe491 100644 --- a/lib/rmg/WaterProxy.cpp +++ b/lib/rmg/WaterProxy.cpp @@ -51,7 +51,7 @@ void WaterProxy::process() for(auto & t : z.second->area().getTilesVector()) { - if(map.map().getTile(t).terType == zone.getTerrainType()) + if(map.map().getTile(t).terType->id == zone.getTerrainType()) { z.second->areaPossible().erase(t); z.second->area().erase(t); diff --git a/lib/rmg/Zone.cpp b/lib/rmg/Zone.cpp index 7323a27fd..6d0e42b1d 100644 --- a/lib/rmg/Zone.cpp +++ b/lib/rmg/Zone.cpp @@ -26,7 +26,7 @@ std::function AREA_NO_FILTER = [](const int3 & t) Zone::Zone(RmgMap & map, CMapGenerator & generator) : ZoneOptions(), townType(ETownType::NEUTRAL), - terrainType(Terrain("grass")), + terrainType(Terrain::GRASS), map(map), generator(generator) { @@ -132,12 +132,12 @@ void Zone::setTownType(si32 town) townType = town; } -const Terrain & Zone::getTerrainType() const +TTerrain Zone::getTerrainType() const { return terrainType; } -void Zone::setTerrainType(const Terrain & terrain) +void Zone::setTerrainType(TTerrain terrain) { terrainType = terrain; } diff --git a/lib/rmg/Zone.h b/lib/rmg/Zone.h index 3679506c5..78ab28182 100644 --- a/lib/rmg/Zone.h +++ b/lib/rmg/Zone.h @@ -98,8 +98,8 @@ public: si32 getTownType() const; void setTownType(si32 town); - const Terrain & getTerrainType() const; - void setTerrainType(const Terrain & terrain); + TTerrain getTerrainType() const; + void setTerrainType(TTerrain terrain); void connectPath(const rmg::Path & path); rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, std::function areafilter = AREA_NO_FILTER) const; @@ -138,6 +138,6 @@ protected: //template info si32 townType; - Terrain terrainType; + TTerrain terrainType; }; diff --git a/scripting/lua/api/BattleCb.cpp b/scripting/lua/api/BattleCb.cpp index 0f8127797..2d9c72f38 100644 --- a/scripting/lua/api/BattleCb.cpp +++ b/scripting/lua/api/BattleCb.cpp @@ -86,7 +86,7 @@ int BattleCbProxy::getTerrainType(lua_State * L) if(!S.tryGet(1, object)) return S.retVoid(); - return LuaStack::quickRetStr(L, object->battleTerrainType()); + return LuaStack::quickRetInt(L, object->battleTerrainType()); } int BattleCbProxy::getUnitByPos(lua_State * L) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 5dcd2dcea..a84540bbf 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1911,7 +1911,7 @@ void CGameHandler::newTurn() hth.id = h->id; auto ti = make_unique(h, 1); // TODO: this code executed when bonuses of previous day not yet updated (this happen in NewTurn::applyGs). See issue 2356 - hth.move = h->maxMovePointsCached(gs->map->getTile(h->getPosition(false)).terType.isLand(), ti.get()); + hth.move = h->maxMovePointsCached(gs->map->getTile(h->getPosition(false)).terType->isLand(), ti.get()); hth.mana = h->getManaNewTurn(); n.heroes.insert(hth); @@ -2217,9 +2217,9 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const battleResult.set(nullptr); const auto t = getTile(tile); - Terrain terrain = t->terType; + TTerrain terrain = t->terType->id; if (gs->map->isCoastalTile(tile)) //coastal tile is always ground - terrain = Terrain("sand"); + terrain = Terrain::SAND; BattleField terType = gs->battleGetBattlefieldType(tile, getRandomGenerator()); if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat) @@ -2316,7 +2316,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo const int3 guardPos = gs->guardingCreaturePosition(hmpos); const bool embarking = !h->boat && !t.visitableObjects.empty() && t.visitableObjects.back()->ID == Obj::BOAT; - const bool disembarking = h->boat && t.terType.isLand() && !t.blocked; + const bool disembarking = h->boat && t.terType->isLand() && !t.blocked; //result structure for start - movement failed, no move points used TryMoveHero tmh; @@ -2338,11 +2338,11 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo //it's a rock or blocked and not visitable tile //OR hero is on land and dest is water and (there is not present only one object - boat) - if (((!t.terType.isPassable() || (t.blocked && !t.visitable && !canFly)) + if (((!t.terType->isPassable() || (t.blocked && !t.visitable && !canFly)) && complain("Cannot move hero, destination tile is blocked!")) - || ((!h->boat && !canWalkOnSea && !canFly && t.terType.isWater() && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != Obj::BOAT && t.visitableObjects.back()->ID != Obj::HERO))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276) + || ((!h->boat && !canWalkOnSea && !canFly && t.terType->isWater() && (t.visitableObjects.size() < 1 || (t.visitableObjects.back()->ID != Obj::BOAT && t.visitableObjects.back()->ID != Obj::HERO))) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276) && complain("Cannot move hero, destination tile is on water!")) - || ((h->boat && t.terType.isLand() && t.blocked) + || ((h->boat && t.terType->isLand() && t.blocked) && complain("Cannot disembark hero, tile is blocked!")) || ((distance(h->pos, dst) >= 1.5 && !teleporting) && complain("Tiles are not neighboring!")) diff --git a/test/game/CGameStateTest.cpp b/test/game/CGameStateTest.cpp index 984cd6c02..6720bc766 100644 --- a/test/game/CGameStateTest.cpp +++ b/test/game/CGameStateTest.cpp @@ -193,7 +193,7 @@ public: const auto t = gameCallback->getTile(tile); - Terrain terrain = t->terType; + TTerrain terrain = t->terType->id; BattleField terType = BattleField::fromString("grass_hills"); //send info about battles diff --git a/test/map/CMapEditManagerTest.cpp b/test/map/CMapEditManagerTest.cpp index d028ac51f..7b8caefd9 100644 --- a/test/map/CMapEditManagerTest.cpp +++ b/test/map/CMapEditManagerTest.cpp @@ -33,30 +33,30 @@ TEST(MapManager, DrawTerrain_Type) // 1x1 Blow up editManager->getTerrainSelection().select(int3(5, 5, 0)); - editManager->drawTerrain(Terrain("grass")); + editManager->drawTerrain(Terrain::GRASS); static const int3 squareCheck[] = { int3(5,5,0), int3(5,4,0), int3(4,4,0), int3(4,5,0) }; for(int i = 0; i < ARRAY_COUNT(squareCheck); ++i) { - EXPECT_EQ(map->getTile(squareCheck[i]).terType, Terrain("grass")); + EXPECT_EQ(map->getTile(squareCheck[i]).terType->id, Terrain::GRASS); } // Concat to square editManager->getTerrainSelection().select(int3(6, 5, 0)); - editManager->drawTerrain(Terrain("grass")); - EXPECT_EQ(map->getTile(int3(6, 4, 0)).terType, Terrain("grass")); + editManager->drawTerrain(Terrain::GRASS); + EXPECT_EQ(map->getTile(int3(6, 4, 0)).terType->id, Terrain::GRASS); editManager->getTerrainSelection().select(int3(6, 5, 0)); - editManager->drawTerrain(Terrain("lava")); - EXPECT_EQ(map->getTile(int3(4, 4, 0)).terType, Terrain("grass")); - EXPECT_EQ(map->getTile(int3(7, 4, 0)).terType, Terrain("lava")); + editManager->drawTerrain(Terrain::LAVA); + EXPECT_EQ(map->getTile(int3(4, 4, 0)).terType->id, Terrain::GRASS); + EXPECT_EQ(map->getTile(int3(7, 4, 0)).terType->id, Terrain::LAVA); // Special case water,rock editManager->getTerrainSelection().selectRange(MapRect(int3(10, 10, 0), 10, 5)); - editManager->drawTerrain(Terrain("grass")); + editManager->drawTerrain(Terrain::GRASS); editManager->getTerrainSelection().selectRange(MapRect(int3(15, 17, 0), 10, 5)); - editManager->drawTerrain(Terrain("grass")); + editManager->drawTerrain(Terrain::GRASS); editManager->getTerrainSelection().select(int3(21, 16, 0)); - editManager->drawTerrain(Terrain("grass")); - EXPECT_EQ(map->getTile(int3(20, 15, 0)).terType, Terrain("grass")); + editManager->drawTerrain(Terrain::GRASS); + EXPECT_EQ(map->getTile(int3(20, 15, 0)).terType->id, Terrain::GRASS); // Special case non water,rock static const int3 diagonalCheck[] = { int3(31,42,0), int3(32,42,0), int3(32,43,0), int3(33,43,0), int3(33,44,0), @@ -66,17 +66,17 @@ TEST(MapManager, DrawTerrain_Type) { editManager->getTerrainSelection().select(diagonalCheck[i]); } - editManager->drawTerrain(Terrain("grass")); - EXPECT_EQ(map->getTile(int3(35, 44, 0)).terType, Terrain("water")); + editManager->drawTerrain(Terrain::GRASS); + EXPECT_EQ(map->getTile(int3(35, 44, 0)).terType->id, Terrain::WATER); // Rock case editManager->getTerrainSelection().selectRange(MapRect(int3(1, 1, 1), 15, 15)); - editManager->drawTerrain(Terrain("subterra")); + editManager->drawTerrain(Terrain::SUBTERRANEAN); std::vector vec({ int3(6, 6, 1), int3(7, 6, 1), int3(8, 6, 1), int3(5, 7, 1), int3(6, 7, 1), int3(7, 7, 1), int3(8, 7, 1), int3(4, 8, 1), int3(5, 8, 1), int3(6, 8, 1)}); editManager->getTerrainSelection().setSelection(vec); - editManager->drawTerrain(Terrain("rock")); - EXPECT_TRUE(!map->getTile(int3(5, 6, 1)).terType.isPassable() || !map->getTile(int3(7, 8, 1)).terType.isPassable()); + editManager->drawTerrain(Terrain::ROCK); + EXPECT_TRUE(!map->getTile(int3(5, 6, 1)).terType->isPassable() || !map->getTile(int3(7, 8, 1)).terType->isPassable()); //todo: add checks here and enable, also use smaller size #if 0 @@ -143,7 +143,7 @@ TEST(MapManager, DrawTerrain_View) int3 pos((si32)posVector[0].Float(), (si32)posVector[1].Float(), (si32)posVector[2].Float()); const auto & originalTile = originalMap->getTile(pos); editManager->getTerrainSelection().selectRange(MapRect(pos, 1, 1)); - editManager->drawTerrain(originalTile.terType, &gen); + editManager->drawTerrain(originalTile.terType->id, &gen); const auto & tile = map->getTile(pos); bool isInRange = false; for(const auto & range : mapping) diff --git a/test/mock/mock_IBattleInfoCallback.h b/test/mock/mock_IBattleInfoCallback.h index 688243ebd..0f3a42efd 100644 --- a/test/mock/mock_IBattleInfoCallback.h +++ b/test/mock/mock_IBattleInfoCallback.h @@ -17,7 +17,7 @@ class IBattleInfoCallbackMock : public IBattleInfoCallback { public: MOCK_CONST_METHOD0(getContextPool, scripting::Pool *()); - MOCK_CONST_METHOD0(battleTerrainType, Terrain()); + MOCK_CONST_METHOD0(battleTerrainType, TTerrain()); MOCK_CONST_METHOD0(battleGetBattlefieldType, BattleField()); MOCK_CONST_METHOD0(battleIsFinished, boost::optional()); diff --git a/test/mock/mock_battle_IBattleState.h b/test/mock/mock_battle_IBattleState.h index 12e3837c0..d71eb81eb 100644 --- a/test/mock/mock_battle_IBattleState.h +++ b/test/mock/mock_battle_IBattleState.h @@ -19,7 +19,7 @@ public: MOCK_CONST_METHOD1(getStacksIf, TStacks(TStackFilter)); MOCK_CONST_METHOD1(getUnitsIf, battle::Units(battle::UnitFilter)); MOCK_CONST_METHOD0(getBattlefieldType, BattleField()); - MOCK_CONST_METHOD0(getTerrainType, Terrain()); + MOCK_CONST_METHOD0(getTerrainType, TTerrain()); MOCK_CONST_METHOD0(getAllObstacles, IBattleInfo::ObstacleCList()); MOCK_CONST_METHOD0(getDefendedTown, const CGTownInstance *()); MOCK_CONST_METHOD1(getWallState, si8(int)); From 11e1bb44a2ae60a94c58bade7e713e36e5e590ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 13:43:00 +0200 Subject: [PATCH 03/74] Load sounds for new terrains later --- client/CMusicHandler.cpp | 14 +++++++++++--- client/CMusicHandler.h | 2 ++ client/CPlayerInterface.cpp | 4 ++++ lib/Terrain.cpp | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 955318be7..376994bbf 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -115,17 +115,21 @@ CSoundHandler::CSoundHandler(): {Terrain::WATER, soundBase::horseWater}, {Terrain::ROCK, soundBase::horseRock} }; +} + +void CSoundHandler::loadHorseSounds() +{ auto terrains = CGI->terrainTypeHandler->terrains(); for(const auto * terrain : terrains) { //since all sounds are hardcoded, let's keep it if(vstd::contains(horseSounds, terrain->id)) continue; - + //Use already existing horse sound horseSounds[terrain->id] = horseSounds.at(terrains[terrain->id]->horseSoundId); } -}; +} void CSoundHandler::init() { @@ -368,7 +372,11 @@ CMusicHandler::CMusicHandler(): addEntryToSet("enemy-turn", file.getName(), file.getName()); } - for(const auto * terrain : CGI->terrainTypeHandler->terrains()) +} + +void CMusicHandler::loadTerrainSounds() +{ + for (const auto* terrain : CGI->terrainTypeHandler->terrains()) { addEntryToSet("terrain", terrain->name, "Music/" + terrain->musicFilename); } diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index 03255f01a..d71005790 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -61,6 +61,7 @@ public: CSoundHandler(); void init() override; + void loadHorseSounds(); void release() override; void setVolume(ui32 percent) override; @@ -139,6 +140,7 @@ public: void addEntryToSet(const std::string & set, const std::string & entryID, const std::string & musicURI); void init() override; + void loadTerrainSounds(); void release() override; void setVolume(ui32 percent) override; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 5c8555e17..1b935c6ed 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -152,6 +152,10 @@ void CPlayerInterface::init(std::shared_ptr ENV, std::shared_ptrsoundh->loadHorseSounds(); + CCS->musich->loadTerrainSounds(); + initializeHeroTownList(); // always recreate advmap interface to avoid possible memory-corruption bugs diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 42011a3dc..7666f7b6a 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -96,7 +96,7 @@ TerrainTypeHandler::TerrainTypeHandler() } else { - info->horseSoundId = terr.second["horseSoundId"].Integer(); + info->horseSoundId = terr.second["horseSoundId"].Float(); } if(!terr.second["text"].isNull()) From c9c4603f754f80cb0e50adea4ef1cf2d2e5d8708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 13:43:57 +0200 Subject: [PATCH 04/74] Firts working version that launches original maps --- lib/Terrain.cpp | 12 +++++++----- lib/VCMI_Lib.cpp | 4 ++-- lib/mapObjects/CObjectClassesHandler.cpp | 23 +++++++++++++++-------- lib/mapObjects/ObjectTemplate.cpp | 11 +++++------ 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 7666f7b6a..ed57f076a 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -74,10 +74,10 @@ TerrainTypeHandler::TerrainTypeHandler() } else { - auto rockTerrainType = terr.second["rockTerrain"].String(); - resolveLater.push_back([this, rockTerrainType, info]() + auto rockTerrainName = terr.second["rockTerrain"].String(); + resolveLater.push_back([this, rockTerrainName, info]() { - info->rockTerrain = getInfoByName(rockTerrainType)->id; + info->rockTerrain = getInfoByName(rockTerrainName)->id; }); } @@ -159,6 +159,7 @@ TerrainTypeHandler::TerrainTypeHandler() id = objects.size(); objects.push_back(info); } + info->id = id; } } @@ -168,7 +169,8 @@ TerrainTypeHandler::TerrainTypeHandler() assert(objects(i)); } - //TODO: add ids to resolve + recreateTerrainMaps(); + for (auto& functor : resolveLater) { functor(); @@ -216,7 +218,7 @@ TerrainType::operator std::string() const } TerrainType::TerrainType(const std::string& _name): - name(name), + name(_name), id(Terrain::WRONG), rockTerrain(Terrain::ROCK), moveCost(100), diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 99477eaab..3d1b98a60 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -193,10 +193,10 @@ void LibClasses::init(bool onlyEssential) createHandler(bth, "Bonus type", pomtime); - createHandler(generaltexth, "General text", pomtime); - createHandler(terrainTypeHandler, "Terrain", pomtime); + createHandler(generaltexth, "General text", pomtime); + createHandler(heroh, "Hero", pomtime); createHandler(arth, "Artifact", pomtime); diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index d9474bd07..95caf0c14 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -484,15 +484,22 @@ void AObjectTypeHandler::init(const JsonNode & input, boost::optionalid = Obj(type); - tmpl->subid = subtype; - tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template? - tmpl->readJson(entry.second); - templates.push_back(std::shared_ptr(tmpl)); + auto tmpl = new ObjectTemplate; + tmpl->id = Obj(type); + tmpl->subid = subtype; + tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template? + tmpl->readJson(entry.second); + templates.push_back(std::shared_ptr(tmpl)); + } + catch (const std::exception & e) + { + logGlobal->warn("Failed to load terrains for object %s: %s", entry.first, e.what()); + } } if (input["name"].isNull()) diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 0d0be8980..05ff04cf9 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -282,25 +282,24 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) else visitDir = 0x00; - if(withTerrain && !node["allowedTerrains"].isNull()) + if (withTerrain && !node["allowedTerrains"].isNull()) { - for (auto & entry : node["allowedTerrains"].Vector()) + for (auto& entry : node["allowedTerrains"].Vector()) allowedTerrains.insert(VLC->terrainTypeHandler->getInfoByName(entry.String())->id); } else { - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for (const auto* terrain : VLC->terrainTypeHandler->terrains()) { - if(!terrain->isPassable() || terrain->isWater()) + if (!terrain->isPassable() || terrain->isWater()) continue; allowedTerrains.insert(terrain->id); } } - if(withTerrain && allowedTerrains.empty()) + if (withTerrain && allowedTerrains.empty()) logGlobal->warn("Loaded template without allowed terrains!"); - auto charToTile = [&](const char & ch) -> ui8 { switch (ch) From 97c17c62942a18d25d43f7172505a274c07c0ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 14:11:32 +0200 Subject: [PATCH 05/74] - Terrain config - Fix for underground terrains --- config/terrains.json | 1 + lib/Terrain.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/terrains.json b/config/terrains.json index 7699146b0..1b1a33c3e 100644 --- a/config/terrains.json +++ b/config/terrains.json @@ -103,6 +103,7 @@ "minimapBlocked" : [ 41, 40, 41 ], "music" : "Lava.mp3", "tiles" : "LAVATL", + "type" : "SUB", "code" : "lv", "river" : "rl", "battleFields" : ["lava"], diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index ed57f076a..56b6dcabb 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -267,7 +267,7 @@ bool TerrainType::isPassable() const bool TerrainType::isUnderground() const { - return passabilityType != PassabilityType::SUBTERRANEAN; + return passabilityType == PassabilityType::SUBTERRANEAN; } bool TerrainType::isTransitionRequired() const From fa31309eed595a57aaf3e1af2112fc7218b49a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 14:42:22 +0200 Subject: [PATCH 06/74] Fixed minimap colors --- client/widgets/AdventureMapClasses.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 55766a41c..92fa64b8c 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -391,7 +391,7 @@ const SDL_Color & CMinimapInstance::getTileColor(const int3 & pos) } // else - use terrain color (blocked version or normal) - auto colorPair = parent->colors.find(tile->terType->id)->second; + const auto & colorPair = parent->colors.find(tile->terType->id)->second; if (tile->blocked && (!tile->visitable)) return colorPair.second; else @@ -500,7 +500,7 @@ std::map > CMinimap::loadColors() { std::map > ret; - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto * terrain : CGI->terrainTypeHandler->terrains()) { SDL_Color normal = { From e53613caa71826204a5bb170b1d6c6b719f500c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 21 Sep 2022 21:44:39 +0200 Subject: [PATCH 07/74] Fixed crash in pathfinder --- lib/CPathfinder.cpp | 2 +- lib/CPathfinder.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 92e7ce265..1de179386 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1027,7 +1027,7 @@ TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn) { bonuses = hero->getAllBonuses(Selector::days(turn), Selector::all, nullptr, ""); bonusCache = make_unique(bonuses); - nativeTerrain = VLC->terrainTypeHandler->terrains()[hero->getNativeTerrain()]; + nativeTerrain = hero->getNativeTerrain(); } bool TurnInfo::isLayerAvailable(const EPathfindingLayer layer) const diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index fc12c853c..9bbd164a3 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -523,7 +523,7 @@ struct DLL_LINKAGE TurnInfo TConstBonusListPtr bonuses; mutable int maxMovePointsLand; mutable int maxMovePointsWater; - const TerrainType * nativeTerrain; + TTerrain nativeTerrain; TurnInfo(const CGHeroInstance * Hero, const int Turn = 0); bool isLayerAvailable(const EPathfindingLayer layer) const; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index f0038a696..4e9d83968 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -98,10 +98,9 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f break; } } - else if(ti->nativeTerrain->id != from.terType->id //the terrain is not native - && ti->nativeTerrain != nullptr //no special creature bonus - && !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType->id) //no special movement bonus - ) + else if(ti->nativeTerrain != from.terType->id &&//the terrain is not native + ti->nativeTerrain != Terrain::ANY_TERRAIN && //no special creature bonus + !ti->hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType->id)) //no special movement bonus { ret = VLC->heroh->terrCosts[from.terType->id]; @@ -128,7 +127,7 @@ TTerrain CGHeroInstance::getNativeTerrain() const if(stackNativeTerrain == Terrain::BORDER) //where does this value come from? continue; - if(nativeTerrain == Terrain::BORDER) //FIXME: this statement is always true + if(nativeTerrain == Terrain::BORDER) nativeTerrain = stackNativeTerrain; else if(nativeTerrain != stackNativeTerrain) return Terrain::BORDER; From 6aaf77812bf28db929ba050d7a0f4af2d433cb1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 22 Sep 2022 18:23:31 +0200 Subject: [PATCH 08/74] Changed logic for zone placement. Now every zone can be surface, underground, or both. This is separate from water <-> land distinction. Iand type is now a combination of flags and can take multiple values: "type": ["LAND", "WATER", "SURFACE", "SUB", "ROCK"]. In nothing is specified, terrains get LAND | SURFACE flags by default. Non-surface zones will default to DIRT, and non-underground zones will default to SUBTERRA. --- config/randomMap.json | 5 ----- config/terrains.json | 2 +- lib/Terrain.cpp | 39 +++++++++++++++++++++++++++++---------- lib/Terrain.h | 16 +++++++++------- lib/rmg/CMapGenerator.cpp | 11 +---------- lib/rmg/CMapGenerator.h | 2 -- lib/rmg/CZonePlacer.cpp | 5 +++-- lib/rmg/Functions.cpp | 26 +++++++++++--------------- 8 files changed, 54 insertions(+), 52 deletions(-) diff --git a/config/randomMap.json b/config/randomMap.json index e5c341c7a..926214ea2 100644 --- a/config/randomMap.json +++ b/config/randomMap.json @@ -1,9 +1,4 @@ { - "terrain" : - { - "undergroundAllow" : ["lava"], //others to be replaced by subterranena - "groundProhibit" : ["subterra"] //to be replaced by dirt - }, "waterZone" : { "treasure" : diff --git a/config/terrains.json b/config/terrains.json index 1b1a33c3e..149ca98c3 100644 --- a/config/terrains.json +++ b/config/terrains.json @@ -103,7 +103,7 @@ "minimapBlocked" : [ 41, 40, 41 ], "music" : "Lava.mp3", "tiles" : "LAVATL", - "type" : "SUB", + "type" : ["SUB", "SURFACE"], "code" : "lv", "river" : "rl", "battleFields" : ["lava"], diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 56b6dcabb..d3ebf9191 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -57,15 +57,29 @@ TerrainTypeHandler::TerrainTypeHandler() if(terr.second["type"].isNull()) { - info->passabilityType = TerrainType::PassabilityType::LAND; + info->passabilityType = TerrainType::PassabilityType::LAND | TerrainType::PassabilityType::SURFACE; } - else + else if (terr.second["type"].getType() == JsonNode::JsonType::DATA_VECTOR) + { + for (const auto& node : terr.second["type"].Vector()) + { + //Set bits + auto s = node.String(); + if (s == "LAND") info->passabilityType |= TerrainType::PassabilityType::LAND; + if (s == "WATER") info->passabilityType |= TerrainType::PassabilityType::WATER; + if (s == "ROCK") info->passabilityType |= TerrainType::PassabilityType::ROCK; + if (s == "SURFACE") info->passabilityType |= TerrainType::PassabilityType::SURFACE; + if (s == "SUB") info->passabilityType |= TerrainType::PassabilityType::SUBTERRANEAN; + } + } + else //should be string - one option only { auto s = terr.second["type"].String(); - if(s == "LAND") info->passabilityType = TerrainType::PassabilityType::LAND; - if(s == "WATER") info->passabilityType = TerrainType::PassabilityType::WATER; - if(s == "ROCK") info->passabilityType = TerrainType::PassabilityType::ROCK; - if(s == "SUB") info->passabilityType = TerrainType::PassabilityType::SUBTERRANEAN; + if (s == "LAND") info->passabilityType = TerrainType::PassabilityType::LAND; + if (s == "WATER") info->passabilityType = TerrainType::PassabilityType::WATER; + if (s == "ROCK") info->passabilityType = TerrainType::PassabilityType::ROCK; + if (s == "SURFACE") info->passabilityType = TerrainType::PassabilityType::SURFACE; + if (s == "SUB") info->passabilityType = TerrainType::PassabilityType::SUBTERRANEAN; } if(terr.second["rockTerrain"].isNull()) @@ -223,7 +237,7 @@ TerrainType::TerrainType(const std::string& _name): rockTerrain(Terrain::ROCK), moveCost(100), horseSoundId(0), - passabilityType(PassabilityType::LAND), + passabilityType(0), transitionRequired(false) { } @@ -257,17 +271,22 @@ bool TerrainType::isLand() const bool TerrainType::isWater() const { - return passabilityType == PassabilityType::WATER; + return passabilityType & PassabilityType::WATER; } bool TerrainType::isPassable() const { - return passabilityType != PassabilityType::ROCK; + return !(passabilityType & PassabilityType::ROCK); +} + +bool TerrainType::isSurface() const +{ + return passabilityType & PassabilityType::SURFACE; } bool TerrainType::isUnderground() const { - return passabilityType == PassabilityType::SUBTERRANEAN; + return passabilityType & PassabilityType::SUBTERRANEAN; } bool TerrainType::isTransitionRequired() const diff --git a/lib/Terrain.h b/lib/Terrain.h index ace2a74e2..1883a25fd 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -19,12 +19,13 @@ class DLL_LINKAGE TerrainType { public: - enum class PassabilityType + enum PassabilityType : ui8 { - LAND, - WATER, - SUBTERRANEAN, - ROCK + LAND = 1, + WATER = 2, + SURFACE = 4, + SUBTERRANEAN = 8, + ROCK = 16 }; std::vector battleFields; @@ -43,7 +44,7 @@ public: TTerrain rockTerrain; int moveCost; int horseSoundId; - PassabilityType passabilityType; + ui8 passabilityType; bool transitionRequired; TerrainType(const std::string & name = ""); @@ -56,7 +57,8 @@ public: bool isLand() const; bool isWater() const; - bool isPassable() const; //ROCK + bool isPassable() const; + bool isSurface() const; bool isUnderground() const; bool isTransitionRequired() const; diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 5edeb4da1..046cdf37a 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -46,16 +46,7 @@ void CMapGenerator::loadConfig() { static const ResourceID path("config/randomMap.json"); JsonNode randomMapJson(path); - for(auto& s : randomMapJson["terrain"]["undergroundAllow"].Vector()) - { - if(!s.isNull()) - config.terrainUndergroundAllowed.emplace_back(VLC->terrainTypeHandler->getInfoByName(s.String())->id); - } - for(auto& s : randomMapJson["terrain"]["groundProhibit"].Vector()) - { - if(!s.isNull()) - config.terrainGroundProhibit.emplace_back(VLC->terrainTypeHandler->getInfoByName(s.String())->id); - } + config.shipyardGuard = randomMapJson["waterZone"]["shipyard"]["value"].Integer(); for(auto & treasure : randomMapJson["waterZone"]["treasure"].Vector()) { diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index fd4887e44..59794f827 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -32,8 +32,6 @@ class DLL_LINKAGE CMapGenerator: public Load::Progress public: struct Config { - std::vector terrainUndergroundAllowed; - std::vector terrainGroundProhibit; std::vector waterTreasure; int shipyardGuard; int mineExtraResources; diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index 6a5fb8acb..e21d0e136 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -198,9 +198,10 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const } else { - if(VLC->terrainTypeHandler->terrains()[tt]->isUnderground()) + const auto * terrainType = VLC->terrainTypeHandler->terrains()[tt]; + if(terrainType->isUnderground() && !terrainType->isSurface()) { - //underground + //underground only zonesOnLevel[1]++; levels[zone.first] = 1; } diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 96ff11a6f..94932d391 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -134,26 +134,22 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) zone.setTerrainType(*RandomGeneratorUtil::nextItem(zone.getTerrainTypes(), gen.rand)); } + //Now, replace disallowed terrains on surface and in the underground //TODO: allow new types of terrain? + const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; + + if(zone.isUnderground()) { - if(zone.isUnderground()) + if(!terrainType->isUnderground()) { - if(!vstd::contains(gen.getConfig().terrainUndergroundAllowed, zone.getTerrainType())) - { - //collect all underground terrain types - std::vector undegroundTerrains; - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) - if(terrain->isUnderground()) - undegroundTerrains.push_back(terrain->id); - - zone.setTerrainType(*RandomGeneratorUtil::nextItem(undegroundTerrains, gen.rand)); - } + zone.setTerrainType(Terrain::SUBTERRANEAN); } - else + } + else + { + if (!terrainType->isSurface()) { - const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; - if(vstd::contains(gen.getConfig().terrainGroundProhibit, zone.getTerrainType()) || terrainType->isUnderground()) - zone.setTerrainType(Terrain::DIRT); + zone.setTerrainType(Terrain::DIRT); } } } From ebe45d512d7b81bff0ae4e1b538b656abb1e74de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Fri, 23 Sep 2022 16:24:01 +0200 Subject: [PATCH 09/74] Moved roads and rivers to TerrainTypeHandler, by analogy to TerrainType. --- client/mapHandler.cpp | 42 +++--- lib/GameConstants.h | 31 ++++- lib/Terrain.cpp | 139 +++++++++++++++++++- lib/Terrain.h | 69 +++++++++- lib/mapObjects/CGHeroInstance.cpp | 19 +-- lib/mapping/CDrawRoadsOperation.cpp | 16 +-- lib/mapping/CDrawRoadsOperation.h | 8 +- lib/mapping/CMap.cpp | 5 +- lib/mapping/CMapDefines.h | 4 +- lib/mapping/CMapEditManager.cpp | 4 +- lib/mapping/CMapEditManager.h | 4 +- lib/mapping/MapFormatH3M.cpp | 13 +- lib/mapping/MapFormatJson.cpp | 191 +++++++++++++++------------- lib/rmg/Functions.cpp | 1 - lib/rmg/RiverPlacer.cpp | 19 +-- lib/rmg/RmgMap.cpp | 2 +- lib/rmg/RmgMap.h | 2 +- lib/rmg/RoadPlacer.cpp | 3 +- lib/rmg/TileInfo.cpp | 6 +- lib/rmg/TileInfo.h | 4 +- 20 files changed, 392 insertions(+), 190 deletions(-) diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index fd84d274f..a631a8b29 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -135,22 +135,6 @@ EMapAnimRedrawStatus CMapHandler::drawTerrainRectNew(SDL_Surface * targetSurface void CMapHandler::initTerrainGraphics() { - static const std::map ROAD_FILES = - { - {ROAD_NAMES[1], "dirtrd"}, - {ROAD_NAMES[2], "gravrd"}, - {ROAD_NAMES[3], "cobbrd"} - }; - - static const std::map RIVER_FILES = - { - {RIVER_NAMES[1], "clrrvr"}, - {RIVER_NAMES[2], "icyrvr"}, - {RIVER_NAMES[3], "mudrvr"}, - {RIVER_NAMES[4], "lavrvr"} - }; - - auto loadFlipped = [](TFlippedAnimations & animation, TFlippedCache & cache, const std::map & files) { //no rotation and basic setup @@ -190,14 +174,24 @@ void CMapHandler::initTerrainGraphics() //TODO: use if as a key std::map terrainFiles; + std::map riverFiles; + std::map roadFiles; for(const auto * terrain : VLC->terrainTypeHandler->terrains()) { terrainFiles[terrain->name] = terrain->tilesFilename; } + for(const auto * river : VLC->terrainTypeHandler->rivers()) + { + riverFiles[river->fileName] = river->fileName; + } + for(const auto * road : VLC->terrainTypeHandler->roads()) + { + roadFiles[road->fileName] = road->fileName; + } loadFlipped(terrainAnimations, terrainImages, terrainFiles); - loadFlipped(roadAnimations, roadImages, ROAD_FILES); - loadFlipped(riverAnimations, riverImages, RIVER_FILES); + loadFlipped(riverAnimations, riverImages, riverFiles); + loadFlipped(roadAnimations, roadImages, roadFiles); // Create enough room for the whole map and its frame @@ -791,21 +785,21 @@ void CMapHandler::CMapBlitter::drawObjects(SDL_Surface * targetSurf, const Terra void CMapHandler::CMapBlitter::drawRoad(SDL_Surface * targetSurf, const TerrainTile & tinfo, const TerrainTile * tinfoUpper) const { - if (tinfoUpper && tinfoUpper->roadType != ROAD_NAMES[0]) + if (tinfoUpper && tinfoUpper->roadType->id != Road::NO_ROAD) { ui8 rotation = (tinfoUpper->extTileFlags >> 4) % 4; Rect source(0, tileSize / 2, tileSize, tileSize / 2); Rect dest(realPos.x, realPos.y, tileSize, tileSize / 2); - drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType][tinfoUpper->roadDir][rotation], + drawElement(EMapCacheType::ROADS, parent->roadImages[tinfoUpper->roadType->fileName][tinfoUpper->roadDir][rotation], &source, targetSurf, &dest); } - if(tinfo.roadType != ROAD_NAMES[0]) //print road from this tile + if(tinfo.roadType->id != Road::NO_ROAD) //print road from this tile { ui8 rotation = (tinfo.extTileFlags >> 4) % 4; Rect source(0, 0, tileSize, halfTileSizeCeil); Rect dest(realPos.x, realPos.y + tileSize / 2, tileSize, tileSize / 2); - drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType][tinfo.roadDir][rotation], + drawElement(EMapCacheType::ROADS, parent->roadImages[tinfo.roadType->fileName][tinfo.roadDir][rotation], &source, targetSurf, &dest); } } @@ -814,7 +808,7 @@ void CMapHandler::CMapBlitter::drawRiver(SDL_Surface * targetSurf, const Terrain { Rect destRect(realTileRect); ui8 rotation = (tinfo.extTileFlags >> 2) % 4; - drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect); + drawElement(EMapCacheType::RIVERS, parent->riverImages[tinfo.riverType->fileName][tinfo.riverDir][rotation], nullptr, targetSurf, &destRect); } void CMapHandler::CMapBlitter::drawFow(SDL_Surface * targetSurf) const @@ -865,7 +859,7 @@ void CMapHandler::CMapBlitter::blit(SDL_Surface * targetSurf, const MapDrawingIn if(isVisible || info->showAllTerrain) { drawTileTerrain(targetSurf, tinfo, tile); - if(tinfo.riverType != RIVER_NAMES[0]) + if(tinfo.riverType->id != River::NO_RIVER) drawRiver(targetSurf, tinfo); drawRoad(targetSurf, tinfo, tinfoUpper); } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index b3d01f462..41b10bd36 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -676,10 +676,6 @@ enum class ETeleportChannelType MIXED }; - -static std::vector RIVER_NAMES {"", "rw", "ri", "rm", "rl"}; -static std::vector ROAD_NAMES {"", "pd", "pg", "pc"}; - class Obj { public: @@ -855,6 +851,31 @@ namespace Terrain }; } +namespace Road +{ + enum ERoad : ui8 + { + NO_ROAD = 0, + DIRT_ROAD = 1, + GRAVEL_ROAD = 2, + COBBLESTONE_ROAD = 3, + ORIGINAL_ROAD_COUNT = COBBLESTONE_ROAD + }; +} + +namespace River +{ + enum ERiver : ui8 + { + NO_RIVER = 0, + WATER_RIVER = 1, + ICY_RIVER = 2, + MUD_RIVER = 3, + LAVA_RIVER = 4, + ORIGINAL_RIVER_COUNT = LAVA_RIVER + }; +} + namespace SecSkillLevel { enum SecSkillLevel @@ -1207,6 +1228,8 @@ typedef std::pair TDmgRange; typedef si32 TBonusSubtype; typedef si32 TQuantity; typedef si8 TTerrain; +typedef si8 TRoad; +typedef si8 TRiver; typedef int TRmgTemplateZoneId; diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index d3ebf9191..4127329bd 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -19,6 +19,9 @@ TerrainTypeHandler::TerrainTypeHandler() { + initRivers(); + initRoads(); + auto allConfigs = VLC->modh->getActiveMods(); allConfigs.insert(allConfigs.begin(), "core"); @@ -97,16 +100,16 @@ TerrainTypeHandler::TerrainTypeHandler() if(terr.second["river"].isNull()) { - info->river = RIVER_NAMES[0]; + info->river = River::NO_RIVER; } else { - info->river = terr.second["river"].String(); + info->river = getRiverByCode(terr.second["river"].String())->id; } if(terr.second["horseSoundId"].isNull()) { - info->horseSoundId = 9; //rock sound as default + info->horseSoundId = Terrain::ROCK; //rock sound as default } else { @@ -191,6 +194,61 @@ TerrainTypeHandler::TerrainTypeHandler() } } +void TerrainTypeHandler::initRivers() +{ + //TODO: load from file? + + const std::vector RIVER_DELTA_TEMPLATE_NAME + { + {""}, + {"clrdelt"}, + {"icedelt"}, + {"muddelt"}, + {"lavdelt"} + }; + + const std::vector> RIVER_CONSTANTS = + { + {"", ""}, + {"clrrvr", "rw"}, + {"icyrvr", "ri"}, + {"mudrvr", "rm"}, + {"lavrvr", "rl"} + }; + + for (size_t i = 0; i < std::size(RIVER_CONSTANTS); i++) + { + riverTypes.emplace_back(new RiverType(RIVER_CONSTANTS[i].first, RIVER_CONSTANTS[i].second, i)); + riverTypes[i]->deltaName = RIVER_DELTA_TEMPLATE_NAME[i]; + } + + recreateRiverMaps(); +} + +void TerrainTypeHandler::initRoads() +{ + //TODO: read from config + + const std::vector> ROAD_CONSTANTS = + { + {"", ""}, + {"dirtrd", "pd"}, + {"gravrd", "pg"}, + {"cobbrd", "pc"} + }; + + for (size_t i = 0; i < std::size(ROAD_CONSTANTS); i++) + { + roadTypes.emplace_back(new RoadType(ROAD_CONSTANTS[i].first, ROAD_CONSTANTS[i].second, i)); + } + + roadTypes[1]->movementCost = 75; + roadTypes[2]->movementCost = 65; + roadTypes[3]->movementCost = 50; + + recreateRoadMaps(); +} + void TerrainTypeHandler::recreateTerrainMaps() { for (const TerrainType * terrainInfo : objects) @@ -201,11 +259,41 @@ void TerrainTypeHandler::recreateTerrainMaps() } } +void TerrainTypeHandler::recreateRiverMaps() +{ + for (const RiverType * riverInfo : riverTypes) + { + riverInfoByName[riverInfo->fileName] = riverInfo; + riverInfoByCode[riverInfo->code] = riverInfo; + riverInfoById[riverInfo->id] = riverInfo; + } +} + +void TerrainTypeHandler::recreateRoadMaps() +{ + for (const RoadType * roadInfo : roadTypes) + { + roadInfoByName[roadInfo->fileName] = roadInfo; + roadInfoByCode[roadInfo->code] = roadInfo; + roadInfoById[roadInfo->id] = roadInfo; + } +} + const std::vector & TerrainTypeHandler::terrains() const { return objects; } +const std::vector& TerrainTypeHandler::rivers() const +{ + return riverTypes; +} + +const std::vector& TerrainTypeHandler::roads() const +{ + return roadTypes; +} + const TerrainType* TerrainTypeHandler::getInfoByName(const std::string& terrainName) const { return terrainInfoByName.at(terrainName); @@ -221,6 +309,36 @@ const TerrainType* TerrainTypeHandler::getInfoById(TTerrain id) const return terrainInfoById.at(id); } +const RiverType* TerrainTypeHandler::getRiverByName(const std::string& riverName) const +{ + return riverInfoByName.at(riverName); +} + +const RiverType* TerrainTypeHandler::getRiverByCode(const std::string& riverCode) const +{ + return riverInfoByCode.at(riverCode); +} + +const RiverType* TerrainTypeHandler::getRiverById(TRiver id) const +{ + return riverInfoById.at(id); +} + +const RoadType* TerrainTypeHandler::getRoadByName(const std::string& roadName) const +{ + return roadInfoByName.at(roadName); +} + +const RoadType* TerrainTypeHandler::getRoadByCode(const std::string& roadCode) const +{ + return roadInfoByCode.at(roadCode); +} + +const RoadType* TerrainTypeHandler::getRoadById(TRoad id) const +{ + return roadInfoById.at(id); +} + std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType) { return os << static_cast(terrainType); @@ -293,3 +411,18 @@ bool TerrainType::isTransitionRequired() const { return transitionRequired; } + +RiverType::RiverType(const std::string & fileName, const std::string & code, TRiver id): + fileName(fileName), + code(code), + id(id) +{ +} + +RoadType::RoadType(const std::string& fileName, const std::string& code, TRoad id): + fileName(fileName), + code(code), + id(id), + movementCost(GameConstants::BASE_MOVEMENT_COST) +{ +} \ No newline at end of file diff --git a/lib/Terrain.h b/lib/Terrain.h index 1883a25fd..eb6ff16c9 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -38,7 +38,7 @@ public: std::string terrainText; std::string typeCode; std::string terrainViewPatterns; - std::string river; + TRiver river; TTerrain id; TTerrain rockTerrain; @@ -87,6 +87,45 @@ public: } }; +class DLL_LINKAGE RiverType +{ +public: + + std::string fileName; + std::string code; + std::string deltaName; + TRiver id; + + RiverType(const std::string & fileName = "", const std::string& code = "", TRiver id = River::NO_RIVER); + + template void serialize(Handler& h, const int version) + { + h & fileName; + h & code; + h & deltaName; + h & id; + } +}; + +class DLL_LINKAGE RoadType +{ +public: + std::string fileName; + std::string code; + TRoad id; + ui8 movementCost; + + RoadType(const std::string & fileName = "", const std::string& code = "", TRoad id = Road::NO_ROAD); + + template void serialize(Handler& h, const int version) + { + h & fileName; + h & code; + h & id; + h & movementCost; + } +}; + DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const TerrainType & terrainType); class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? @@ -94,32 +133,58 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? public: TerrainTypeHandler(); + void initRivers(); + void initRoads(); const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; const TerrainType * getInfoByCode(const std::string & terrainCode) const; const TerrainType * getInfoById(TTerrain id) const; - //TODO: road, river types? + const std::vector & rivers() const; + const RiverType * getRiverByName(const std::string & riverName) const; + const RiverType * getRiverByCode(const std::string & riverCode) const; + const RiverType * getRiverById(TRiver id) const; + + const std::vector & roads() const; + const RoadType * getRoadByName(const std::string & roadName) const; + const RoadType * getRoadByCode(const std::string & roadCode) const; + const RoadType * getRoadById(TRoad id) const; template void serialize(Handler &h, const int version) { h & objects; + h & riverTypes; + h & roadTypes; if (!h.saving) { recreateTerrainMaps(); + recreateRiverMaps(); + recreateRoadMaps(); } } private: std::vector objects; + std::vector riverTypes; + std::vector roadTypes; std::unordered_map terrainInfoByName; std::unordered_map terrainInfoByCode; std::unordered_map terrainInfoById; + std::unordered_map riverInfoByName; + std::unordered_map riverInfoByCode; + std::unordered_map riverInfoById; + + std::unordered_map roadInfoByName; + std::unordered_map roadInfoByCode; + std::unordered_map roadInfoById; + void recreateTerrainMaps(); + void recreateRiverMaps(); + void recreateRoadMaps(); }; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 4e9d83968..861adc262 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -79,24 +79,9 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f int64_t ret = GameConstants::BASE_MOVEMENT_COST; //if there is road both on dest and src tiles - use road movement cost - if(dest.roadType != ROAD_NAMES[0] && from.roadType != ROAD_NAMES[0]) + if(dest.roadType->id && from.roadType->id) { - int roadPos = std::min(vstd::find_pos(ROAD_NAMES, dest.roadType), vstd::find_pos(ROAD_NAMES, from.roadType)); //used road ID - switch(roadPos) - { - case 1: - ret = 75; - break; - case 2: - ret = 65; - break; - case 3: - ret = 50; - break; - default: - logGlobal->error("Unknown road type: %d", roadPos); - break; - } + ret = std::max(dest.roadType->movementCost, from.roadType->movementCost); } else if(ti->nativeTerrain != from.terType->id &&//the terrain is not native ti->nativeTerrain != Terrain::ANY_TERRAIN && //no special creature bonus diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index d0dd1fff9..4f8bd0b24 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -156,14 +156,14 @@ CDrawLinesOperation::CDrawLinesOperation(CMap * map, const CTerrainSelection & t } ///CDrawRoadsOperation -CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen): +CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel,gen), roadType(roadType) { } ///CDrawRiversOperation -CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & riverType, CRandomGenerator * gen): +CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRiver riverType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel, gen), riverType(riverType) { @@ -336,12 +336,12 @@ std::string CDrawRiversOperation::getLabel() const void CDrawRoadsOperation::executeTile(TerrainTile & tile) { - tile.roadType = roadType; + tile.roadType = VLC->terrainTypeHandler->roads()[roadType]; } void CDrawRiversOperation::executeTile(TerrainTile & tile) { - tile.riverType = riverType; + tile.riverType = VLC->terrainTypeHandler->rivers()[riverType]; } bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const @@ -356,22 +356,22 @@ bool CDrawRiversOperation::canApplyPattern(const LinePattern & pattern) const bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const { - return tile.roadType != ROAD_NAMES[0]; + return tile.roadType->id != Road::NO_ROAD; } bool CDrawRiversOperation::needUpdateTile(const TerrainTile & tile) const { - return tile.riverType != RIVER_NAMES[0]; + return tile.riverType->id != River::NO_RIVER; } bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const { - return map->getTile(pos).roadType != ROAD_NAMES[0]; + return map->getTile(pos).roadType->id != Road::NO_ROAD; } bool CDrawRiversOperation::tileHasSomething(const int3& pos) const { - return map->getTile(pos).riverType != RIVER_NAMES[0]; + return map->getTile(pos).riverType->id != River::NO_RIVER; } void CDrawRoadsOperation::updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) diff --git a/lib/mapping/CDrawRoadsOperation.h b/lib/mapping/CDrawRoadsOperation.h index b283c5dc8..b614811f5 100644 --- a/lib/mapping/CDrawRoadsOperation.h +++ b/lib/mapping/CDrawRoadsOperation.h @@ -61,7 +61,7 @@ protected: class CDrawRoadsOperation : public CDrawLinesOperation { public: - CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen); + CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -72,13 +72,13 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - std::string roadType; + TRoad roadType; }; class CDrawRiversOperation : public CDrawLinesOperation { public: - CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, const std::string & roadType, CRandomGenerator * gen); + CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -89,5 +89,5 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - std::string riverType; + TRiver riverType; }; diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index b7c658d17..b47ba37b5 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -126,15 +126,14 @@ CCastleEvent::CCastleEvent() : town(nullptr) TerrainTile::TerrainTile(): terType(nullptr), terView(0), - riverType(RIVER_NAMES[0]), riverDir(0), - roadType(ROAD_NAMES[0]), roadDir(0), extTileFlags(0), visitable(false), blocked(false) { - + riverType = VLC->terrainTypeHandler->rivers()[0]; + roadType = VLC->terrainTypeHandler->roads()[0]; } bool TerrainTile::entrableTerrain(const TerrainTile * from) const diff --git a/lib/mapping/CMapDefines.h b/lib/mapping/CMapDefines.h index dc057be5b..8d02c4eff 100644 --- a/lib/mapping/CMapDefines.h +++ b/lib/mapping/CMapDefines.h @@ -82,9 +82,9 @@ struct DLL_LINKAGE TerrainTile TerrainType * terType; ui8 terView; - std::string riverType; + RiverType * riverType; ui8 riverDir; - std::string roadType; //TODO: switch to ui8 + RoadType * roadType; ui8 roadDir; /// first two bits - how to rotate terrain graphic (next two - river graphic, next two - road); /// 7th bit - whether tile is coastal (allows disembarking if land or block movement if water); 8th bit - Favorable Winds effect diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 09a23067c..3db91fda7 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -130,13 +130,13 @@ void CMapEditManager::drawTerrain(TTerrain terType, CRandomGenerator * gen) terrainSel.clearSelection(); } -void CMapEditManager::drawRoad(const std::string & roadType, CRandomGenerator* gen) +void CMapEditManager::drawRoad(TRoad roadType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, roadType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); } -void CMapEditManager::drawRiver(const std::string & riverType, CRandomGenerator* gen) +void CMapEditManager::drawRiver(TRiver riverType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, riverType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 99c84a011..970aab701 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -73,10 +73,10 @@ public: void drawTerrain(TTerrain terType, CRandomGenerator * gen = nullptr); /// Draws roads at the current terrain selection. The selection will be cleared automatically. - void drawRoad(const std::string & roadType, CRandomGenerator * gen = nullptr); + void drawRoad(TRoad roadType, CRandomGenerator * gen = nullptr); /// Draws rivers at the current terrain selection. The selection will be cleared automatically. - void drawRiver(const std::string & riverType, CRandomGenerator * gen = nullptr); + void drawRiver(TRiver riverType, CRandomGenerator * gen = nullptr); void insertObject(CGObjectInstance * obj); void insertObjects(std::set & objects); diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index c3a7c0df3..a2705dc20 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -922,16 +922,13 @@ void CMapLoaderH3M::readTerrain() { map->initTerrain(); const auto terrains = VLC->terrainTypeHandler->terrains(); + const auto rivers = VLC->terrainTypeHandler->rivers(); + const auto roads = VLC->terrainTypeHandler->roads(); // Read terrain int3 pos; - for(pos.z = 0; pos.z < 2; ++pos.z) + for(pos.z = 0; pos.z < map->levels(); ++pos.z) { - if(pos.z == 1 && !map->twoLevel) - { - break; - } - //OH3 format is [z][y][x] for(pos.y = 0; pos.y < map->height; pos.y++) { @@ -940,9 +937,9 @@ void CMapLoaderH3M::readTerrain() auto & tile = map->getTile(pos); tile.terType = terrains[reader.readUInt8()]; tile.terView = reader.readUInt8(); - tile.riverType = RIVER_NAMES[reader.readUInt8()]; + tile.riverType = rivers[reader.readUInt8()]; tile.riverDir = reader.readUInt8(); - tile.roadType = ROAD_NAMES[reader.readUInt8()]; + tile.roadType = roads[reader.readUInt8()]; tile.roadDir = reader.readUInt8(); tile.extTileFlags = reader.readUInt8(); tile.blocked = ((!tile.terType->isPassable() || tile.terType->id == Terrain::BORDER ) ? true : false); //underground tiles are always blocked diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 961721740..deb2fa031 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -942,96 +942,107 @@ void CMapLoaderJson::readHeader(const bool complete) void CMapLoaderJson::readTerrainTile(const std::string & src, TerrainTile & tile) { - using namespace TerrainDetail; - {//terrain type - const std::string typeCode = src.substr(0, 2); - tile.terType = const_cast(VLC->terrainTypeHandler->getInfoByCode(typeCode)); - } - int startPos = 2; //0+typeCode fixed length - {//terrain view - int pos = startPos; - while(isdigit(src.at(pos))) - pos++; - int len = pos - startPos; - if(len<=0) - throw std::runtime_error("Invalid terrain view in "+src); - const std::string rawCode = src.substr(startPos, len); - tile.terView = atoi(rawCode.c_str()); - startPos+=len; - } - {//terrain flip - int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++)); - if(terrainFlip < 0) - throw std::runtime_error("Invalid terrain flip in "+src); - else - tile.extTileFlags = terrainFlip; - } - if(startPos >= src.size()) - return; - bool hasRoad = true; - {//road type - const std::string typeCode = src.substr(startPos, 2); - startPos+=2; - if(vstd::find_pos(ROAD_NAMES, typeCode) < 0) - { - if(vstd::find_pos(RIVER_NAMES, typeCode) < 0) - throw std::runtime_error("Invalid river type in "+src); - else - { - tile.riverType = typeCode; - hasRoad = false; - } + try + { + using namespace TerrainDetail; + {//terrain type + const std::string typeCode = src.substr(0, 2); + tile.terType = const_cast(VLC->terrainTypeHandler->getInfoByCode(typeCode)); + } + int startPos = 2; //0+typeCode fixed length + {//terrain view + int pos = startPos; + while (isdigit(src.at(pos))) + pos++; + int len = pos - startPos; + if (len <= 0) + throw std::runtime_error("Invalid terrain view in " + src); + const std::string rawCode = src.substr(startPos, len); + tile.terView = atoi(rawCode.c_str()); + startPos += len; + } + {//terrain flip + int terrainFlip = vstd::find_pos(flipCodes, src.at(startPos++)); + if (terrainFlip < 0) + throw std::runtime_error("Invalid terrain flip in " + src); + else + tile.extTileFlags = terrainFlip; + } + if (startPos >= src.size()) + return; + bool hasRoad = true; + //FIXME: check without exceptions? + {//road type + const std::string typeCode = src.substr(startPos, 2); + startPos += 2; + try + { + tile.roadType = const_cast(VLC->terrainTypeHandler->getRoadByCode(typeCode)); + } + catch (const std::exception& e) //it's not a road, it's a river + { + try + { + tile.riverType = const_cast(VLC->terrainTypeHandler->getRiverByCode(typeCode)); + hasRoad = false; + } + catch (const std::exception& e) + { + throw std::runtime_error("Invalid river type in " + src); + } + + } + } + if (hasRoad) + {//road dir + int pos = startPos; + while (isdigit(src.at(pos))) + pos++; + int len = pos - startPos; + if (len <= 0) + throw std::runtime_error("Invalid road dir in " + src); + const std::string rawCode = src.substr(startPos, len); + tile.roadDir = atoi(rawCode.c_str()); + startPos += len; + } + if (hasRoad) + {//road flip + int flip = vstd::find_pos(flipCodes, src.at(startPos++)); + if (flip < 0) + throw std::runtime_error("Invalid road flip in " + src); + else + tile.extTileFlags |= (flip << 4); + } + if (startPos >= src.size()) + return; + if (hasRoad) + {//river type + const std::string typeCode = src.substr(startPos, 2); + startPos += 2; + tile.riverType = const_cast(VLC->terrainTypeHandler->getRiverByCode(typeCode)); + } + {//river dir + int pos = startPos; + while (isdigit(src.at(pos))) + pos++; + int len = pos - startPos; + if (len <= 0) + throw std::runtime_error("Invalid river dir in " + src); + const std::string rawCode = src.substr(startPos, len); + tile.riverDir = atoi(rawCode.c_str()); + startPos += len; + } + {//river flip + int flip = vstd::find_pos(flipCodes, src.at(startPos++)); + if (flip < 0) + throw std::runtime_error("Invalid road flip in " + src); + else + tile.extTileFlags |= (flip << 2); } - else - tile.roadType = typeCode; } - if(hasRoad) - {//road dir - int pos = startPos; - while(isdigit(src.at(pos))) - pos++; - int len = pos - startPos; - if(len<=0) - throw std::runtime_error("Invalid road dir in "+src); - const std::string rawCode = src.substr(startPos, len); - tile.roadDir = atoi(rawCode.c_str()); - startPos+=len; - } - if(hasRoad) - {//road flip - int flip = vstd::find_pos(flipCodes, src.at(startPos++)); - if(flip < 0) - throw std::runtime_error("Invalid road flip in "+src); - else - tile.extTileFlags |= (flip<<4); - } - if(startPos >= src.size()) - return; - if(hasRoad) - {//river type - const std::string typeCode = src.substr(startPos, 2); - startPos+=2; - if(vstd::find_pos(RIVER_NAMES, typeCode) < 0) - throw std::runtime_error("Invalid river type in "+src); - tile.riverType = typeCode; - } - {//river dir - int pos = startPos; - while(isdigit(src.at(pos))) - pos++; - int len = pos - startPos; - if(len<=0) - throw std::runtime_error("Invalid river dir in "+src); - const std::string rawCode = src.substr(startPos, len); - tile.riverDir = atoi(rawCode.c_str()); - startPos+=len; - } - {//river flip - int flip = vstd::find_pos(flipCodes, src.at(startPos++)); - if(flip < 0) - throw std::runtime_error("Invalid road flip in "+src); - else - tile.extTileFlags |= (flip<<2); + catch (const std::exception & e) + { + logGlobal->error("Failed to read terrain tile: %s"); } } @@ -1278,10 +1289,10 @@ std::string CMapSaverJson::writeTerrainTile(const TerrainTile & tile) out << tile.terType->typeCode << (int)tile.terView << flipCodes[tile.extTileFlags % 4]; - if(tile.roadType != ROAD_NAMES[0]) + if(tile.roadType->id != Road::NO_ROAD) out << tile.roadType << (int)tile.roadDir << flipCodes[(tile.extTileFlags >> 4) % 4]; - if(tile.riverType != RIVER_NAMES[0]) + if(tile.riverType->id != River::NO_RIVER) out << tile.riverType << (int)tile.riverDir << flipCodes[(tile.extTileFlags >> 2) % 4]; return out.str(); diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 94932d391..7d48e836d 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -135,7 +135,6 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) } //Now, replace disallowed terrains on surface and in the underground - //TODO: allow new types of terrain? const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; if(zone.isUnderground()) diff --git a/lib/rmg/RiverPlacer.cpp b/lib/rmg/RiverPlacer.cpp index fd0a5ba6a..0ce29b0e4 100644 --- a/lib/rmg/RiverPlacer.cpp +++ b/lib/rmg/RiverPlacer.cpp @@ -22,15 +22,9 @@ #include "WaterProxy.h" #include "RoadPlacer.h" +//TODO: move to Obj:: ? const int RIVER_DELTA_ID = 143; const int RIVER_DELTA_SUBTYPE = 0; -const std::map RIVER_DELTA_TEMPLATE_NAME -{ - {RIVER_NAMES[1], "clrdelt"}, - {RIVER_NAMES[2], "icedelt"}, - {RIVER_NAMES[3], "muddelt"}, - {RIVER_NAMES[4], "lavdelt"} -}; const std::array, 4> deltaTemplates { @@ -238,7 +232,7 @@ void RiverPlacer::preprocess() deltaOrientations[p] = templateId + 1; //specific case: deltas for ice rivers amd mud rivers are messed :( - if(river == RIVER_NAMES[2]) + if(river == River::ICY_RIVER) { switch(deltaOrientations[p]) { @@ -256,7 +250,7 @@ void RiverPlacer::preprocess() break; } } - if(river == RIVER_NAMES[3]) + if(river == River::MUD_RIVER) { switch(deltaOrientations[p]) { @@ -326,8 +320,9 @@ void RiverPlacer::preprocess() void RiverPlacer::connectRiver(const int3 & tile) { - auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; - if(river.empty() || river == RIVER_NAMES[0]) + auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; + auto river = VLC->terrainTypeHandler->rivers()[riverType]; + if(river->id == River::NO_RIVER) return; rmg::Area roads; @@ -386,7 +381,7 @@ void RiverPlacer::connectRiver(const int3 & tile) if(tmplates.size() % 4 != 0) throw rmgException(boost::to_string(boost::format("River templates for (%d,%d) at terrain %s, river %s are incorrect") % RIVER_DELTA_ID % RIVER_DELTA_SUBTYPE % zone.getTerrainType() % river)); - std::string targetTemplateName = RIVER_DELTA_TEMPLATE_NAME.at(river) + std::to_string(deltaOrientations[pos]) + ".def"; + std::string targetTemplateName = river->deltaName + std::to_string(deltaOrientations[pos]) + ".def"; for(auto & templ : tmplates) { if(templ->animationFile == targetTemplateName) diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index e50f991b9..132b613ec 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -229,7 +229,7 @@ void RmgMap::setOccupied(const int3 &tile, ETileType::ETileType state) tiles[tile.x][tile.y][tile.z].setOccupied(state); } -void RmgMap::setRoad(const int3& tile, const std::string & roadType) +void RmgMap::setRoad(const int3& tile, TRoad roadType) { assertOnMap(tile); diff --git a/lib/rmg/RmgMap.h b/lib/rmg/RmgMap.h index ab5be9b78..22612276d 100644 --- a/lib/rmg/RmgMap.h +++ b/lib/rmg/RmgMap.h @@ -44,7 +44,7 @@ public: bool isOnMap(const int3 & tile) const; void setOccupied(const int3 &tile, ETileType::ETileType state); - void setRoad(const int3 &tile, const std::string & roadType); + void setRoad(const int3 &tile, TRoad roadType); TileInfo getTile(const int3 & tile) const; diff --git a/lib/rmg/RoadPlacer.cpp b/lib/rmg/RoadPlacer.cpp index 8f605a0d6..25016c2e8 100644 --- a/lib/rmg/RoadPlacer.cpp +++ b/lib/rmg/RoadPlacer.cpp @@ -69,7 +69,8 @@ void RoadPlacer::drawRoads(bool secondary) zone.areaPossible().subtract(roads); zone.freePaths().unite(roads); map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector()); - std::string roadType = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType); + std::string roadCode = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType); + TRoad roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id; map.getEditManager()->drawRoad(roadType, &generator.rand); } diff --git a/lib/rmg/TileInfo.cpp b/lib/rmg/TileInfo.cpp index d53281bac..ba8a4eb35 100644 --- a/lib/rmg/TileInfo.cpp +++ b/lib/rmg/TileInfo.cpp @@ -44,7 +44,7 @@ bool TileInfo::isFree() const bool TileInfo::isRoad() const { - return roadType != ROAD_NAMES[0]; + return roadType != Road::NO_ROAD; } bool TileInfo::isUsed() const @@ -71,8 +71,8 @@ void TileInfo::setTerrainType(TTerrain type) terrain = type; } -void TileInfo::setRoadType(const std::string & value) +void TileInfo::setRoadType(TRoad type) { - roadType = value; + roadType = type; // setOccupied(ETileType::FREE); } diff --git a/lib/rmg/TileInfo.h b/lib/rmg/TileInfo.h index b3a1da1cc..46d0430e3 100644 --- a/lib/rmg/TileInfo.h +++ b/lib/rmg/TileInfo.h @@ -32,10 +32,10 @@ public: ETileType::ETileType getTileType() const; void setTerrainType(TTerrain value); - void setRoadType(const std::string & value); + void setRoadType(TRoad type); private: float nearestObjectDistance; ETileType::ETileType occupied; TTerrain terrain; - std::string roadType; + TRoad roadType; }; From 09931b6c9d5942f94827b9837581f2baeac28112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Fri, 23 Sep 2022 18:57:16 +0200 Subject: [PATCH 10/74] Moved roads and rivers to config files. This also allows adding new ones via mods. --- config/rivers.json | 30 ++++++++++++++ config/roads.json | 23 +++++++++++ lib/GameConstants.h | 4 +- lib/Terrain.cpp | 96 +++++++++++++++++++++++++++++---------------- 4 files changed, 117 insertions(+), 36 deletions(-) create mode 100644 config/rivers.json create mode 100644 config/roads.json diff --git a/config/rivers.json b/config/rivers.json new file mode 100644 index 000000000..1ff5e32c2 --- /dev/null +++ b/config/rivers.json @@ -0,0 +1,30 @@ +{ + "waterRiver": + { + "originalRiverId": 1, + "code": "rw", //must be 2 characters + "animation": "clrrvr", + "delta": "clrdelt" + }, + "iceRiver": + { + "originalRiverId": 2, + "code": "ri", + "animation": "icyrvr", + "delta": "icedelt" + }, + "mudRiver": + { + "originalRiverId": 3, + "code": "rm", + "animation": "mudrvr", + "delta": "muddelt" + }, + "lavaRiver": + { + "originalRiverId": 4, + "code": "rl", + "animation": "lavrvr", + "delta": "lavdelt" + } +} \ No newline at end of file diff --git a/config/roads.json b/config/roads.json new file mode 100644 index 000000000..48832d2e0 --- /dev/null +++ b/config/roads.json @@ -0,0 +1,23 @@ +{ + "dirtRoad": + { + "originalRoadId": 1, + "code": "pd", //must be 2 characters + "animation": "dirtrd", + "moveCost": 75 + }, + "gravelRoad": + { + "originalRoadId": 2, + "code": "pg", + "animation": "gravrd", + "moveCost": 65 + }, + "cobblestoneRoad": + { + "originalRoadId": 3, + "code": "pc", + "animation": "cobbrd", + "moveCost": 50 + } +} \ No newline at end of file diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 41b10bd36..f864cdd53 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -859,7 +859,7 @@ namespace Road DIRT_ROAD = 1, GRAVEL_ROAD = 2, COBBLESTONE_ROAD = 3, - ORIGINAL_ROAD_COUNT = COBBLESTONE_ROAD + ORIGINAL_ROAD_COUNT //+1 }; } @@ -872,7 +872,7 @@ namespace River ICY_RIVER = 2, MUD_RIVER = 3, LAVA_RIVER = 4, - ORIGINAL_RIVER_COUNT = LAVA_RIVER + ORIGINAL_RIVER_COUNT //+1 }; } diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 4127329bd..951797591 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -196,30 +196,38 @@ TerrainTypeHandler::TerrainTypeHandler() void TerrainTypeHandler::initRivers() { - //TODO: load from file? + auto allConfigs = VLC->modh->getActiveMods(); + allConfigs.insert(allConfigs.begin(), "core"); - const std::vector RIVER_DELTA_TEMPLATE_NAME - { - {""}, - {"clrdelt"}, - {"icedelt"}, - {"muddelt"}, - {"lavdelt"} - }; + riverTypes.resize(River::ORIGINAL_RIVER_COUNT, nullptr); //make space for original rivers + riverTypes[River::NO_RIVER] = new RiverType(); //default - const std::vector> RIVER_CONSTANTS = + for (auto & mod : allConfigs) { - {"", ""}, - {"clrrvr", "rw"}, - {"icyrvr", "ri"}, - {"mudrvr", "rm"}, - {"lavrvr", "rl"} - }; + if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/rivers.json"))) + continue; - for (size_t i = 0; i < std::size(RIVER_CONSTANTS); i++) - { - riverTypes.emplace_back(new RiverType(RIVER_CONSTANTS[i].first, RIVER_CONSTANTS[i].second, i)); - riverTypes[i]->deltaName = RIVER_DELTA_TEMPLATE_NAME[i]; + JsonNode rivs(mod, ResourceID("config/rivers.json")); + for (auto & river : rivs.Struct()) + { + auto * info = new RiverType(); + + info->fileName = river.second["animation"].String(); + info->code = river.second["code"].String(); + info->deltaName = river.second["delta"].String(); + //info->movementCost = river.second["moveCost"].Integer(); + + if (!river.second["originalRiverId"].isNull()) + { + info->id = static_cast(river.second["originalRiverId"].Float()); + riverTypes[info->id] = info; + } + else + { + info->id = riverTypes.size(); + riverTypes.push_back(info); + } + } } recreateRiverMaps(); @@ -227,24 +235,38 @@ void TerrainTypeHandler::initRivers() void TerrainTypeHandler::initRoads() { - //TODO: read from config + auto allConfigs = VLC->modh->getActiveMods(); + allConfigs.insert(allConfigs.begin(), "core"); - const std::vector> ROAD_CONSTANTS = - { - {"", ""}, - {"dirtrd", "pd"}, - {"gravrd", "pg"}, - {"cobbrd", "pc"} - }; + roadTypes.resize(Road::ORIGINAL_ROAD_COUNT, nullptr); //make space for original rivers + roadTypes[Road::NO_ROAD] = new RoadType(); //default - for (size_t i = 0; i < std::size(ROAD_CONSTANTS); i++) + for (auto & mod : allConfigs) { - roadTypes.emplace_back(new RoadType(ROAD_CONSTANTS[i].first, ROAD_CONSTANTS[i].second, i)); + if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/roads.json"))) + continue; + + JsonNode rds(mod, ResourceID("config/roads.json")); + for (auto & road : rds.Struct()) + { + auto * info = new RoadType(); + + info->fileName = road.second["animation"].String(); + info->code = road.second["code"].String(); + info->movementCost = static_cast(road.second["moveCost"].Float()); + + if (!road.second["originalRoadId"].isNull()) + { + info->id = static_cast(road.second["originalRoadId"].Float()); + roadTypes[info->id] = info; + } + else + { + info->id = roadTypes.size(); + roadTypes.push_back(info); + } + } } - - roadTypes[1]->movementCost = 75; - roadTypes[2]->movementCost = 65; - roadTypes[3]->movementCost = 50; recreateRoadMaps(); } @@ -263,6 +285,9 @@ void TerrainTypeHandler::recreateRiverMaps() { for (const RiverType * riverInfo : riverTypes) { + if (riverInfo->id == River::NO_RIVER) + continue; + riverInfoByName[riverInfo->fileName] = riverInfo; riverInfoByCode[riverInfo->code] = riverInfo; riverInfoById[riverInfo->id] = riverInfo; @@ -273,6 +298,9 @@ void TerrainTypeHandler::recreateRoadMaps() { for (const RoadType * roadInfo : roadTypes) { + if (roadInfo->id == Road::NO_ROAD) + continue; + roadInfoByName[roadInfo->fileName] = roadInfo; roadInfoByCode[roadInfo->code] = roadInfo; roadInfoById[roadInfo->id] = roadInfo; From f883395710ae48fa25e9355a0d93610c2c0466ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Fri, 23 Sep 2022 19:26:38 +0200 Subject: [PATCH 11/74] A little refactoring --- lib/Terrain.cpp | 22 +++++++++++----------- lib/Terrain.h | 5 +++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 951797591..e3902f000 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -19,12 +19,18 @@ TerrainTypeHandler::TerrainTypeHandler() { - initRivers(); - initRoads(); - auto allConfigs = VLC->modh->getActiveMods(); allConfigs.insert(allConfigs.begin(), "core"); + initRivers(allConfigs); + recreateRiverMaps(); + initRoads(allConfigs); + recreateRoadMaps(); + initTerrains(allConfigs); //maps will be populated inside +} + +void TerrainTypeHandler::initTerrains(const std::vector & allConfigs) +{ std::vector> resolveLater; objects.resize(Terrain::ORIGINAL_TERRAIN_COUNT, nullptr); //make space for original terrains @@ -194,11 +200,8 @@ TerrainTypeHandler::TerrainTypeHandler() } } -void TerrainTypeHandler::initRivers() +void TerrainTypeHandler::initRivers(const std::vector & allConfigs) { - auto allConfigs = VLC->modh->getActiveMods(); - allConfigs.insert(allConfigs.begin(), "core"); - riverTypes.resize(River::ORIGINAL_RIVER_COUNT, nullptr); //make space for original rivers riverTypes[River::NO_RIVER] = new RiverType(); //default @@ -233,11 +236,8 @@ void TerrainTypeHandler::initRivers() recreateRiverMaps(); } -void TerrainTypeHandler::initRoads() +void TerrainTypeHandler::initRoads(const std::vector & allConfigs) { - auto allConfigs = VLC->modh->getActiveMods(); - allConfigs.insert(allConfigs.begin(), "core"); - roadTypes.resize(Road::ORIGINAL_ROAD_COUNT, nullptr); //make space for original rivers roadTypes[Road::NO_ROAD] = new RoadType(); //default diff --git a/lib/Terrain.h b/lib/Terrain.h index eb6ff16c9..e222365b5 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -133,8 +133,9 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? public: TerrainTypeHandler(); - void initRivers(); - void initRoads(); + void initTerrains(const std::vector & allConfigs); + void initRivers(const std::vector & allConfigs); + void initRoads(const std::vector & allConfigs); const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; From 0b56778e00eeebc3373e91c66e84d26875d46692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Fri, 23 Sep 2022 20:01:54 +0200 Subject: [PATCH 12/74] Fix for compatibility in rewrite --- lib/rmg/ObstaclePlacer.cpp | 2 +- lib/rmg/ObstaclePlacer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rmg/ObstaclePlacer.cpp b/lib/rmg/ObstaclePlacer.cpp index 29fba34ab..bb4c7e042 100644 --- a/lib/rmg/ObstaclePlacer.cpp +++ b/lib/rmg/ObstaclePlacer.cpp @@ -24,7 +24,7 @@ #include "Functions.h" #include "../mapping/CMapEditManager.h" -void ObstacleProxy::collectPossibleObstacles(const Terrain & terrain) +void ObstacleProxy::collectPossibleObstacles(TTerrain terrain) { //get all possible obstacles for this terrain for(auto primaryID : VLC->objtypeh->knownObjects()) diff --git a/lib/rmg/ObstaclePlacer.h b/lib/rmg/ObstaclePlacer.h index b98d042aa..e61df728f 100644 --- a/lib/rmg/ObstaclePlacer.h +++ b/lib/rmg/ObstaclePlacer.h @@ -23,7 +23,7 @@ public: rmg::Area blockedArea; - void collectPossibleObstacles(const Terrain & terrain); + void collectPossibleObstacles(TTerrain terrain); void placeObstacles(CMap * map, CRandomGenerator & rand); From 659be89a0111f6d3e11abbe5ac8fdd81ec8040df Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 24 Sep 2022 16:12:02 +0300 Subject: [PATCH 13/74] remove setting values that are never read --- AI/Nullkiller/Analyzers/BuildAnalyzer.cpp | 4 ---- .../Pathfinding/Rules/AIMovementAfterDestinationRule.cpp | 1 - lib/CCreatureHandler.cpp | 2 +- lib/CStack.cpp | 1 + 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 72314e61d..378598d5e 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -205,8 +205,6 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( logAi->trace("checking %s", info.name); logAi->trace("buildInfo %s", info.toString()); - buildPtr = nullptr; - if(!town->hasBuilt(building)) { auto canBuild = ai->cb->canBuildStructure(town, building); @@ -239,8 +237,6 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( } else { - buildPtr = townInfo->buildings.at(building); - logAi->trace("cant build. Need %d", missingBuildings[0].num); BuildingInfo prerequisite = getBuildingOrPrerequisite(town, missingBuildings[0], excludeDwellingDependencies); diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp index 68aab0c35..225f139ca 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp @@ -147,7 +147,6 @@ namespace AIPathfinding return false; } - destinationNode = questNode.get(); destination.node = questNode.get(); nodeStorage->commit(destination, source); diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 709b40242..2d63a3540 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -1230,7 +1230,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars { if (b.type != Bonus::REBIRTH) b.val = 0; //on-off ability, no value specified - curVal = static_cast(parser.readNumber());// 0 level is never active + parser.readNumber(); // 0 level is never active for (int i = 1; i < 11; ++i) { curVal = static_cast(parser.readNumber()); diff --git a/lib/CStack.cpp b/lib/CStack.cpp index 64c5e98f8..3d472e393 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -304,6 +304,7 @@ std::vector CStack::meleeAttackHexes(const battle::Unit * attacker, c res.push_back(otherDefenderPos); } } + UNUSED(mask); return res; } From 97a94ce61ee78bef08771aec5f2c6df9d0ca37d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sun, 25 Sep 2022 08:04:15 +0200 Subject: [PATCH 14/74] Handle Tile by reference instead of pointer --- AI/VCAI/Pathfinding/AINodeStorage.cpp | 6 +++--- lib/CPathfinder.cpp | 6 +++--- lib/PathfinderUtil.h | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/AI/VCAI/Pathfinding/AINodeStorage.cpp b/AI/VCAI/Pathfinding/AINodeStorage.cpp index 1a0e08316..0b1b3fc70 100644 --- a/AI/VCAI/Pathfinding/AINodeStorage.cpp +++ b/AI/VCAI/Pathfinding/AINodeStorage.cpp @@ -43,11 +43,11 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta { for(pos.y=0; pos.y < sizes.y; ++pos.y) { - const TerrainTile * tile = &gs->map->getTile(pos); - if(!tile->terType->isPassable()) + const TerrainTile & tile = gs->map->getTile(pos); + if(!tile.terType->isPassable()) continue; - if(tile->terType->isWater()) + if(tile.terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 1de179386..e99cc13d4 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -45,8 +45,8 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState { for(pos.y=0; pos.y < sizes.y; ++pos.y) { - const TerrainTile * tile = &gs->map->getTile(pos); - if(tile->terType->isWater()) + const TerrainTile tile = gs->map->getTile(pos); + if(tile.terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) @@ -54,7 +54,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState if(useWaterWalking) resetTile(pos, ELayer::WATER, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); } - if(tile->terType->isLand()) + if(tile.terType->isLand()) { resetTile(pos, ELayer::LAND, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if(useFlying) diff --git a/lib/PathfinderUtil.h b/lib/PathfinderUtil.h index 063f97820..a2fb5898a 100644 --- a/lib/PathfinderUtil.h +++ b/lib/PathfinderUtil.h @@ -18,7 +18,7 @@ namespace PathfinderUtil using ELayer = EPathfindingLayer; template - CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, FoW fow, const PlayerColor player, const CGameState * gs) + CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile & tinfo, FoW fow, const PlayerColor player, const CGameState * gs) { if(!(*fow)[pos.z][pos.x][pos.y]) return CGPathNode::BLOCKED; @@ -27,15 +27,15 @@ namespace PathfinderUtil { case ELayer::LAND: case ELayer::SAIL: - if(tinfo->visitable) + if(tinfo.visitable) { - if(tinfo->visitableObjects.front()->ID == Obj::SANCTUARY && tinfo->visitableObjects.back()->ID == Obj::HERO && tinfo->visitableObjects.back()->tempOwner != player) //non-owned hero stands on Sanctuary + if(tinfo.visitableObjects.front()->ID == Obj::SANCTUARY && tinfo.visitableObjects.back()->ID == Obj::HERO && tinfo.visitableObjects.back()->tempOwner != player) //non-owned hero stands on Sanctuary { return CGPathNode::BLOCKED; } else { - for(const CGObjectInstance * obj : tinfo->visitableObjects) + for(const CGObjectInstance * obj : tinfo.visitableObjects) { if(obj->blockVisit) return CGPathNode::BLOCKVIS; @@ -46,7 +46,7 @@ namespace PathfinderUtil } } } - else if(tinfo->blocked) + else if(tinfo.blocked) { return CGPathNode::BLOCKED; } @@ -59,13 +59,13 @@ namespace PathfinderUtil break; case ELayer::WATER: - if(tinfo->blocked || tinfo->terType->isLand()) + if(tinfo.blocked || tinfo.terType->isLand()) return CGPathNode::BLOCKED; break; case ELayer::AIR: - if(tinfo->blocked || tinfo->terType->isLand()) + if(tinfo.blocked || tinfo.terType->isLand()) return CGPathNode::FLYABLE; break; From fd63cb6109322cd29be4acc09b048ae9e77d1fa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sun, 25 Sep 2022 08:07:22 +0200 Subject: [PATCH 15/74] and here --- AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 608e94d4f..44159791c 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -88,11 +88,11 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta { for(pos.y = 0; pos.y < sizes.y; ++pos.y) { - const TerrainTile* tile = &gs->map->getTile(pos); - if (!tile->terType->isPassable()) + const TerrainTile & tile = gs->map->getTile(pos); + if (!tile.terType->isPassable()) continue; - if (tile->terType->isWater()) + if (tile.terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); if (useFlying) From 0718acdb6d308243162e29f3de0cf6f4e331da32 Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Sat, 24 Sep 2022 23:50:31 -0700 Subject: [PATCH 16/74] Use tuple instead of vector for comparing values There are only 3 values, and they're only used for doing a comparison, so it's wasteful to create a whole vector for that. std::tuple is better suited for this use case. --- lib/mapObjects/CGHeroInstance.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 743af6b32..6993fc77a 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -840,11 +840,10 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b } else { - auto quality = [getCreatureID](std::shared_ptr pick) -> std::vector + auto quality = [getCreatureID](std::shared_ptr pick) -> std::tuple { const CCreature * c = VLC->creh->objects[getCreatureID(pick)]; - std::vector v = {c->level, static_cast(c->cost.marketValue()), -pick->additionalInfo[1]}; - return v; + return std::tuple {c->level, static_cast(c->cost.marketValue()), -pick->additionalInfo[1]}; }; if(quality(topPick) < quality(newPick)) topPick = newPick; From 72feb538cebd470951623d8e395ec40d6cc16e8b Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 24 Sep 2022 17:29:29 +0300 Subject: [PATCH 17/74] add explicit null pointer checks --- AI/Nullkiller/AIUtility.cpp | 3 +++ client/CPlayerInterface.cpp | 2 +- client/battle/CBattleAnimations.cpp | 2 +- client/windows/CKingdomInterface.cpp | 3 +++ lib/CPathfinder.cpp | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 55a2ad2cf..2f2a29fde 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -307,6 +307,9 @@ bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2 bool isWeeklyRevisitable(const CGObjectInstance * obj) { + if(!obj) + return false; + //TODO: allow polling of remaining creatures in dwelling if(dynamic_cast(obj)) // ensures future compatibility, unlike IDs return true; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 62463f048..2607c4d32 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1327,7 +1327,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town ) ki->townChanged(townObj); } } - else if (GH.listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1 + else if(town && GH.listInt.size() && (town->ID == Obj::CREATURE_GENERATOR1 || town->ID == Obj::CREATURE_GENERATOR4 || town->ID == Obj::WAR_MACHINE_FACTORY)) { CRecruitmentWindow *crw = dynamic_cast(GH.topInt().get()); diff --git a/client/battle/CBattleAnimations.cpp b/client/battle/CBattleAnimations.cpp index 2a7000340..b2516fa55 100644 --- a/client/battle/CBattleAnimations.cpp +++ b/client/battle/CBattleAnimations.cpp @@ -196,7 +196,7 @@ bool CDefenceAnimation::init() } //unit reversed - if(rangedAttack) //delay hit animation + if(rangedAttack && attacker != nullptr) //delay hit animation { for(std::list::const_iterator it = owner->projectiles.begin(); it != owner->projectiles.end(); ++it) { diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index 163cb3966..4e3a0aa5d 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -315,6 +315,9 @@ int InfoBoxHeroData::getSubID() si64 InfoBoxHeroData::getValue() { + if(!hero) + return 0; + switch(type) { case HERO_PRIMARY_SKILL: diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index 6ae919db0..98d58f7bf 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -463,7 +463,7 @@ std::vector CPathfinderHelper::getAllowedTeleportChannelExits(TeleportChan allowedExits.push_back(p); } } - else if(CGTeleport::isExitPassable(gs, hero, obj)) + else if(obj && CGTeleport::isExitPassable(gs, hero, obj)) allowedExits.push_back(obj->visitablePos()); } From 4ea57ea7fcd32dcb4287bd46f3ae60884240350e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sun, 25 Sep 2022 09:33:56 +0200 Subject: [PATCH 18/74] A variety of suggested style tweaks --- client/CMusicHandler.cpp | 4 +-- client/CMusicHandler.h | 2 +- client/CPlayerInterface.cpp | 4 +-- client/widgets/AdventureMapClasses.cpp | 4 +-- client/widgets/AdventureMapClasses.h | 4 +-- lib/CCreatureHandler.cpp | 4 +-- lib/CCreatureHandler.h | 4 +-- lib/CGeneralTextHandler.h | 2 +- lib/CHeroHandler.h | 2 +- lib/CPathfinder.h | 2 +- lib/CStack.cpp | 2 +- lib/CStack.h | 4 +-- lib/CTownHandler.cpp | 10 +++---- lib/CTownHandler.h | 10 +++---- lib/GameConstants.h | 6 ++--- lib/HeroBonus.cpp | 2 +- lib/HeroBonus.h | 4 +-- lib/NetPacksLib.cpp | 2 +- lib/ObstacleHandler.cpp | 2 +- lib/ObstacleHandler.h | 4 +-- lib/Terrain.cpp | 21 +++++++-------- lib/Terrain.h | 34 ++++++++++++------------ lib/battle/BattleInfo.cpp | 4 +-- lib/battle/BattleInfo.h | 6 ++--- lib/battle/BattleProxy.cpp | 2 +- lib/battle/BattleProxy.h | 2 +- lib/battle/CBattleInfoEssentials.cpp | 4 +-- lib/battle/CBattleInfoEssentials.h | 2 +- lib/battle/IBattleInfoCallback.h | 2 +- lib/battle/IBattleState.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 6 ++--- lib/mapObjects/CGHeroInstance.h | 2 +- lib/mapObjects/CObjectClassesHandler.cpp | 4 +-- lib/mapObjects/CObjectClassesHandler.h | 4 +-- lib/mapObjects/ObjectTemplate.cpp | 14 +++++----- lib/mapObjects/ObjectTemplate.h | 4 +-- lib/mapping/CDrawRoadsOperation.cpp | 4 +-- lib/mapping/CDrawRoadsOperation.h | 8 +++--- lib/mapping/CMapEditManager.cpp | 6 ++--- lib/mapping/CMapEditManager.h | 6 ++--- lib/mapping/CMapOperation.cpp | 2 +- lib/mapping/CMapOperation.h | 4 +-- lib/mapping/MapEditUtils.cpp | 4 +-- lib/mapping/MapEditUtils.h | 4 +-- lib/rmg/CRmgTemplate.cpp | 4 +-- lib/rmg/CRmgTemplate.h | 6 ++--- lib/rmg/Functions.cpp | 6 ++--- lib/rmg/Functions.h | 4 +-- lib/rmg/ObstaclePlacer.cpp | 2 +- lib/rmg/ObstaclePlacer.h | 2 +- lib/rmg/RmgMap.cpp | 2 +- lib/rmg/RmgMap.h | 2 +- lib/rmg/RmgObject.cpp | 4 +-- lib/rmg/RmgObject.h | 4 +-- lib/rmg/RoadPlacer.cpp | 2 +- lib/rmg/RockPlacer.h | 2 +- lib/rmg/TileInfo.cpp | 6 ++--- lib/rmg/TileInfo.h | 10 +++---- lib/rmg/TreasurePlacer.cpp | 2 +- lib/rmg/TreasurePlacer.h | 2 +- lib/rmg/Zone.cpp | 4 +-- lib/rmg/Zone.h | 6 ++--- server/CGameHandler.cpp | 4 +-- test/game/CGameStateTest.cpp | 4 +-- test/mock/mock_IBattleInfoCallback.h | 2 +- test/mock/mock_battle_IBattleState.h | 2 +- 66 files changed, 155 insertions(+), 156 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 376994bbf..473b2cc1a 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -119,7 +119,7 @@ CSoundHandler::CSoundHandler(): void CSoundHandler::loadHorseSounds() { - auto terrains = CGI->terrainTypeHandler->terrains(); + const auto & terrains = CGI->terrainTypeHandler->terrains(); for(const auto * terrain : terrains) { //since all sounds are hardcoded, let's keep it @@ -376,7 +376,7 @@ CMusicHandler::CMusicHandler(): void CMusicHandler::loadTerrainSounds() { - for (const auto* terrain : CGI->terrainTypeHandler->terrains()) + for (const auto * terrain : CGI->terrainTypeHandler->terrains()) { addEntryToSet("terrain", terrain->name, "Music/" + terrain->musicFilename); } diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index d71005790..401185b5f 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -84,7 +84,7 @@ public: // Sets std::vector pickupSounds; std::vector battleIntroSounds; - std::map horseSounds; + std::map horseSounds; }; // Helper //now it looks somewhat useless diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 1b935c6ed..7cf8463d3 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2746,8 +2746,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path) { path.convert(0); - TTerrain currentTerrain = Terrain::BORDER; // not init yet - TTerrain newTerrain; + TTerrainId currentTerrain = Terrain::BORDER; // not init yet + TTerrainId newTerrain; int sh = -1; auto canStop = [&](CGPathNode * node) -> bool diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 6553bc1d4..5aa52c64f 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -495,9 +495,9 @@ void CMinimapInstance::showAll(SDL_Surface * to) } } -std::map > CMinimap::loadColors() +std::map > CMinimap::loadColors() { - std::map > ret; + std::map > ret; for(const auto * terrain : CGI->terrainTypeHandler->terrains()) { diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index 75540c81a..50bb0137c 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -217,7 +217,7 @@ protected: int level; //to initialize colors - std::map > loadColors(); + std::map > loadColors(); void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; @@ -228,7 +228,7 @@ protected: public: // terrainID -> (normal color, blocked color) - const std::map > colors; + const std::map > colors; CMinimap(const Rect & position); diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 3aeb8706d..af2a3d45f 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -283,13 +283,13 @@ std::string CCreature::nodeName() const return "\"" + namePl + "\""; } -bool CCreature::isItNativeTerrain(TTerrain terrain) const +bool CCreature::isItNativeTerrain(TTerrainId terrain) const { auto native = getNativeTerrain(); return native == terrain || native == Terrain::ANY_TERRAIN; } -TTerrain CCreature::getNativeTerrain() const +TTerrainId CCreature::getNativeTerrain() const { const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY"; static const auto selectorNoTerrainPenalty = Selector::type()(Bonus::NO_TERRAIN_PENALTY); diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index d64803fb9..10122a618 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -119,14 +119,14 @@ public: ArtifactID warMachine; - bool isItNativeTerrain(TTerrain terrain) const; + bool isItNativeTerrain(TTerrainId terrain) const; /** Returns creature native terrain considering some terrain bonuses. @param considerBonus is used to avoid Dead Lock when this method is called inside getAllBonuses considerBonus = true is called from Pathfinder and fills actual nativeTerrain considering bonus(es). considerBonus = false is called on Battle init and returns already prepared nativeTerrain without Bonus system calling. */ - TTerrain getNativeTerrain() const; + TTerrainId getNativeTerrain() const; int32_t getIndex() const override; int32_t getIconIndex() const override; const std::string & getName() const override; diff --git a/lib/CGeneralTextHandler.h b/lib/CGeneralTextHandler.h index 97a7010e1..20dc8abaa 100644 --- a/lib/CGeneralTextHandler.h +++ b/lib/CGeneralTextHandler.h @@ -122,7 +122,7 @@ public: std::vector advobtxt; std::vector xtrainfo; std::vector restypes; //names of resources - std::map terrainNames; + std::map terrainNames; std::vector randsign; std::vector> mines; //first - name; second - event description std::vector seerEmpty; diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index 418439eab..37e2dc9fc 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -265,7 +265,7 @@ public: CHeroClassHandler classes; //default costs of going through terrains. -1 means terrain is impassable - std::map terrCosts; + std::map terrCosts; struct SBallisticsLevelInfo { diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 3e02f1457..a00c251d7 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -527,7 +527,7 @@ struct DLL_LINKAGE TurnInfo TConstBonusListPtr bonuses; mutable int maxMovePointsLand; mutable int maxMovePointsWater; - TTerrain nativeTerrain; + TTerrainId nativeTerrain; TurnInfo(const CGHeroInstance * Hero, const int Turn = 0); bool isLayerAvailable(const EPathfindingLayer layer) const; diff --git a/lib/CStack.cpp b/lib/CStack.cpp index 7abb32067..29657c7dc 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -332,7 +332,7 @@ bool CStack::isOnNativeTerrain() const return res; } -bool CStack::isOnTerrain(TTerrain terrain) const +bool CStack::isOnTerrain(TTerrainId terrain) const { return battle->getTerrainType() == terrain; } diff --git a/lib/CStack.h b/lib/CStack.h index 09109e1ec..5d4cc9fd5 100644 --- a/lib/CStack.h +++ b/lib/CStack.h @@ -29,7 +29,7 @@ public: ui32 ID; //unique ID of stack const CCreature * type; - TTerrain nativeTerrain; //tmp variable to save native terrain value on battle init + TTerrainId nativeTerrain; //tmp variable to save native terrain value on battle init ui32 baseAmount; PlayerColor owner; //owner - player color (255 for neutrals) @@ -51,7 +51,7 @@ public: bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines bool isOnNativeTerrain() const; - bool isOnTerrain(TTerrain terrain) const; + bool isOnTerrain(TTerrainId terrain) const; ui32 level() const; si32 magicResistance() const override; //include aura of resistance diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 88be8b956..1b9b4697b 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -26,9 +26,9 @@ const int NAMES_PER_TOWN=16; // number of town names per faction in H3 files. Json can define any number -const TTerrain CTownHandler::defaultGoodTerrain(Terrain::GRASS); -const TTerrain CTownHandler::defaultEvilTerrain(Terrain::LAVA); -const TTerrain CTownHandler::defaultNeutralTerrain(Terrain::ROUGH); +const TTerrainId CTownHandler::defaultGoodTerrain(Terrain::GRASS); +const TTerrainId CTownHandler::defaultEvilTerrain(Terrain::LAVA); +const TTerrainId CTownHandler::defaultNeutralTerrain(Terrain::ROUGH); const std::map CBuilding::MODES = { @@ -942,9 +942,9 @@ void CTownHandler::loadPuzzle(CFaction &faction, const JsonNode &source) assert(faction.puzzleMap.size() == GameConstants::PUZZLE_MAP_PIECES); } -TTerrain CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const +TTerrainId CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const { - TTerrain terrain = defaultGoodTerrain; + TTerrainId terrain = defaultGoodTerrain; switch(alignment) { diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 52f56e323..47b52cbb0 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -185,7 +185,7 @@ public: TFaction index; - TTerrain nativeTerrain; + TTerrainId nativeTerrain; EAlignment::EAlignment alignment; bool preferUndergroundPlacement; @@ -358,9 +358,9 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase requirementsToLoad; std::vector overriddenBidsToLoad; //list of buildings, which bonuses should be overridden. - const static TTerrain defaultGoodTerrain; - const static TTerrain defaultEvilTerrain; - const static TTerrain defaultNeutralTerrain; + const static TTerrainId defaultGoodTerrain; + const static TTerrainId defaultEvilTerrain; + const static TTerrainId defaultNeutralTerrain; static TPropagatorPtr & emptyPropagator(); @@ -391,7 +391,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase TDmgRange; typedef si32 TBonusSubtype; typedef si32 TQuantity; -typedef si8 TTerrain; -typedef si8 TRoad; -typedef si8 TRiver; +typedef si8 TTerrainId; +typedef si8 TRoadId; +typedef si8 TRiverId; typedef int TRmgTemplateZoneId; diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 042c0f526..6eb9e9813 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -2111,7 +2111,7 @@ CreatureTerrainLimiter::CreatureTerrainLimiter() { } -CreatureTerrainLimiter::CreatureTerrainLimiter(TTerrain terrain): +CreatureTerrainLimiter::CreatureTerrainLimiter(TTerrainId terrain): terrainType(terrain) { } diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index f1ff8a950..23a7d3052 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -1060,9 +1060,9 @@ public: class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain { public: - TTerrain terrainType; + TTerrainId terrainType; CreatureTerrainLimiter(); - CreatureTerrainLimiter(TTerrain terrain); + CreatureTerrainLimiter(TTerrainId terrain); int limit(const BonusLimitationContext &context) const override; virtual std::string toString() const override; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 5024a0d09..78df665db 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -701,7 +701,7 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs) DLL_LINKAGE void NewObject::applyGs(CGameState *gs) { - TTerrain terrainType = Terrain::BORDER; + TTerrainId terrainType = Terrain::BORDER; if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not { diff --git a/lib/ObstacleHandler.cpp b/lib/ObstacleHandler.cpp index 69918e64e..a4ac99360 100644 --- a/lib/ObstacleHandler.cpp +++ b/lib/ObstacleHandler.cpp @@ -66,7 +66,7 @@ std::vector ObstacleInfo::getBlocked(BattleHex hex) const return ret; } -bool ObstacleInfo::isAppropriate(const TTerrain terrainType, const BattleField & battlefield) const +bool ObstacleInfo::isAppropriate(const TTerrainId terrainType, const BattleField & battlefield) const { auto bgInfo = battlefield.getInfo(); diff --git a/lib/ObstacleHandler.h b/lib/ObstacleHandler.h index e870265c9..4e9e03dcd 100644 --- a/lib/ObstacleHandler.h +++ b/lib/ObstacleHandler.h @@ -31,7 +31,7 @@ public: si32 iconIndex; std::string identifier; std::string appearAnimation, animation, dissapearAnimation; - std::vector allowedTerrains; + std::vector allowedTerrains; std::vector allowedSpecialBfields; //TODO: here is extra field to implement it's logic in the future but save backward compatibility @@ -50,7 +50,7 @@ public: std::vector getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex' - bool isAppropriate(const TTerrain terrainType, const BattleField & specialBattlefield) const; + bool isAppropriate(const TTerrainId terrainType, const BattleField & specialBattlefield) const; template void serialize(Handler &h, const int version) { diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index e3902f000..6dfa102bc 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -169,11 +169,11 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig info->terrainViewPatterns = terr.second["terrainViewPatterns"].String(); } - TTerrain id = Terrain::WRONG; + TTerrainId id = Terrain::WRONG; if(!terr.second["originalTerrainId"].isNull()) { //place in reserved slot - id = (TTerrain)(terr.second["originalTerrainId"].Float()); + id = (TTerrainId)(terr.second["originalTerrainId"].Float()); objects[id] = info; } else @@ -222,7 +222,7 @@ void TerrainTypeHandler::initRivers(const std::vector & allConfigs) if (!river.second["originalRiverId"].isNull()) { - info->id = static_cast(river.second["originalRiverId"].Float()); + info->id = static_cast(river.second["originalRiverId"].Float()); riverTypes[info->id] = info; } else @@ -257,7 +257,7 @@ void TerrainTypeHandler::initRoads(const std::vector & allConfigs) if (!road.second["originalRoadId"].isNull()) { - info->id = static_cast(road.second["originalRoadId"].Float()); + info->id = static_cast(road.second["originalRoadId"].Float()); roadTypes[info->id] = info; } else @@ -332,7 +332,7 @@ const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainC return terrainInfoByCode.at(terrainCode); } -const TerrainType* TerrainTypeHandler::getInfoById(TTerrain id) const +const TerrainType* TerrainTypeHandler::getInfoById(TTerrainId id) const { return terrainInfoById.at(id); } @@ -347,7 +347,7 @@ const RiverType* TerrainTypeHandler::getRiverByCode(const std::string& riverCode return riverInfoByCode.at(riverCode); } -const RiverType* TerrainTypeHandler::getRiverById(TRiver id) const +const RiverType* TerrainTypeHandler::getRiverById(TRiverId id) const { return riverInfoById.at(id); } @@ -362,7 +362,7 @@ const RoadType* TerrainTypeHandler::getRoadByCode(const std::string& roadCode) c return roadInfoByCode.at(roadCode); } -const RoadType* TerrainTypeHandler::getRoadById(TRoad id) const +const RoadType* TerrainTypeHandler::getRoadById(TRoadId id) const { return roadInfoById.at(id); } @@ -440,17 +440,16 @@ bool TerrainType::isTransitionRequired() const return transitionRequired; } -RiverType::RiverType(const std::string & fileName, const std::string & code, TRiver id): +RiverType::RiverType(const std::string & fileName, const std::string & code, TRiverId id): fileName(fileName), code(code), id(id) { } -RoadType::RoadType(const std::string& fileName, const std::string& code, TRoad id): +RoadType::RoadType(const std::string& fileName, const std::string& code, TRoadId id): fileName(fileName), code(code), - id(id), - movementCost(GameConstants::BASE_MOVEMENT_COST) + id(id) { } \ No newline at end of file diff --git a/lib/Terrain.h b/lib/Terrain.h index e222365b5..3ca466b1a 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -29,7 +29,7 @@ public: }; std::vector battleFields; - std::vector prohibitTransitions; + std::vector prohibitTransitions; std::array minimapBlocked; std::array minimapUnblocked; std::string name; @@ -38,10 +38,10 @@ public: std::string terrainText; std::string typeCode; std::string terrainViewPatterns; - TRiver river; + TRiverId river; - TTerrain id; - TTerrain rockTerrain; + TTerrainId id; + TTerrainId rockTerrain; int moveCost; int horseSoundId; ui8 passabilityType; @@ -94,9 +94,9 @@ public: std::string fileName; std::string code; std::string deltaName; - TRiver id; + TRiverId id; - RiverType(const std::string & fileName = "", const std::string& code = "", TRiver id = River::NO_RIVER); + RiverType(const std::string & fileName = "", const std::string & code = "", TRiverId id = River::NO_RIVER); template void serialize(Handler& h, const int version) { @@ -112,10 +112,10 @@ class DLL_LINKAGE RoadType public: std::string fileName; std::string code; - TRoad id; + TRoadId id; ui8 movementCost; - RoadType(const std::string & fileName = "", const std::string& code = "", TRoad id = Road::NO_ROAD); + RoadType(const std::string & fileName = "", const std::string& code = "", TRoadId id = Road::NO_ROAD); template void serialize(Handler& h, const int version) { @@ -133,24 +133,21 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? public: TerrainTypeHandler(); - void initTerrains(const std::vector & allConfigs); - void initRivers(const std::vector & allConfigs); - void initRoads(const std::vector & allConfigs); const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; const TerrainType * getInfoByCode(const std::string & terrainCode) const; - const TerrainType * getInfoById(TTerrain id) const; + const TerrainType * getInfoById(TTerrainId id) const; const std::vector & rivers() const; const RiverType * getRiverByName(const std::string & riverName) const; const RiverType * getRiverByCode(const std::string & riverCode) const; - const RiverType * getRiverById(TRiver id) const; + const RiverType * getRiverById(TRiverId id) const; const std::vector & roads() const; const RoadType * getRoadByName(const std::string & roadName) const; const RoadType * getRoadByCode(const std::string & roadCode) const; - const RoadType * getRoadById(TRoad id) const; + const RoadType * getRoadById(TRoadId id) const; template void serialize(Handler &h, const int version) { @@ -174,16 +171,19 @@ private: std::unordered_map terrainInfoByName; std::unordered_map terrainInfoByCode; - std::unordered_map terrainInfoById; + std::unordered_map terrainInfoById; std::unordered_map riverInfoByName; std::unordered_map riverInfoByCode; - std::unordered_map riverInfoById; + std::unordered_map riverInfoById; std::unordered_map roadInfoByName; std::unordered_map roadInfoByCode; - std::unordered_map roadInfoById; + std::unordered_map roadInfoById; + void initTerrains(const std::vector & allConfigs); + void initRivers(const std::vector & allConfigs); + void initRoads(const std::vector & allConfigs); void recreateTerrainMaps(); void recreateRiverMaps(); void recreateRoadMaps(); diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index 47c797f24..919e3bdd1 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -189,7 +189,7 @@ struct RangeGenerator std::function myRand; }; -BattleInfo * BattleInfo::setupBattle(const int3 & tile, TTerrain terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) +BattleInfo * BattleInfo::setupBattle(const int3 & tile, TTerrainId terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) { CMP_stack cmpst; auto curB = new BattleInfo(); @@ -563,7 +563,7 @@ BattleField BattleInfo::getBattlefieldType() const return battlefieldType; } -TTerrain BattleInfo::getTerrainType() const +TTerrainId BattleInfo::getTerrainType() const { return terrainType; } diff --git a/lib/battle/BattleInfo.h b/lib/battle/BattleInfo.h index 84748bc46..60e146de2 100644 --- a/lib/battle/BattleInfo.h +++ b/lib/battle/BattleInfo.h @@ -37,7 +37,7 @@ public: SiegeInfo si; BattleField battlefieldType; //like !!BA:B - TTerrain terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) + TTerrainId terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) ui8 tacticsSide; //which side is requested to play tactics phase ui8 tacticDistance; //how many hexes we can go forward (1 = only hexes adjacent to margin line) @@ -73,7 +73,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - TTerrain getTerrainType() const override; + TTerrainId getTerrainType() const override; ObstacleCList getAllObstacles() const override; @@ -138,7 +138,7 @@ public: const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player void localInit(); - static BattleInfo * setupBattle(const int3 & tile, TTerrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); + static BattleInfo * setupBattle(const int3 & tile, TTerrainId, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); ui8 whatSide(PlayerColor player) const; diff --git a/lib/battle/BattleProxy.cpp b/lib/battle/BattleProxy.cpp index 18bbc328c..d32972f3b 100644 --- a/lib/battle/BattleProxy.cpp +++ b/lib/battle/BattleProxy.cpp @@ -47,7 +47,7 @@ BattleField BattleProxy::getBattlefieldType() const return subject->battleGetBattlefieldType(); } -TTerrain BattleProxy::getTerrainType() const +TTerrainId BattleProxy::getTerrainType() const { return subject->battleTerrainType(); } diff --git a/lib/battle/BattleProxy.h b/lib/battle/BattleProxy.h index 9972fe071..3b8998353 100644 --- a/lib/battle/BattleProxy.h +++ b/lib/battle/BattleProxy.h @@ -30,7 +30,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - TTerrain getTerrainType() const override; + TTerrainId getTerrainType() const override; ObstacleCList getAllObstacles() const override; diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index 512ed414c..43af98110 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -14,9 +14,9 @@ #include "../NetPacks.h" #include "../mapObjects/CGTownInstance.h" -TTerrain CBattleInfoEssentials::battleTerrainType() const +TTerrainId CBattleInfoEssentials::battleTerrainType() const { - RETURN_IF_NOT_BATTLE(TTerrain()); + RETURN_IF_NOT_BATTLE(TTerrainId()); return getBattle()->getTerrainType(); } diff --git a/lib/battle/CBattleInfoEssentials.h b/lib/battle/CBattleInfoEssentials.h index 89b1fb90c..ef3812f1a 100644 --- a/lib/battle/CBattleInfoEssentials.h +++ b/lib/battle/CBattleInfoEssentials.h @@ -46,7 +46,7 @@ public: BattlePerspective::BattlePerspective battleGetMySide() const; const IBonusBearer * getBattleNode() const; - TTerrain battleTerrainType() const override; + TTerrainId battleTerrainType() const override; BattleField battleGetBattlefieldType() const override; int32_t battleGetEnchanterCounter(ui8 side) const; diff --git a/lib/battle/IBattleInfoCallback.h b/lib/battle/IBattleInfoCallback.h index 5a8c1c06c..41a684ad9 100644 --- a/lib/battle/IBattleInfoCallback.h +++ b/lib/battle/IBattleInfoCallback.h @@ -38,7 +38,7 @@ public: virtual scripting::Pool * getContextPool() const = 0; #endif - virtual TTerrain battleTerrainType() const = 0; + virtual TTerrainId battleTerrainType() const = 0; virtual BattleField battleGetBattlefieldType() const = 0; ///return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw diff --git a/lib/battle/IBattleState.h b/lib/battle/IBattleState.h index 89c0f3cc3..fd52672f7 100644 --- a/lib/battle/IBattleState.h +++ b/lib/battle/IBattleState.h @@ -42,7 +42,7 @@ public: virtual battle::Units getUnitsIf(battle::UnitFilter predicate) const = 0; virtual BattleField getBattlefieldType() const = 0; - virtual TTerrain getTerrainType() const = 0; + virtual TTerrainId getTerrainType() const = 0; virtual ObstacleCList getAllObstacles() const = 0; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 861adc262..679a4a8e9 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -96,7 +96,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f return (ui32)ret; } -TTerrain CGHeroInstance::getNativeTerrain() const +TTerrainId CGHeroInstance::getNativeTerrain() const { // NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army. // This is clearly bug in H3 however intended behaviour is not clear. @@ -104,11 +104,11 @@ TTerrain CGHeroInstance::getNativeTerrain() const // will always have best penalty without any influence from player-defined stacks order // TODO: What should we do if all hero stacks are neutral creatures? - TTerrain nativeTerrain = Terrain::BORDER; + TTerrainId nativeTerrain = Terrain::BORDER; for(auto stack : stacks) { - TTerrain stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. + TTerrainId stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. if(stackNativeTerrain == Terrain::BORDER) //where does this value come from? continue; diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index a0443bb4c..326624c0a 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -155,7 +155,7 @@ public: bool needsLastStack()const override; ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling - TTerrain getNativeTerrain() const; + TTerrainId getNativeTerrain() const; ui32 getLowestCreatureSpeed() const; int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index 95caf0c14..717a6d5a7 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -588,7 +588,7 @@ BattleField AObjectTypeHandler::getBattlefield() const return battlefield ? BattleField::fromString(battlefield.get()) : BattleField::NONE; } -std::vector>AObjectTypeHandler::getTemplates(TTerrain terrainType) const +std::vector>AObjectTypeHandler::getTemplates(TTerrainId terrainType) const { std::vector> templates = getTemplates(); std::vector> filtered; @@ -605,7 +605,7 @@ std::vector>AObjectTypeHandler::getTemplat return filtered; } -std::shared_ptr AObjectTypeHandler::getOverride(TTerrain terrainType, const CGObjectInstance * object) const +std::shared_ptr AObjectTypeHandler::getOverride(TTerrainId terrainType, const CGObjectInstance * object) const { std::vector> ret = getTemplates(terrainType); for (const auto & tmpl: ret) diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index 83ff1b5f3..ef5fea929 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -182,11 +182,11 @@ public: /// returns all templates matching parameters std::vector> getTemplates() const; - std::vector> getTemplates(const TTerrain terrainType) const; + std::vector> getTemplates(const TTerrainId terrainType) const; /// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle) /// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server) - std::shared_ptr getOverride(TTerrain terrainType, const CGObjectInstance * object) const; + std::shared_ptr getOverride(TTerrainId terrainType, const CGObjectInstance * object) const; BattleField getBattlefield() const; diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 05ff04cf9..26f1ccd41 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -156,7 +156,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain assert(terrStr.size() == Terrain::ROCK - 1); // all terrains but rock - for(TTerrain i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) + for(TTerrainId i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) { if (terrStr[8-i] == '1') allowedTerrains.insert(i); @@ -282,22 +282,22 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) else visitDir = 0x00; - if (withTerrain && !node["allowedTerrains"].isNull()) + if(withTerrain && !node["allowedTerrains"].isNull()) { - for (auto& entry : node["allowedTerrains"].Vector()) + for(auto& entry : node["allowedTerrains"].Vector()) allowedTerrains.insert(VLC->terrainTypeHandler->getInfoByName(entry.String())->id); } else { - for (const auto* terrain : VLC->terrainTypeHandler->terrains()) + for(const auto* terrain : VLC->terrainTypeHandler->terrains()) { - if (!terrain->isPassable() || terrain->isWater()) + if(!terrain->isPassable() || terrain->isWater()) continue; allowedTerrains.insert(terrain->id); } } - if (withTerrain && allowedTerrains.empty()) + if(withTerrain && allowedTerrains.empty()) logGlobal->warn("Loaded template without allowed terrains!"); auto charToTile = [&](const char & ch) -> ui8 @@ -555,7 +555,7 @@ void ObjectTemplate::calculateVisitableOffset() visitableOffset = int3(0, 0, 0); } -bool ObjectTemplate::canBePlacedAt(TTerrain terrain) const +bool ObjectTemplate::canBePlacedAt(TTerrainId terrain) const { return vstd::contains(allowedTerrains, terrain); } diff --git a/lib/mapObjects/ObjectTemplate.h b/lib/mapObjects/ObjectTemplate.h index e1b9c2c1b..999250ecd 100644 --- a/lib/mapObjects/ObjectTemplate.h +++ b/lib/mapObjects/ObjectTemplate.h @@ -31,7 +31,7 @@ class DLL_LINKAGE ObjectTemplate /// directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7) ui8 visitDir; /// list of terrains on which this object can be placed - std::set allowedTerrains; + std::set allowedTerrains; void afterLoadFixup(); @@ -98,7 +98,7 @@ public: }; // Checks if object can be placed on specific terrain - bool canBePlacedAt(TTerrain terrain) const; + bool canBePlacedAt(TTerrainId terrain) const; ObjectTemplate(); //custom copy constructor is required diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 4f8bd0b24..3b624fa4f 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -156,14 +156,14 @@ CDrawLinesOperation::CDrawLinesOperation(CMap * map, const CTerrainSelection & t } ///CDrawRoadsOperation -CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen): +CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel,gen), roadType(roadType) { } ///CDrawRiversOperation -CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRiver riverType, CRandomGenerator * gen): +CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRiverId riverType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel, gen), riverType(riverType) { diff --git a/lib/mapping/CDrawRoadsOperation.h b/lib/mapping/CDrawRoadsOperation.h index b614811f5..de9abd4ec 100644 --- a/lib/mapping/CDrawRoadsOperation.h +++ b/lib/mapping/CDrawRoadsOperation.h @@ -61,7 +61,7 @@ protected: class CDrawRoadsOperation : public CDrawLinesOperation { public: - CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen); + CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -72,13 +72,13 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - TRoad roadType; + TRoadId roadType; }; class CDrawRiversOperation : public CDrawLinesOperation { public: - CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRoad roadType, CRandomGenerator * gen); + CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -89,5 +89,5 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - TRiver riverType; + TRiverId riverType; }; diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 3db91fda7..bb8c1a569 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -124,19 +124,19 @@ void CMapEditManager::clearTerrain(CRandomGenerator * gen) execute(make_unique(map, gen ? gen : &(this->gen))); } -void CMapEditManager::drawTerrain(TTerrain terType, CRandomGenerator * gen) +void CMapEditManager::drawTerrain(TTerrainId terType, CRandomGenerator * gen) { execute(make_unique(map, terrainSel, terType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); } -void CMapEditManager::drawRoad(TRoad roadType, CRandomGenerator* gen) +void CMapEditManager::drawRoad(TRoadId roadType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, roadType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); } -void CMapEditManager::drawRiver(TRiver riverType, CRandomGenerator* gen) +void CMapEditManager::drawRiver(TRiverId riverType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, riverType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 970aab701..052257beb 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -70,13 +70,13 @@ public: void clearTerrain(CRandomGenerator * gen = nullptr); /// Draws terrain at the current terrain selection. The selection will be cleared automatically. - void drawTerrain(TTerrain terType, CRandomGenerator * gen = nullptr); + void drawTerrain(TTerrainId terType, CRandomGenerator * gen = nullptr); /// Draws roads at the current terrain selection. The selection will be cleared automatically. - void drawRoad(TRoad roadType, CRandomGenerator * gen = nullptr); + void drawRoad(TRoadId roadType, CRandomGenerator * gen = nullptr); /// Draws rivers at the current terrain selection. The selection will be cleared automatically. - void drawRiver(TRiver riverType, CRandomGenerator * gen = nullptr); + void drawRiver(TRiverId riverType, CRandomGenerator * gen = nullptr); void insertObject(CGObjectInstance * obj); void insertObjects(std::set & objects); diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 4882e0101..4392beb24 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -81,7 +81,7 @@ void CComposedOperation::addOperation(std::unique_ptr&& operation operations.push_back(std::move(operation)); } -CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, TTerrain terType, CRandomGenerator* gen): +CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, TTerrainId terType, CRandomGenerator* gen): CMapOperation(map), terrainSel(terrainSel), terType(terType), diff --git a/lib/mapping/CMapOperation.h b/lib/mapping/CMapOperation.h index 0c3f851ff..3728f16c0 100644 --- a/lib/mapping/CMapOperation.h +++ b/lib/mapping/CMapOperation.h @@ -61,7 +61,7 @@ private: class CDrawTerrainOperation : public CMapOperation { public: - CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, TTerrain terType, CRandomGenerator * gen); + CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, TTerrainId terType, CRandomGenerator * gen); void execute() override; void undo() override; @@ -98,7 +98,7 @@ private: ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const; CTerrainSelection terrainSel; - TTerrain terType; + TTerrainId terType; CRandomGenerator* gen; std::set invalidatedTerViews; }; diff --git a/lib/mapping/MapEditUtils.cpp b/lib/mapping/MapEditUtils.cpp index 513e05f1a..603d009d7 100644 --- a/lib/mapping/MapEditUtils.cpp +++ b/lib/mapping/MapEditUtils.cpp @@ -268,7 +268,7 @@ CTerrainViewPatternConfig::~CTerrainViewPatternConfig() } -const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TTerrain terrain) const +const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TTerrainId terrain) const { auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain]->terrainViewPatterns); if (iter == terrainViewPatterns.end()) @@ -293,7 +293,7 @@ boost::optional CTerrainViewPatternConfig::getTerrai return boost::optional(); } -boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(TTerrain terrain, const std::string & id) const +boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(TTerrainId terrain, const std::string & id) const { const std::vector & groupPatterns = getTerrainViewPatterns(terrain); for (const TVPVector & patternFlips : groupPatterns) diff --git a/lib/mapping/MapEditUtils.h b/lib/mapping/MapEditUtils.h index 6a6e44962..3517f49dc 100644 --- a/lib/mapping/MapEditUtils.h +++ b/lib/mapping/MapEditUtils.h @@ -215,9 +215,9 @@ public: CTerrainViewPatternConfig(); ~CTerrainViewPatternConfig(); - const std::vector & getTerrainViewPatterns(TTerrain terrain) const; + const std::vector & getTerrainViewPatterns(TTerrainId terrain) const; boost::optional getTerrainViewPatternById(std::string patternId, const std::string & id) const; - boost::optional getTerrainViewPatternsById(TTerrain terrain, const std::string & id) const; + boost::optional getTerrainViewPatternsById(TTerrainId terrain, const std::string & id) const; const TVPVector * getTerrainTypePatternById(const std::string & id) const; void flipPattern(TerrainViewPattern & pattern, int flip) const; diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index 74a376508..7b4439227 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -215,12 +215,12 @@ boost::optional ZoneOptions::getOwner() const return owner; } -const std::set & ZoneOptions::getTerrainTypes() const +const std::set & ZoneOptions::getTerrainTypes() const { return terrainTypes; } -void ZoneOptions::setTerrainTypes(const std::set & value) +void ZoneOptions::setTerrainTypes(const std::set & value) { //assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() && // value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end()); diff --git a/lib/rmg/CRmgTemplate.h b/lib/rmg/CRmgTemplate.h index 3007a9988..f7e5b28c8 100644 --- a/lib/rmg/CRmgTemplate.h +++ b/lib/rmg/CRmgTemplate.h @@ -103,8 +103,8 @@ public: void setSize(int value); boost::optional getOwner() const; - const std::set & getTerrainTypes() const; - void setTerrainTypes(const std::set & value); + const std::set & getTerrainTypes() const; + void setTerrainTypes(const std::set & value); const CTownInfo & getPlayerTowns() const; const CTownInfo & getNeutralTowns() const; @@ -144,7 +144,7 @@ protected: CTownInfo playerTowns; CTownInfo neutralTowns; bool matchTerrainToTown; - std::set terrainTypes; + std::set terrainTypes; bool townsAreSameType; std::set townTypes; diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 7d48e836d..7195cde00 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -93,14 +93,14 @@ void createBorder(RmgMap & gen, Zone & zone) } } -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrain terrain) +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrainId terrain) { auto v = zone.getArea().getTilesVector(); map.getEditManager()->getTerrainSelection().setSelection(v); map.getEditManager()->drawTerrain(terrain, &generator); } -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrain terrain) +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrainId terrain) { auto factories = VLC->objtypeh->knownSubObjects(ObjID); vstd::erase_if(factories, [ObjID, &terrain](si32 f) @@ -116,7 +116,7 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) if(zone.getType()==ETemplateZoneType::WATER) { //collect all water terrain types - std::vector waterTerrains; + std::vector waterTerrains; for(auto & terrain : VLC->terrainTypeHandler->terrains()) if(terrain->isWater()) waterTerrains.push_back(terrain->id); diff --git a/lib/rmg/Functions.h b/lib/rmg/Functions.h index db340c3f7..68a26229e 100644 --- a/lib/rmg/Functions.h +++ b/lib/rmg/Functions.h @@ -40,9 +40,9 @@ rmg::Tileset collectDistantTiles(const Zone & zone, int distance); void createBorder(RmgMap & gen, Zone & zone); -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrain terrainType); +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrainId terrainType); void initTerrainType(Zone & zone, CMapGenerator & gen); -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrain terrain); +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrainId terrain); diff --git a/lib/rmg/ObstaclePlacer.cpp b/lib/rmg/ObstaclePlacer.cpp index bb4c7e042..3700b4f16 100644 --- a/lib/rmg/ObstaclePlacer.cpp +++ b/lib/rmg/ObstaclePlacer.cpp @@ -24,7 +24,7 @@ #include "Functions.h" #include "../mapping/CMapEditManager.h" -void ObstacleProxy::collectPossibleObstacles(TTerrain terrain) +void ObstacleProxy::collectPossibleObstacles(TTerrainId terrain) { //get all possible obstacles for this terrain for(auto primaryID : VLC->objtypeh->knownObjects()) diff --git a/lib/rmg/ObstaclePlacer.h b/lib/rmg/ObstaclePlacer.h index e61df728f..4e1001ad3 100644 --- a/lib/rmg/ObstaclePlacer.h +++ b/lib/rmg/ObstaclePlacer.h @@ -23,7 +23,7 @@ public: rmg::Area blockedArea; - void collectPossibleObstacles(TTerrain terrain); + void collectPossibleObstacles(TTerrainId terrain); void placeObstacles(CMap * map, CRandomGenerator & rand); diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index 132b613ec..2d6e03b91 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -229,7 +229,7 @@ void RmgMap::setOccupied(const int3 &tile, ETileType::ETileType state) tiles[tile.x][tile.y][tile.z].setOccupied(state); } -void RmgMap::setRoad(const int3& tile, TRoad roadType) +void RmgMap::setRoad(const int3& tile, TRoadId roadType) { assertOnMap(tile); diff --git a/lib/rmg/RmgMap.h b/lib/rmg/RmgMap.h index 22612276d..9deccac20 100644 --- a/lib/rmg/RmgMap.h +++ b/lib/rmg/RmgMap.h @@ -44,7 +44,7 @@ public: bool isOnMap(const int3 & tile) const; void setOccupied(const int3 &tile, ETileType::ETileType state); - void setRoad(const int3 &tile, TRoad roadType); + void setRoad(const int3 &tile, TRoadId roadType); TileInfo getTile(const int3 & tile) const; diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index a1f117559..68d5a7754 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -103,7 +103,7 @@ void Object::Instance::setPositionRaw(const int3 & position) dObject.pos = dPosition + dParent.getPosition(); } -void Object::Instance::setTemplate(const TTerrain & terrain) +void Object::Instance::setTemplate(const TTerrainId & terrain) { if(dObject.appearance->id == Obj::NO_OBJ) { @@ -257,7 +257,7 @@ void Object::setPosition(const int3 & position) i.setPositionRaw(i.getPosition()); } -void Object::setTemplate(const TTerrain & terrain) +void Object::setTemplate(const TTerrainId & terrain) { for(auto& i : dInstances) i.setTemplate(terrain); diff --git a/lib/rmg/RmgObject.h b/lib/rmg/RmgObject.h index 7a72126c4..a085c6bd6 100644 --- a/lib/rmg/RmgObject.h +++ b/lib/rmg/RmgObject.h @@ -33,7 +33,7 @@ public: int3 getVisitablePosition() const; bool isVisitableFrom(const int3 & tile) const; const Area & getAccessibleArea() const; - void setTemplate(const TTerrain & terrain); //cache invalidation + void setTemplate(const TTerrainId & terrain); //cache invalidation int3 getPosition(bool isAbsolute = false) const; void setPosition(const int3 & position); //cache invalidation @@ -69,7 +69,7 @@ public: const int3 & getPosition() const; void setPosition(const int3 & position); - void setTemplate(const TTerrain & terrain); + void setTemplate(const TTerrainId & terrain); const Area & getArea() const; //lazy cache invalidation diff --git a/lib/rmg/RoadPlacer.cpp b/lib/rmg/RoadPlacer.cpp index 25016c2e8..a235388ad 100644 --- a/lib/rmg/RoadPlacer.cpp +++ b/lib/rmg/RoadPlacer.cpp @@ -70,7 +70,7 @@ void RoadPlacer::drawRoads(bool secondary) zone.freePaths().unite(roads); map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector()); std::string roadCode = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType); - TRoad roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id; + TRoadId roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id; map.getEditManager()->drawRoad(roadType, &generator.rand); } diff --git a/lib/rmg/RockPlacer.h b/lib/rmg/RockPlacer.h index 1163a7cdd..b1df1f7fe 100644 --- a/lib/rmg/RockPlacer.h +++ b/lib/rmg/RockPlacer.h @@ -26,5 +26,5 @@ public: protected: rmg::Area rockArea, accessibleArea; - TTerrain rockTerrain; + TTerrainId rockTerrain; }; diff --git a/lib/rmg/TileInfo.cpp b/lib/rmg/TileInfo.cpp index ba8a4eb35..c28841b09 100644 --- a/lib/rmg/TileInfo.cpp +++ b/lib/rmg/TileInfo.cpp @@ -61,17 +61,17 @@ ETileType::ETileType TileInfo::getTileType() const return occupied; } -TTerrain TileInfo::getTerrainType() const +TTerrainId TileInfo::getTerrainType() const { return terrain; } -void TileInfo::setTerrainType(TTerrain type) +void TileInfo::setTerrainType(TTerrainId type) { terrain = type; } -void TileInfo::setRoadType(TRoad type) +void TileInfo::setRoadType(TRoadId type) { roadType = type; // setOccupied(ETileType::FREE); diff --git a/lib/rmg/TileInfo.h b/lib/rmg/TileInfo.h index 46d0430e3..198481dc4 100644 --- a/lib/rmg/TileInfo.h +++ b/lib/rmg/TileInfo.h @@ -28,14 +28,14 @@ public: bool isUsed() const; bool isRoad() const; void setOccupied(ETileType::ETileType value); - TTerrain getTerrainType() const; + TTerrainId getTerrainType() const; ETileType::ETileType getTileType() const; - void setTerrainType(TTerrain value); + void setTerrainType(TTerrainId value); - void setRoadType(TRoad type); + void setRoadType(TRoadId type); private: float nearestObjectDistance; ETileType::ETileType occupied; - TTerrain terrain; - TRoad roadType; + TTerrainId terrain; + TRoadId roadType; }; diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 801c6b994..83885ccb3 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -811,7 +811,7 @@ ObjectInfo::ObjectInfo() } -void ObjectInfo::setTemplate(si32 type, si32 subtype, TTerrain terrainType) +void ObjectInfo::setTemplate(si32 type, si32 subtype, TTerrainId terrainType) { auto templHandler = VLC->objtypeh->getHandlerFor(type, subtype); if(!templHandler) diff --git a/lib/rmg/TreasurePlacer.h b/lib/rmg/TreasurePlacer.h index 9d005b224..adea2cd6f 100644 --- a/lib/rmg/TreasurePlacer.h +++ b/lib/rmg/TreasurePlacer.h @@ -26,7 +26,7 @@ struct ObjectInfo //ui32 maxPerMap; //unused std::function generateObject; - void setTemplate(si32 type, si32 subtype, TTerrain terrain); + void setTemplate(si32 type, si32 subtype, TTerrainId terrain); ObjectInfo(); diff --git a/lib/rmg/Zone.cpp b/lib/rmg/Zone.cpp index 83fbd5638..e432b102d 100644 --- a/lib/rmg/Zone.cpp +++ b/lib/rmg/Zone.cpp @@ -132,12 +132,12 @@ void Zone::setTownType(si32 town) townType = town; } -TTerrain Zone::getTerrainType() const +TTerrainId Zone::getTerrainType() const { return terrainType; } -void Zone::setTerrainType(TTerrain terrain) +void Zone::setTerrainType(TTerrainId terrain) { terrainType = terrain; } diff --git a/lib/rmg/Zone.h b/lib/rmg/Zone.h index 78ab28182..830fad6ea 100644 --- a/lib/rmg/Zone.h +++ b/lib/rmg/Zone.h @@ -98,8 +98,8 @@ public: si32 getTownType() const; void setTownType(si32 town); - TTerrain getTerrainType() const; - void setTerrainType(TTerrain terrain); + TTerrainId getTerrainType() const; + void setTerrainType(TTerrainId terrain); void connectPath(const rmg::Path & path); rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, std::function areafilter = AREA_NO_FILTER) const; @@ -138,6 +138,6 @@ protected: //template info si32 townType; - TTerrain terrainType; + TTerrainId terrainType; }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 799c65369..d039bf749 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2238,8 +2238,8 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const { battleResult.set(nullptr); - const auto t = getTile(tile); - TTerrain terrain = t->terType->id; + const auto & t = *getTile(tile); + TTerrainId terrain = t.terType->id; if (gs->map->isCoastalTile(tile)) //coastal tile is always ground terrain = Terrain::SAND; diff --git a/test/game/CGameStateTest.cpp b/test/game/CGameStateTest.cpp index 6720bc766..cbda7d01e 100644 --- a/test/game/CGameStateTest.cpp +++ b/test/game/CGameStateTest.cpp @@ -191,9 +191,9 @@ public: int3 tile(4,4,0); - const auto t = gameCallback->getTile(tile); + const auto & t = *gameCallback->getTile(tile); - TTerrain terrain = t->terType->id; + TTerrainId terrain = t.terType->id; BattleField terType = BattleField::fromString("grass_hills"); //send info about battles diff --git a/test/mock/mock_IBattleInfoCallback.h b/test/mock/mock_IBattleInfoCallback.h index 0f3a42efd..aa9183de7 100644 --- a/test/mock/mock_IBattleInfoCallback.h +++ b/test/mock/mock_IBattleInfoCallback.h @@ -17,7 +17,7 @@ class IBattleInfoCallbackMock : public IBattleInfoCallback { public: MOCK_CONST_METHOD0(getContextPool, scripting::Pool *()); - MOCK_CONST_METHOD0(battleTerrainType, TTerrain()); + MOCK_CONST_METHOD0(battleTerrainType, TTerrainId()); MOCK_CONST_METHOD0(battleGetBattlefieldType, BattleField()); MOCK_CONST_METHOD0(battleIsFinished, boost::optional()); diff --git a/test/mock/mock_battle_IBattleState.h b/test/mock/mock_battle_IBattleState.h index d71eb81eb..c63d2716f 100644 --- a/test/mock/mock_battle_IBattleState.h +++ b/test/mock/mock_battle_IBattleState.h @@ -19,7 +19,7 @@ public: MOCK_CONST_METHOD1(getStacksIf, TStacks(TStackFilter)); MOCK_CONST_METHOD1(getUnitsIf, battle::Units(battle::UnitFilter)); MOCK_CONST_METHOD0(getBattlefieldType, BattleField()); - MOCK_CONST_METHOD0(getTerrainType, TTerrain()); + MOCK_CONST_METHOD0(getTerrainType, TTerrainId()); MOCK_CONST_METHOD0(getAllObstacles, IBattleInfo::ObstacleCList()); MOCK_CONST_METHOD0(getDefendedTown, const CGTownInstance *()); MOCK_CONST_METHOD1(getWallState, si8(int)); From 64fd89697831817918c47be82e44ac724d34201d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sun, 25 Sep 2022 20:52:51 +0200 Subject: [PATCH 19/74] Free memory at TerrainTypeHandler destruction --- lib/Terrain.cpp | 16 ++++++++++++++++ lib/Terrain.h | 1 + 2 files changed, 17 insertions(+) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 6dfa102bc..78612ba5f 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -29,6 +29,22 @@ TerrainTypeHandler::TerrainTypeHandler() initTerrains(allConfigs); //maps will be populated inside } +TerrainTypeHandler::~TerrainTypeHandler() +{ + for (const auto * terrain : objects) + { + delete terrain; + } + for (const auto * river : riverTypes) + { + delete river; + } + for (const auto * road : roadTypes) + { + delete road; + } +} + void TerrainTypeHandler::initTerrains(const std::vector & allConfigs) { std::vector> resolveLater; diff --git a/lib/Terrain.h b/lib/Terrain.h index 3ca466b1a..cf4b06f1c 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -133,6 +133,7 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? public: TerrainTypeHandler(); + ~TerrainTypeHandler(); const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; From cd3a1a02c23caba3bdea885dfa079442c13d488d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sun, 25 Sep 2022 21:47:44 +0200 Subject: [PATCH 20/74] More style tweaks --- client/battle/CBattleInterface.cpp | 4 ++-- lib/mapping/CMap.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 04e42914f..e0e0b6713 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -456,8 +456,8 @@ CBattleInterface::~CBattleInterface() if (adventureInt && adventureInt->selection) { - const auto * terrain = LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType; - CCS->musich->playMusicFromSet("terrain", terrain->name, true); + const auto & terrain = *(LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType); + CCS->musich->playMusicFromSet("terrain", terrain.name, true); } animsAreDisplayed.setn(false); } diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index b47ba37b5..8c8116056 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -126,14 +126,14 @@ CCastleEvent::CCastleEvent() : town(nullptr) TerrainTile::TerrainTile(): terType(nullptr), terView(0), + riverType(VLC->terrainTypeHandler->rivers()[0]), riverDir(0), + roadType(VLC->terrainTypeHandler->roads()[0]), roadDir(0), extTileFlags(0), visitable(false), blocked(false) { - riverType = VLC->terrainTypeHandler->rivers()[0]; - roadType = VLC->terrainTypeHandler->roads()[0]; } bool TerrainTile::entrableTerrain(const TerrainTile * from) const From 2bd30556a365925d6c86b2db45d9670f1399b87a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Mon, 26 Sep 2022 09:17:55 +0200 Subject: [PATCH 21/74] Store TerrainType by havlue and handle by reference --- client/CMusicHandler.cpp | 10 +- client/mapHandler.cpp | 4 +- client/widgets/AdventureMapClasses.cpp | 16 +-- lib/CGeneralTextHandler.cpp | 6 +- lib/CHeroHandler.cpp | 6 +- lib/CPathfinder.cpp | 4 +- lib/HeroBonus.cpp | 4 +- lib/Terrain.cpp | 175 ++++++++++++++----------- lib/Terrain.h | 4 +- lib/mapObjects/ObjectTemplate.cpp | 18 +-- lib/mapping/CMapOperation.cpp | 2 +- lib/mapping/MapEditUtils.cpp | 2 +- lib/mapping/MapFormatH3M.cpp | 8 +- lib/rmg/CRmgTemplate.cpp | 8 +- lib/rmg/CZonePlacer.cpp | 4 +- lib/rmg/ConnectionsPlacer.cpp | 4 +- lib/rmg/Functions.cpp | 12 +- lib/rmg/RiverPlacer.cpp | 6 +- lib/rmg/RmgObject.cpp | 2 +- lib/rmg/RockPlacer.cpp | 4 +- 20 files changed, 162 insertions(+), 137 deletions(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index 473b2cc1a..eead0ee36 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -120,14 +120,14 @@ CSoundHandler::CSoundHandler(): void CSoundHandler::loadHorseSounds() { const auto & terrains = CGI->terrainTypeHandler->terrains(); - for(const auto * terrain : terrains) + for(const auto & terrain : terrains) { //since all sounds are hardcoded, let's keep it - if(vstd::contains(horseSounds, terrain->id)) + if(vstd::contains(horseSounds, terrain.id)) continue; //Use already existing horse sound - horseSounds[terrain->id] = horseSounds.at(terrains[terrain->id]->horseSoundId); + horseSounds[terrain.id] = horseSounds.at(terrains[terrain.id].horseSoundId); } } @@ -376,9 +376,9 @@ CMusicHandler::CMusicHandler(): void CMusicHandler::loadTerrainSounds() { - for (const auto * terrain : CGI->terrainTypeHandler->terrains()) + for (const auto & terrain : CGI->terrainTypeHandler->terrains()) { - addEntryToSet("terrain", terrain->name, "Music/" + terrain->musicFilename); + addEntryToSet("terrain", terrain.name, "Music/" + terrain.musicFilename); } } diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index a631a8b29..e6177153b 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -176,9 +176,9 @@ void CMapHandler::initTerrainGraphics() std::map terrainFiles; std::map riverFiles; std::map roadFiles; - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - terrainFiles[terrain->name] = terrain->tilesFilename; + terrainFiles[terrain.name] = terrain.tilesFilename; } for(const auto * river : VLC->terrainTypeHandler->rivers()) { diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 5aa52c64f..4f9697cb3 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -499,25 +499,25 @@ std::map > CMinimap::loadColors() { std::map > ret; - for(const auto * terrain : CGI->terrainTypeHandler->terrains()) + for(const auto & terrain : CGI->terrainTypeHandler->terrains()) { SDL_Color normal = { - ui8(terrain->minimapUnblocked[0]), - ui8(terrain->minimapUnblocked[1]), - ui8(terrain->minimapUnblocked[2]), + ui8(terrain.minimapUnblocked[0]), + ui8(terrain.minimapUnblocked[1]), + ui8(terrain.minimapUnblocked[2]), ui8(255) }; SDL_Color blocked = { - ui8(terrain->minimapBlocked[0]), - ui8(terrain->minimapBlocked[1]), - ui8(terrain->minimapBlocked[2]), + ui8(terrain.minimapBlocked[0]), + ui8(terrain.minimapBlocked[1]), + ui8(terrain.minimapBlocked[2]), ui8(255) }; - ret[terrain->id] = std::make_pair(normal, blocked); + ret[terrain.id] = std::make_pair(normal, blocked); } return ret; } diff --git a/lib/CGeneralTextHandler.cpp b/lib/CGeneralTextHandler.cpp index f4ad41280..985b02a81 100644 --- a/lib/CGeneralTextHandler.cpp +++ b/lib/CGeneralTextHandler.cpp @@ -338,10 +338,10 @@ CGeneralTextHandler::CGeneralTextHandler() { terrainNames[i] = h3mTerrainNames[i]; } - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - if(!terrain->terrainText.empty()) - terrainNames[terrain->id] = terrain->terrainText; + if(!terrain.terrainText.empty()) + terrainNames[terrain.id] = terrain.terrainText; } diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index a215f27f4..213ef23b9 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -346,7 +346,7 @@ CHeroHandler::CHeroHandler() loadTerrains(); for(int i = 0; i < VLC->terrainTypeHandler->terrains().size(); ++i) { - VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler->terrains()[i]->name, i); + VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler->terrains()[i].name, i); } loadBallistics(); loadExperience(); @@ -972,9 +972,9 @@ ui64 CHeroHandler::reqExp (ui32 level) const void CHeroHandler::loadTerrains() { - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - terrCosts[terrain->id] = terrain->moveCost; + terrCosts[terrain.id] = terrain.moveCost; } } diff --git a/lib/CPathfinder.cpp b/lib/CPathfinder.cpp index e99cc13d4..973f1d4fa 100644 --- a/lib/CPathfinder.cpp +++ b/lib/CPathfinder.cpp @@ -1008,10 +1008,10 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const TurnInfo::BonusCache::BonusCache(TConstBonusListPtr bl) { - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { noTerrainPenalty.push_back(static_cast( - bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(terrain->id))))); + bl->getFirst(Selector::type()(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype()(terrain.id))))); } freeShipBoarding = static_cast(bl->getFirst(Selector::type()(Bonus::FREE_SHIP_BOARDING))); diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 6eb9e9813..4890e7f17 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -2137,7 +2137,7 @@ int CreatureTerrainLimiter::limit(const BonusLimitationContext &context) const std::string CreatureTerrainLimiter::toString() const { boost::format fmt("CreatureTerrainLimiter(terrainType=%s)"); - auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType]->name; + auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType].name; fmt % (terrainType == Terrain::NATIVE_TERRAIN ? "native" : terrainName); return fmt.str(); } @@ -2147,7 +2147,7 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const JsonNode root(JsonNode::JsonType::DATA_STRUCT); root["type"].String() = "CREATURE_TERRAIN_LIMITER"; - auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType]->name; + auto terrainName = VLC->terrainTypeHandler->terrains()[terrainType].name; root["parameters"].Vector().push_back(JsonUtils::stringNode(terrainName)); return root; diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 78612ba5f..a95e322a2 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -31,10 +31,6 @@ TerrainTypeHandler::TerrainTypeHandler() TerrainTypeHandler::~TerrainTypeHandler() { - for (const auto * terrain : objects) - { - delete terrain; - } for (const auto * river : riverTypes) { delete river; @@ -49,7 +45,7 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig { std::vector> resolveLater; - objects.resize(Terrain::ORIGINAL_TERRAIN_COUNT, nullptr); //make space for original terrains + objects.resize(Terrain::ORIGINAL_TERRAIN_COUNT); //make space for original terrains for(auto & mod : allConfigs) { @@ -59,11 +55,11 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig JsonNode terrs(mod, ResourceID("config/terrains.json")); for(auto & terr : terrs.Struct()) { - auto * info = new TerrainType(terr.first); //set name + TerrainType info(terr.first); //set name - info->moveCost = terr.second["moveCost"].Integer(); + info.moveCost = static_cast(terr.second["moveCost"].Integer()); const JsonVector &unblockedVec = terr.second["minimapUnblocked"].Vector(); - info->minimapUnblocked = + info.minimapUnblocked = { ui8(unblockedVec[0].Float()), ui8(unblockedVec[1].Float()), @@ -71,18 +67,18 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig }; const JsonVector &blockedVec = terr.second["minimapBlocked"].Vector(); - info->minimapBlocked = + info.minimapBlocked = { ui8(blockedVec[0].Float()), ui8(blockedVec[1].Float()), ui8(blockedVec[2].Float()) }; - info->musicFilename = terr.second["music"].String(); - info->tilesFilename = terr.second["tiles"].String(); + info.musicFilename = terr.second["music"].String(); + info.tilesFilename = terr.second["tiles"].String(); if(terr.second["type"].isNull()) { - info->passabilityType = TerrainType::PassabilityType::LAND | TerrainType::PassabilityType::SURFACE; + info.passabilityType = TerrainType::PassabilityType::LAND | TerrainType::PassabilityType::SURFACE; } else if (terr.second["type"].getType() == JsonNode::JsonType::DATA_VECTOR) { @@ -90,122 +86,125 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig { //Set bits auto s = node.String(); - if (s == "LAND") info->passabilityType |= TerrainType::PassabilityType::LAND; - if (s == "WATER") info->passabilityType |= TerrainType::PassabilityType::WATER; - if (s == "ROCK") info->passabilityType |= TerrainType::PassabilityType::ROCK; - if (s == "SURFACE") info->passabilityType |= TerrainType::PassabilityType::SURFACE; - if (s == "SUB") info->passabilityType |= TerrainType::PassabilityType::SUBTERRANEAN; + if (s == "LAND") info.passabilityType |= TerrainType::PassabilityType::LAND; + if (s == "WATER") info.passabilityType |= TerrainType::PassabilityType::WATER; + if (s == "ROCK") info.passabilityType |= TerrainType::PassabilityType::ROCK; + if (s == "SURFACE") info.passabilityType |= TerrainType::PassabilityType::SURFACE; + if (s == "SUB") info.passabilityType |= TerrainType::PassabilityType::SUBTERRANEAN; } } else //should be string - one option only { auto s = terr.second["type"].String(); - if (s == "LAND") info->passabilityType = TerrainType::PassabilityType::LAND; - if (s == "WATER") info->passabilityType = TerrainType::PassabilityType::WATER; - if (s == "ROCK") info->passabilityType = TerrainType::PassabilityType::ROCK; - if (s == "SURFACE") info->passabilityType = TerrainType::PassabilityType::SURFACE; - if (s == "SUB") info->passabilityType = TerrainType::PassabilityType::SUBTERRANEAN; - } - - if(terr.second["rockTerrain"].isNull()) - { - info->rockTerrain = Terrain::ROCK; - } - else - { - auto rockTerrainName = terr.second["rockTerrain"].String(); - resolveLater.push_back([this, rockTerrainName, info]() - { - info->rockTerrain = getInfoByName(rockTerrainName)->id; - }); + if (s == "LAND") info.passabilityType = TerrainType::PassabilityType::LAND; + if (s == "WATER") info.passabilityType = TerrainType::PassabilityType::WATER; + if (s == "ROCK") info.passabilityType = TerrainType::PassabilityType::ROCK; + if (s == "SURFACE") info.passabilityType = TerrainType::PassabilityType::SURFACE; + if (s == "SUB") info.passabilityType = TerrainType::PassabilityType::SUBTERRANEAN; } if(terr.second["river"].isNull()) { - info->river = River::NO_RIVER; + info.river = River::NO_RIVER; } else { - info->river = getRiverByCode(terr.second["river"].String())->id; + info.river = getRiverByCode(terr.second["river"].String())->id; } if(terr.second["horseSoundId"].isNull()) { - info->horseSoundId = Terrain::ROCK; //rock sound as default + info.horseSoundId = Terrain::ROCK; //rock sound as default } else { - info->horseSoundId = terr.second["horseSoundId"].Float(); + info.horseSoundId = static_cast(terr.second["horseSoundId"].Float()); } if(!terr.second["text"].isNull()) { - info->terrainText = terr.second["text"].String(); + info.terrainText = terr.second["text"].String(); } if(terr.second["code"].isNull()) { - info->typeCode = terr.first.substr(0, 2); + info.typeCode = terr.first.substr(0, 2); } else { - info->typeCode = terr.second["code"].String(); - assert(info->typeCode.length() == 2); + info.typeCode = terr.second["code"].String(); + assert(info.typeCode.length() == 2); } if(!terr.second["battleFields"].isNull()) { for(auto & t : terr.second["battleFields"].Vector()) { - info->battleFields.emplace_back(t.String()); + info.battleFields.emplace_back(t.String()); } } + info.transitionRequired = false; + if(!terr.second["transitionRequired"].isNull()) + { + info.transitionRequired = terr.second["transitionRequired"].Bool(); + } + + info.terrainViewPatterns = "normal"; + if(!terr.second["terrainViewPatterns"].isNull()) + { + info.terrainViewPatterns = terr.second["terrainViewPatterns"].String(); + } + + if(!terr.second["originalTerrainId"].isNull()) + { + //place in reserved slot + info.id = (TTerrainId)(terr.second["originalTerrainId"].Float()); + objects[info.id] = info; + } + else + { + //append at the end + info.id = static_cast(objects.size()); + objects.push_back(info); + } + TTerrainId id = info.id; + + //Update terrain with this id in the future, after all terrain types are populated + if(!terr.second["prohibitTransitions"].isNull()) { for(auto & t : terr.second["prohibitTransitions"].Vector()) { std::string prohibitedTerrainName = t.String(); - resolveLater.push_back([this, prohibitedTerrainName, info]() + resolveLater.push_back([this, prohibitedTerrainName, id]() { - info->prohibitTransitions.emplace_back(getInfoByName(prohibitedTerrainName)->id); + //FIXME: is that reference to the element in vector? + objects[id].prohibitTransitions.emplace_back(getInfoByName(prohibitedTerrainName)->id); }); } } - - info->transitionRequired = false; - if(!terr.second["transitionRequired"].isNull()) - { - info->transitionRequired = terr.second["transitionRequired"].Bool(); - } - - info->terrainViewPatterns = "normal"; - if(!terr.second["terrainViewPatterns"].isNull()) - { - info->terrainViewPatterns = terr.second["terrainViewPatterns"].String(); - } - TTerrainId id = Terrain::WRONG; - if(!terr.second["originalTerrainId"].isNull()) + if(terr.second["rockTerrain"].isNull()) { - //place in reserved slot - id = (TTerrainId)(terr.second["originalTerrainId"].Float()); - objects[id] = info; + objects[id].rockTerrain = Terrain::ROCK; } else { - //append at the end - id = objects.size(); - objects.push_back(info); + auto rockTerrainName = terr.second["rockTerrain"].String(); + resolveLater.push_back([this, rockTerrainName, id]() + { + //FIXME: is that reference to the element in vector? + objects[id].rockTerrain = getInfoByName(rockTerrainName)->id; + }); } - info->id = id; } } for (size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++) { //Make sure that original terrains are loaded - assert(objects(i)); + assert(objects(i).id != Terrain::WRONG); } recreateTerrainMaps(); @@ -243,7 +242,7 @@ void TerrainTypeHandler::initRivers(const std::vector & allConfigs) } else { - info->id = riverTypes.size(); + info->id = static_cast(riverTypes.size()); riverTypes.push_back(info); } } @@ -278,7 +277,7 @@ void TerrainTypeHandler::initRoads(const std::vector & allConfigs) } else { - info->id = roadTypes.size(); + info->id = static_cast(roadTypes.size()); roadTypes.push_back(info); } } @@ -289,8 +288,12 @@ void TerrainTypeHandler::initRoads(const std::vector & allConfigs) void TerrainTypeHandler::recreateTerrainMaps() { - for (const TerrainType * terrainInfo : objects) + //This assumes the vector will never be updated or reallocated in the future + + for (size_t i = 0; i < objects.size(); i++) { + const auto * terrainInfo = &objects[i]; + terrainInfoByName[terrainInfo->name] = terrainInfo; terrainInfoByCode[terrainInfo->typeCode] = terrainInfo; terrainInfoById[terrainInfo->id] = terrainInfo; @@ -323,8 +326,9 @@ void TerrainTypeHandler::recreateRoadMaps() } } -const std::vector & TerrainTypeHandler::terrains() const +const std::vector & TerrainTypeHandler::terrains() const { + //FIXME: somehow make it non-copyable? Pointers must point t original data and not its copy return objects; } @@ -394,10 +398,13 @@ TerrainType::operator std::string() const } TerrainType::TerrainType(const std::string& _name): + minimapBlocked({0,0,0}), //black + minimapUnblocked({ 128,128,128 }), //grey name(_name), + river(River::NO_RIVER), id(Terrain::WRONG), rockTerrain(Terrain::ROCK), - moveCost(100), + moveCost(GameConstants::BASE_MOVEMENT_COST), horseSoundId(0), passabilityType(0), transitionRequired(false) @@ -406,8 +413,25 @@ TerrainType::TerrainType(const std::string& _name): TerrainType& TerrainType::operator=(const TerrainType & other) { - //TODO + battleFields = other.battleFields; + prohibitTransitions = other.prohibitTransitions; + minimapBlocked = other.minimapBlocked; + minimapUnblocked = other.minimapUnblocked; name = other.name; + musicFilename = other.musicFilename; + tilesFilename = other.tilesFilename; + terrainText = other.terrainText; + typeCode = other.typeCode; + terrainViewPatterns = other.terrainViewPatterns; + rockTerrain = other.rockTerrain; + river = other.river; + + id = other.id; + moveCost = other.moveCost; + horseSoundId = other.horseSoundId; + passabilityType = other.passabilityType; + transitionRequired = other.transitionRequired; + return *this; } @@ -466,6 +490,7 @@ RiverType::RiverType(const std::string & fileName, const std::string & code, TRi RoadType::RoadType(const std::string& fileName, const std::string& code, TRoadId id): fileName(fileName), code(code), - id(id) + id(id), + movementCost(GameConstants::BASE_MOVEMENT_COST) { } \ No newline at end of file diff --git a/lib/Terrain.h b/lib/Terrain.h index cf4b06f1c..a4da258c7 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -135,7 +135,7 @@ public: TerrainTypeHandler(); ~TerrainTypeHandler(); - const std::vector & terrains() const; + const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; const TerrainType * getInfoByCode(const std::string & terrainCode) const; const TerrainType * getInfoById(TTerrainId id) const; @@ -166,7 +166,7 @@ public: private: - std::vector objects; + std::vector objects; std::vector riverTypes; std::vector roadTypes; diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index 26f1ccd41..dd444a53f 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -165,10 +165,10 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) //assuming that object can be placed on other land terrains if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER)) { - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - if(terrain->isLand() && terrain->isPassable()) - allowedTerrains.insert(terrain->id); + if(terrain.isLand() && terrain.isPassable()) + allowedTerrains.insert(terrain.id); } } @@ -238,10 +238,10 @@ void ObjectTemplate::readMap(CBinaryReader & reader) //assuming that object can be placed on other land terrains if(allowedTerrains.size() >= 8 && !allowedTerrains.count(Terrain::WATER)) { - for(const auto * terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - if(terrain->isLand() && terrain->isPassable()) - allowedTerrains.insert(terrain->id); + if(terrain.isLand() && terrain.isPassable()) + allowedTerrains.insert(terrain.id); } } @@ -289,11 +289,11 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) } else { - for(const auto* terrain : VLC->terrainTypeHandler->terrains()) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - if(!terrain->isPassable() || terrain->isWater()) + if(!terrain.isPassable() || terrain.isWater()) continue; - allowedTerrains.insert(terrain->id); + allowedTerrains.insert(terrain.id); } } diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 4392beb24..94178d21a 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -95,7 +95,7 @@ void CDrawTerrainOperation::execute() for(const auto & pos : terrainSel.getSelectedItems()) { auto & tile = map->getTile(pos); - tile.terType = VLC->terrainTypeHandler->terrains()[terType]; + tile.terType = const_cast(&VLC->terrainTypeHandler->terrains()[terType]); invalidateTerrainViews(pos); } diff --git a/lib/mapping/MapEditUtils.cpp b/lib/mapping/MapEditUtils.cpp index 603d009d7..7a5be3e33 100644 --- a/lib/mapping/MapEditUtils.cpp +++ b/lib/mapping/MapEditUtils.cpp @@ -270,7 +270,7 @@ CTerrainViewPatternConfig::~CTerrainViewPatternConfig() const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TTerrainId terrain) const { - auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain]->terrainViewPatterns); + auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain].terrainViewPatterns); if (iter == terrainViewPatterns.end()) return terrainViewPatterns.at("normal"); return iter->second; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index a2705dc20..481ba7833 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -921,9 +921,9 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot) void CMapLoaderH3M::readTerrain() { map->initTerrain(); - const auto terrains = VLC->terrainTypeHandler->terrains(); - const auto rivers = VLC->terrainTypeHandler->rivers(); - const auto roads = VLC->terrainTypeHandler->roads(); + const auto & terrains = VLC->terrainTypeHandler->terrains(); + const auto & rivers = VLC->terrainTypeHandler->rivers(); + const auto & roads = VLC->terrainTypeHandler->roads(); // Read terrain int3 pos; @@ -935,7 +935,7 @@ void CMapLoaderH3M::readTerrain() for(pos.x = 0; pos.x < map->width; pos.x++) { auto & tile = map->getTile(pos); - tile.terType = terrains[reader.readUInt8()]; + tile.terType = const_cast(&terrains[reader.readUInt8()]); tile.terView = reader.readUInt8(); tile.riverType = rivers[reader.readUInt8()]; tile.riverDir = reader.readUInt8(); diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index 7b4439227..423742a70 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -73,7 +73,7 @@ public: static std::string encode(const si32 index) { const auto& terrains = VLC->terrainTypeHandler->terrains(); - return (index >=0 && index < terrains.size()) ? terrains[index]->name : ""; + return (index >=0 && index < terrains.size()) ? terrains[index].name : ""; } }; @@ -150,9 +150,9 @@ ZoneOptions::ZoneOptions() terrainTypeLikeZone(NO_ZONE), treasureLikeZone(NO_ZONE) { - for(const auto * terr : VLC->terrainTypeHandler->terrains()) - if(terr->isLand() && terr->isPassable()) - terrainTypes.insert(terr->id); + for(const auto & terr : VLC->terrainTypeHandler->terrains()) + if(terr.isLand() && terr.isPassable()) + terrainTypes.insert(terr.id); } ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other) diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index e21d0e136..fa4b6daeb 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -198,8 +198,8 @@ void CZonePlacer::prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const } else { - const auto * terrainType = VLC->terrainTypeHandler->terrains()[tt]; - if(terrainType->isUnderground() && !terrainType->isSurface()) + const auto & terrainType = VLC->terrainTypeHandler->terrains()[tt]; + if(terrainType.isUnderground() && !terrainType.isSurface()) { //underground only zonesOnLevel[1]++; diff --git a/lib/rmg/ConnectionsPlacer.cpp b/lib/rmg/ConnectionsPlacer.cpp index 9886bf4c3..89af592e9 100644 --- a/lib/rmg/ConnectionsPlacer.cpp +++ b/lib/rmg/ConnectionsPlacer.cpp @@ -83,8 +83,8 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con //1. Try to make direct connection //Do if it's not prohibited by terrain settings const auto& terrains = VLC->terrainTypeHandler->terrains(); - bool directProhibited = vstd::contains(terrains[zone.getTerrainType()]->prohibitTransitions, otherZone->getTerrainType()) - || vstd::contains(terrains[otherZone->getTerrainType()]->prohibitTransitions, zone.getTerrainType()); + bool directProhibited = vstd::contains(terrains[zone.getTerrainType()].prohibitTransitions, otherZone->getTerrainType()) + || vstd::contains(terrains[otherZone->getTerrainType()].prohibitTransitions, zone.getTerrainType()); auto directConnectionIterator = dNeighbourZones.find(otherZoneId); if(!directProhibited && directConnectionIterator != dNeighbourZones.end()) { diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 7195cde00..d409de87d 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -117,9 +117,9 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) { //collect all water terrain types std::vector waterTerrains; - for(auto & terrain : VLC->terrainTypeHandler->terrains()) - if(terrain->isWater()) - waterTerrains.push_back(terrain->id); + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) + if(terrain.isWater()) + waterTerrains.push_back(terrain.id); zone.setTerrainType(*RandomGeneratorUtil::nextItem(waterTerrains, gen.rand)); } @@ -135,18 +135,18 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) } //Now, replace disallowed terrains on surface and in the underground - const auto* terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; + const auto & terrainType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]; if(zone.isUnderground()) { - if(!terrainType->isUnderground()) + if(!terrainType.isUnderground()) { zone.setTerrainType(Terrain::SUBTERRANEAN); } } else { - if (!terrainType->isSurface()) + if (!terrainType.isSurface()) { zone.setTerrainType(Terrain::DIRT); } diff --git a/lib/rmg/RiverPlacer.cpp b/lib/rmg/RiverPlacer.cpp index 0ce29b0e4..5e731dbf8 100644 --- a/lib/rmg/RiverPlacer.cpp +++ b/lib/rmg/RiverPlacer.cpp @@ -85,7 +85,7 @@ void RiverPlacer::init() void RiverPlacer::drawRivers() { map.getEditManager()->getTerrainSelection().setSelection(rivers.getTilesVector()); - map.getEditManager()->drawRiver(VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river, &generator.rand); + map.getEditManager()->drawRiver(VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river, &generator.rand); } char RiverPlacer::dump(const int3 & t) @@ -194,7 +194,7 @@ void RiverPlacer::preprocess() //calculate delta positions if(connectedToWaterZoneId > -1) { - auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; + auto river = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river; auto & a = neighbourZonesTiles[connectedToWaterZoneId]; auto availableArea = zone.areaPossible() + zone.freePaths(); for(auto & tileToProcess : availableArea.getTilesVector()) @@ -320,7 +320,7 @@ void RiverPlacer::preprocess() void RiverPlacer::connectRiver(const int3 & tile) { - auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->river; + auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river; auto river = VLC->terrainTypeHandler->rivers()[riverType]; if(river->id == River::NO_RIVER) return; diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index 68d5a7754..2e670778a 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -108,7 +108,7 @@ void Object::Instance::setTemplate(const TTerrainId & terrain) if(dObject.appearance->id == Obj::NO_OBJ) { auto templates = VLC->objtypeh->getHandlerFor(dObject.ID, dObject.subID)->getTemplates(terrain); - auto terrainName = VLC->terrainTypeHandler->terrains()[terrain]->name; + auto terrainName = VLC->terrainTypeHandler->terrains()[terrain].name; if (templates.empty()) { throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") % diff --git a/lib/rmg/RockPlacer.cpp b/lib/rmg/RockPlacer.cpp index 358a4269d..48c419fa0 100644 --- a/lib/rmg/RockPlacer.cpp +++ b/lib/rmg/RockPlacer.cpp @@ -22,8 +22,8 @@ void RockPlacer::process() { - rockTerrain = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()]->rockTerrain; - assert(!VLC->terrainTypeHandler->terrains()[rockTerrain]->isPassable()); + rockTerrain = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].rockTerrain; + assert(!VLC->terrainTypeHandler->terrains()[rockTerrain].isPassable()); accessibleArea = zone.freePaths() + zone.areaUsed(); if(auto * m = zone.getModificator()) From 11dd71515a68c3bfd32868b6758be87cecfa4376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Mon, 26 Sep 2022 09:18:01 +0200 Subject: [PATCH 22/74] comment --- client/CMusicHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/CMusicHandler.cpp b/client/CMusicHandler.cpp index eead0ee36..97160bded 100644 --- a/client/CMusicHandler.cpp +++ b/client/CMusicHandler.cpp @@ -101,7 +101,7 @@ CSoundHandler::CSoundHandler(): }; //predefine terrain set - //TODO: need refactoring - support custom sounds for new terrains and load from json + //TODO: support custom sounds for new terrains and load from json horseSounds = { {Terrain::DIRT, soundBase::horseDirt}, From f804f8a326ba7e8c42af564d7887e593341f815e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Mon, 26 Sep 2022 09:51:36 +0200 Subject: [PATCH 23/74] Store RiverType by value, handle by reference --- client/mapHandler.cpp | 4 +-- lib/GameConstants.h | 1 + lib/Terrain.cpp | 41 ++++++++++++++++------------- lib/Terrain.h | 8 +++--- lib/mapping/CDrawRoadsOperation.cpp | 2 +- lib/mapping/CMap.cpp | 2 +- lib/mapping/MapFormatH3M.cpp | 2 +- lib/rmg/RiverPlacer.cpp | 9 ++++--- 8 files changed, 39 insertions(+), 30 deletions(-) diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index e6177153b..c11ca7ad7 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -180,9 +180,9 @@ void CMapHandler::initTerrainGraphics() { terrainFiles[terrain.name] = terrain.tilesFilename; } - for(const auto * river : VLC->terrainTypeHandler->rivers()) + for(const auto & river : VLC->terrainTypeHandler->rivers()) { - riverFiles[river->fileName] = river->fileName; + riverFiles[river.fileName] = river.fileName; } for(const auto * road : VLC->terrainTypeHandler->roads()) { diff --git a/lib/GameConstants.h b/lib/GameConstants.h index b0835ed07..491b42fe8 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -871,6 +871,7 @@ namespace River enum ERiver : ui8 { NO_RIVER = 0, + FIRST_REGULAR_RIVER = 1, WATER_RIVER = 1, ICY_RIVER = 2, MUD_RIVER = 3, diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index a95e322a2..241e7e9af 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -31,10 +31,6 @@ TerrainTypeHandler::TerrainTypeHandler() TerrainTypeHandler::~TerrainTypeHandler() { - for (const auto * river : riverTypes) - { - delete river; - } for (const auto * road : roadTypes) { delete road; @@ -217,8 +213,8 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig void TerrainTypeHandler::initRivers(const std::vector & allConfigs) { - riverTypes.resize(River::ORIGINAL_RIVER_COUNT, nullptr); //make space for original rivers - riverTypes[River::NO_RIVER] = new RiverType(); //default + riverTypes.resize(River::ORIGINAL_RIVER_COUNT); //make space for original rivers + //First object will be default for (auto & mod : allConfigs) { @@ -228,21 +224,21 @@ void TerrainTypeHandler::initRivers(const std::vector & allConfigs) JsonNode rivs(mod, ResourceID("config/rivers.json")); for (auto & river : rivs.Struct()) { - auto * info = new RiverType(); + RiverType info; - info->fileName = river.second["animation"].String(); - info->code = river.second["code"].String(); - info->deltaName = river.second["delta"].String(); + info.fileName = river.second["animation"].String(); + info.code = river.second["code"].String(); + info.deltaName = river.second["delta"].String(); //info->movementCost = river.second["moveCost"].Integer(); if (!river.second["originalRiverId"].isNull()) { - info->id = static_cast(river.second["originalRiverId"].Float()); - riverTypes[info->id] = info; + info.id = static_cast(river.second["originalRiverId"].Float()); + riverTypes[info.id] = info; } else { - info->id = static_cast(riverTypes.size()); + info.id = static_cast(riverTypes.size()); riverTypes.push_back(info); } } @@ -302,10 +298,9 @@ void TerrainTypeHandler::recreateTerrainMaps() void TerrainTypeHandler::recreateRiverMaps() { - for (const RiverType * riverInfo : riverTypes) + for (size_t i = River::FIRST_REGULAR_RIVER ; i < riverTypes.size(); i++) { - if (riverInfo->id == River::NO_RIVER) - continue; + const auto* riverInfo = &riverTypes[i]; riverInfoByName[riverInfo->fileName] = riverInfo; riverInfoByCode[riverInfo->code] = riverInfo; @@ -328,11 +323,11 @@ void TerrainTypeHandler::recreateRoadMaps() const std::vector & TerrainTypeHandler::terrains() const { - //FIXME: somehow make it non-copyable? Pointers must point t original data and not its copy + //FIXME: somehow make it non-copyable? Pointers must point to original data and not its copy return objects; } -const std::vector& TerrainTypeHandler::rivers() const +const std::vector& TerrainTypeHandler::rivers() const { return riverTypes; } @@ -487,6 +482,16 @@ RiverType::RiverType(const std::string & fileName, const std::string & code, TRi { } +RiverType& RiverType::operator=(const RiverType& other) +{ + fileName = other.fileName; + code = other.code; + deltaName = other.deltaName; + id = other.id; + + return *this; +} + RoadType::RoadType(const std::string& fileName, const std::string& code, TRoadId id): fileName(fileName), code(code), diff --git a/lib/Terrain.h b/lib/Terrain.h index a4da258c7..505e5c34f 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -49,7 +49,7 @@ public: TerrainType(const std::string & name = ""); - TerrainType& operator=(const TerrainType & _type); + TerrainType& operator=(const TerrainType & other); bool operator==(const TerrainType & other); bool operator!=(const TerrainType & other); @@ -98,6 +98,8 @@ public: RiverType(const std::string & fileName = "", const std::string & code = "", TRiverId id = River::NO_RIVER); + RiverType& operator=(const RiverType & other); + template void serialize(Handler& h, const int version) { h & fileName; @@ -140,7 +142,7 @@ public: const TerrainType * getInfoByCode(const std::string & terrainCode) const; const TerrainType * getInfoById(TTerrainId id) const; - const std::vector & rivers() const; + const std::vector & rivers() const; const RiverType * getRiverByName(const std::string & riverName) const; const RiverType * getRiverByCode(const std::string & riverCode) const; const RiverType * getRiverById(TRiverId id) const; @@ -167,7 +169,7 @@ public: private: std::vector objects; - std::vector riverTypes; + std::vector riverTypes; std::vector roadTypes; std::unordered_map terrainInfoByName; diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 3b624fa4f..9982584b5 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -341,7 +341,7 @@ void CDrawRoadsOperation::executeTile(TerrainTile & tile) void CDrawRiversOperation::executeTile(TerrainTile & tile) { - tile.riverType = VLC->terrainTypeHandler->rivers()[riverType]; + tile.riverType = const_cast(&VLC->terrainTypeHandler->rivers()[riverType]); } bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 8c8116056..b6f62d06b 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -126,7 +126,7 @@ CCastleEvent::CCastleEvent() : town(nullptr) TerrainTile::TerrainTile(): terType(nullptr), terView(0), - riverType(VLC->terrainTypeHandler->rivers()[0]), + riverType(const_cast(&VLC->terrainTypeHandler->rivers()[0])), riverDir(0), roadType(VLC->terrainTypeHandler->roads()[0]), roadDir(0), diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 481ba7833..fb2eb65eb 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -937,7 +937,7 @@ void CMapLoaderH3M::readTerrain() auto & tile = map->getTile(pos); tile.terType = const_cast(&terrains[reader.readUInt8()]); tile.terView = reader.readUInt8(); - tile.riverType = rivers[reader.readUInt8()]; + tile.riverType = const_cast(&rivers[reader.readUInt8()]); tile.riverDir = reader.readUInt8(); tile.roadType = roads[reader.readUInt8()]; tile.roadDir = reader.readUInt8(); diff --git a/lib/rmg/RiverPlacer.cpp b/lib/rmg/RiverPlacer.cpp index 5e731dbf8..cdcca8d55 100644 --- a/lib/rmg/RiverPlacer.cpp +++ b/lib/rmg/RiverPlacer.cpp @@ -321,8 +321,8 @@ void RiverPlacer::preprocess() void RiverPlacer::connectRiver(const int3 & tile) { auto riverType = VLC->terrainTypeHandler->terrains()[zone.getTerrainType()].river; - auto river = VLC->terrainTypeHandler->rivers()[riverType]; - if(river->id == River::NO_RIVER) + const auto & river = VLC->terrainTypeHandler->rivers()[riverType]; + if(river.id == River::NO_RIVER) return; rmg::Area roads; @@ -379,9 +379,10 @@ void RiverPlacer::connectRiver(const int3 & tile) if(tmplates.size() > 3) { if(tmplates.size() % 4 != 0) - throw rmgException(boost::to_string(boost::format("River templates for (%d,%d) at terrain %s, river %s are incorrect") % RIVER_DELTA_ID % RIVER_DELTA_SUBTYPE % zone.getTerrainType() % river)); + throw rmgException(boost::to_string(boost::format("River templates for (%d,%d) at terrain %s, river %s are incorrect") % + RIVER_DELTA_ID % RIVER_DELTA_SUBTYPE % zone.getTerrainType() % river.code)); - std::string targetTemplateName = river->deltaName + std::to_string(deltaOrientations[pos]) + ".def"; + std::string targetTemplateName = river.deltaName + std::to_string(deltaOrientations[pos]) + ".def"; for(auto & templ : tmplates) { if(templ->animationFile == targetTemplateName) From 25f66097ccfdbd11b8dd8d93f3f37577b9c8ff8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Mon, 26 Sep 2022 10:20:39 +0200 Subject: [PATCH 24/74] Handle RoadType by value / reference --- client/mapHandler.cpp | 6 +-- lib/GameConstants.h | 1 + lib/Terrain.cpp | 66 ++++++++++++++--------------- lib/Terrain.h | 8 ++-- lib/mapping/CDrawRoadsOperation.cpp | 2 +- lib/mapping/CMap.cpp | 2 +- lib/mapping/MapFormatH3M.cpp | 2 +- 7 files changed, 45 insertions(+), 42 deletions(-) diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index c11ca7ad7..922bc1103 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -172,7 +172,7 @@ void CMapHandler::initTerrainGraphics() } }; - //TODO: use if as a key + //TODO: use id as a key std::map terrainFiles; std::map riverFiles; std::map roadFiles; @@ -184,9 +184,9 @@ void CMapHandler::initTerrainGraphics() { riverFiles[river.fileName] = river.fileName; } - for(const auto * road : VLC->terrainTypeHandler->roads()) + for(const auto & road : VLC->terrainTypeHandler->roads()) { - roadFiles[road->fileName] = road->fileName; + roadFiles[road.fileName] = road.fileName; } loadFlipped(terrainAnimations, terrainImages, terrainFiles); diff --git a/lib/GameConstants.h b/lib/GameConstants.h index 491b42fe8..69913e496 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -859,6 +859,7 @@ namespace Road enum ERoad : ui8 { NO_ROAD = 0, + FIRST_REGULAR_ROAD = 1, DIRT_ROAD = 1, GRAVEL_ROAD = 2, COBBLESTONE_ROAD = 3, diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 241e7e9af..2955b58fc 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -29,14 +29,6 @@ TerrainTypeHandler::TerrainTypeHandler() initTerrains(allConfigs); //maps will be populated inside } -TerrainTypeHandler::~TerrainTypeHandler() -{ - for (const auto * road : roadTypes) - { - delete road; - } -} - void TerrainTypeHandler::initTerrains(const std::vector & allConfigs) { std::vector> resolveLater; @@ -78,7 +70,7 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig } else if (terr.second["type"].getType() == JsonNode::JsonType::DATA_VECTOR) { - for (const auto& node : terr.second["type"].Vector()) + for(const auto& node : terr.second["type"].Vector()) { //Set bits auto s = node.String(); @@ -197,7 +189,7 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig } } - for (size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++) + for(size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++) { //Make sure that original terrains are loaded assert(objects(i).id != Terrain::WRONG); @@ -205,7 +197,7 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig recreateTerrainMaps(); - for (auto& functor : resolveLater) + for(auto& functor : resolveLater) { functor(); } @@ -214,22 +206,21 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig void TerrainTypeHandler::initRivers(const std::vector & allConfigs) { riverTypes.resize(River::ORIGINAL_RIVER_COUNT); //make space for original rivers - //First object will be default + //First object will be default NO_RIVER - for (auto & mod : allConfigs) + for(auto & mod : allConfigs) { if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/rivers.json"))) continue; JsonNode rivs(mod, ResourceID("config/rivers.json")); - for (auto & river : rivs.Struct()) + for(auto & river : rivs.Struct()) { RiverType info; info.fileName = river.second["animation"].String(); info.code = river.second["code"].String(); info.deltaName = river.second["delta"].String(); - //info->movementCost = river.second["moveCost"].Integer(); if (!river.second["originalRiverId"].isNull()) { @@ -249,31 +240,31 @@ void TerrainTypeHandler::initRivers(const std::vector & allConfigs) void TerrainTypeHandler::initRoads(const std::vector & allConfigs) { - roadTypes.resize(Road::ORIGINAL_ROAD_COUNT, nullptr); //make space for original rivers - roadTypes[Road::NO_ROAD] = new RoadType(); //default + roadTypes.resize(Road::ORIGINAL_ROAD_COUNT); //make space for original rivers + //first object will be default NO_ROAD - for (auto & mod : allConfigs) + for(auto & mod : allConfigs) { if (!CResourceHandler::get(mod)->existsResource(ResourceID("config/roads.json"))) continue; JsonNode rds(mod, ResourceID("config/roads.json")); - for (auto & road : rds.Struct()) + for(auto & road : rds.Struct()) { - auto * info = new RoadType(); + RoadType info; - info->fileName = road.second["animation"].String(); - info->code = road.second["code"].String(); - info->movementCost = static_cast(road.second["moveCost"].Float()); + info.fileName = road.second["animation"].String(); + info.code = road.second["code"].String(); + info.movementCost = static_cast(road.second["moveCost"].Float()); if (!road.second["originalRoadId"].isNull()) { - info->id = static_cast(road.second["originalRoadId"].Float()); - roadTypes[info->id] = info; + info.id = static_cast(road.second["originalRoadId"].Float()); + roadTypes[info.id] = info; } else { - info->id = static_cast(roadTypes.size()); + info.id = static_cast(roadTypes.size()); roadTypes.push_back(info); } } @@ -286,7 +277,7 @@ void TerrainTypeHandler::recreateTerrainMaps() { //This assumes the vector will never be updated or reallocated in the future - for (size_t i = 0; i < objects.size(); i++) + for(size_t i = 0; i < objects.size(); i++) { const auto * terrainInfo = &objects[i]; @@ -298,9 +289,9 @@ void TerrainTypeHandler::recreateTerrainMaps() void TerrainTypeHandler::recreateRiverMaps() { - for (size_t i = River::FIRST_REGULAR_RIVER ; i < riverTypes.size(); i++) + for(size_t i = River::FIRST_REGULAR_RIVER ; i < riverTypes.size(); i++) { - const auto* riverInfo = &riverTypes[i]; + const auto * riverInfo = &riverTypes[i]; riverInfoByName[riverInfo->fileName] = riverInfo; riverInfoByCode[riverInfo->code] = riverInfo; @@ -310,10 +301,9 @@ void TerrainTypeHandler::recreateRiverMaps() void TerrainTypeHandler::recreateRoadMaps() { - for (const RoadType * roadInfo : roadTypes) + for(size_t i = Road::FIRST_REGULAR_ROAD ; i < roadTypes.size(); i++) { - if (roadInfo->id == Road::NO_ROAD) - continue; + const auto * roadInfo = &roadTypes[i]; roadInfoByName[roadInfo->fileName] = roadInfo; roadInfoByCode[roadInfo->code] = roadInfo; @@ -332,7 +322,7 @@ const std::vector& TerrainTypeHandler::rivers() const return riverTypes; } -const std::vector& TerrainTypeHandler::roads() const +const std::vector& TerrainTypeHandler::roads() const { return roadTypes; } @@ -498,4 +488,14 @@ RoadType::RoadType(const std::string& fileName, const std::string& code, TRoadId id(id), movementCost(GameConstants::BASE_MOVEMENT_COST) { +} + +RoadType& RoadType::operator=(const RoadType& other) +{ + fileName = other.fileName; + code = other.code; + id = other.id; + movementCost = other.movementCost; + + return *this; } \ No newline at end of file diff --git a/lib/Terrain.h b/lib/Terrain.h index 505e5c34f..1bc5939fb 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -119,6 +119,8 @@ public: RoadType(const std::string & fileName = "", const std::string& code = "", TRoadId id = Road::NO_ROAD); + RoadType& operator=(const RoadType & other); + template void serialize(Handler& h, const int version) { h & fileName; @@ -135,7 +137,7 @@ class DLL_LINKAGE TerrainTypeHandler //TODO: public IHandlerBase ? public: TerrainTypeHandler(); - ~TerrainTypeHandler(); + ~TerrainTypeHandler() {}; const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; @@ -147,7 +149,7 @@ public: const RiverType * getRiverByCode(const std::string & riverCode) const; const RiverType * getRiverById(TRiverId id) const; - const std::vector & roads() const; + const std::vector & roads() const; const RoadType * getRoadByName(const std::string & roadName) const; const RoadType * getRoadByCode(const std::string & roadCode) const; const RoadType * getRoadById(TRoadId id) const; @@ -170,7 +172,7 @@ private: std::vector objects; std::vector riverTypes; - std::vector roadTypes; + std::vector roadTypes; std::unordered_map terrainInfoByName; std::unordered_map terrainInfoByCode; diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 9982584b5..e87ea7cf2 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -336,7 +336,7 @@ std::string CDrawRiversOperation::getLabel() const void CDrawRoadsOperation::executeTile(TerrainTile & tile) { - tile.roadType = VLC->terrainTypeHandler->roads()[roadType]; + tile.roadType = const_cast(&VLC->terrainTypeHandler->roads()[roadType]); } void CDrawRiversOperation::executeTile(TerrainTile & tile) diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index b6f62d06b..43ff2b08e 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -128,7 +128,7 @@ TerrainTile::TerrainTile(): terView(0), riverType(const_cast(&VLC->terrainTypeHandler->rivers()[0])), riverDir(0), - roadType(VLC->terrainTypeHandler->roads()[0]), + roadType(const_cast(&VLC->terrainTypeHandler->roads()[0])), roadDir(0), extTileFlags(0), visitable(false), diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index fb2eb65eb..0bf3c66d8 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -939,7 +939,7 @@ void CMapLoaderH3M::readTerrain() tile.terView = reader.readUInt8(); tile.riverType = const_cast(&rivers[reader.readUInt8()]); tile.riverDir = reader.readUInt8(); - tile.roadType = roads[reader.readUInt8()]; + tile.roadType = const_cast(&roads[reader.readUInt8()]); tile.roadDir = reader.readUInt8(); tile.extTileFlags = reader.readUInt8(); tile.blocked = ((!tile.terType->isPassable() || tile.terType->id == Terrain::BORDER ) ? true : false); //underground tiles are always blocked From bbf08afb3d86bb1689b93a3983fe1bf3db965de4 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 24 Sep 2022 17:29:39 +0300 Subject: [PATCH 25/74] fix possible memory leak --- lib/NetPacksLib.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 3fa981434..e0a200a7a 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -916,10 +916,8 @@ DLL_LINKAGE void SwapStacks::applyGs(CGameState * gs) DLL_LINKAGE void InsertNewStack::applyGs(CGameState *gs) { - auto s = new CStackInstance(type, count); - auto obj = gs->getArmyInstance(army); - if(obj) - obj->putStack(slot, s); + if(auto obj = gs->getArmyInstance(army)) + obj->putStack(slot, new CStackInstance(type, count)); else logNetwork->error("[CRITICAL] InsertNewStack: invalid army object %d, possible game state corruption.", army.getNum()); } From 802147c5b76e1923246889782b38803dd206c2eb Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 24 Sep 2022 17:30:00 +0300 Subject: [PATCH 26/74] add some asserts that shouldn't fire --- AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp | 1 + client/CMessage.cpp | 1 + lib/spells/ISpellMechanics.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp index daea0c741..0b65c4eac 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp @@ -133,6 +133,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector } } + assert(closestWay || waysToVisitObj.empty()); for(auto way : waysToVisitObj) { way->closestWayRatio diff --git a/client/CMessage.cpp b/client/CMessage.cpp index 2159d7a81..fcd29b93b 100644 --- a/client/CMessage.cpp +++ b/client/CMessage.cpp @@ -208,6 +208,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play const int sizes[][2] = {{400, 125}, {500, 150}, {600, 200}, {480, 400}}; + assert(ret && ret->text); for(int i = 0; i < ARRAY_COUNT(sizes) && sizes[i][0] < screen->w - 150 diff --git a/lib/spells/ISpellMechanics.cpp b/lib/spells/ISpellMechanics.cpp index 29578ff56..db8b22bcf 100644 --- a/lib/spells/ISpellMechanics.cpp +++ b/lib/spells/ISpellMechanics.cpp @@ -490,6 +490,7 @@ bool BaseMechanics::adaptGenericProblem(Problem & target) const MetaString text; // %s recites the incantations but they seem to have no effect. text.addTxt(MetaString::GENERAL_TXT, 541); + assert(caster); caster->getCasterName(text); target.add(std::move(text), spells::Problem::NORMAL); From 380100f90b68f69930691bf229b85fb7acef8e56 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 17:25:18 +0300 Subject: [PATCH 27/74] compile Version.cpp only when ENABLE_GITVERSION is ON Co-authored-by: Johannes Schauer Marin Rodrigues --- cmake_modules/VCMI_lib.cmake | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index b143c860e..a3e8d48da 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -2,7 +2,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) set(MAIN_LIB_DIR "${CMAKE_SOURCE_DIR}/lib") set(lib_SRCS ${MAIN_LIB_DIR}/StdInc.cpp - ${CMAKE_BINARY_DIR}/Version.cpp ${MAIN_LIB_DIR}/battle/AccessibilityInfo.cpp ${MAIN_LIB_DIR}/battle/BattleAction.cpp @@ -196,9 +195,12 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ) # Version.cpp is a generated file - set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp - PROPERTIES GENERATED TRUE - ) + if(ENABLE_GITVERSION) + list(APPEND lib_SRCS ${CMAKE_BINARY_DIR}/Version.cpp) + set_source_files_properties(${CMAKE_BINARY_DIR}/Version.cpp + PROPERTIES GENERATED TRUE + ) + endif() set(lib_HEADERS ${CMAKE_SOURCE_DIR}/include/vstd/CLoggerBase.h From 95e3400eb90422409ec65f0f4a88318a21378c44 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 06:31:06 +0300 Subject: [PATCH 28/74] raise iOS deployment target to 12.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86e15c821..c918facbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,7 +171,7 @@ endif() if(APPLE_IOS) set(CMAKE_MACOSX_RPATH 1) - set(CMAKE_OSX_DEPLOYMENT_TARGET 10.0) + set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0) list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_PREFIX_PATH}") # required for Boost set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH FALSE) From 7a51527ede48ff8b37d99b614d343485ab01d20d Mon Sep 17 00:00:00 2001 From: Agoston Szepessy Date: Mon, 26 Sep 2022 20:57:51 -0700 Subject: [PATCH 29/74] Change issues link to github issues link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea125e563..4902670ad 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ VCMI is work-in-progress attempt to recreate engine for Heroes III, giving it ne * Homepage: https://vcmi.eu/ * Wiki: https://wiki.vcmi.eu/ * Forums: https://forum.vcmi.eu/ - * Bugtracker: https://bugs.vcmi.eu/ + * Bugtracker: https://github.com/vcmi/vcmi/issues * Slack: https://slack.vcmi.eu/ ## Installation guides From 70c51e43707cb6e7d1fcb38be4465fca2e85da10 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 07:01:16 +0300 Subject: [PATCH 30/74] iOS: don't compile unused function --- client/CMT.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/CMT.cpp b/client/CMT.cpp index 9a9139085..bfcef4aed 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -975,6 +975,7 @@ void playIntro() } } +#ifndef VCMI_IOS static bool checkVideoMode(int monitorIndex, int w, int h) { //we only check that our desired window size fits on screen @@ -996,6 +997,7 @@ static bool checkVideoMode(int monitorIndex, int w, int h) return false; } +#endif static void cleanupRenderer() { From 53ac61b52b65cfb97c2aaaa9f57dd66caa3c1bae Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 07:05:10 +0300 Subject: [PATCH 31/74] iOS: don't create unused CConsoleHandler --- client/CMT.cpp | 6 ++++++ launcher/mainwindow_moc.cpp | 2 ++ lib/logging/CLogger.cpp | 6 +++++- lib/logging/CLogger.h | 2 ++ server/CVCMIServer.cpp | 2 ++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index bfcef4aed..3d9382016 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -104,7 +104,9 @@ static po::variables_map vm; //static bool setResolution = false; //set by event handling thread after resolution is adjusted +#ifndef VCMI_IOS void processCommand(const std::string &message); +#endif static void setScreenRes(int w, int h, int bpp, bool fullscreen, int displayIndex, bool resetVideo=true); void playIntro(); static void mainLoop(); @@ -236,9 +238,11 @@ int main(int argc, char * argv[]) // Init old logging system and new (temporary) logging system CStopWatch total, pomtime; std::cout.flags(std::ios::unitbuf); +#ifndef VCMI_IOS console = new CConsoleHandler(); *console->cb = processCommand; console->start(); +#endif const bfs::path logPath = VCMIDirs::get().userLogsPath() / "VCMI_Client_log.txt"; logConfig = new CBasicLogConfigurator(logPath, console); @@ -553,6 +557,7 @@ void removeGUI() LOCPLINT = nullptr; } +#ifndef VCMI_IOS void processCommand(const std::string &message) { std::istringstream readed; @@ -965,6 +970,7 @@ void processCommand(const std::string &message) LOCPLINT->cb->sendMessage(message); }*/ } +#endif //plays intro, ends when intro is over or button has been pressed (handles events) void playIntro() diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index 82769300f..969b55747 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -27,7 +27,9 @@ void MainWindow::load() // This is important on Mac for relative paths to work inside DMG. QDir::setCurrent(QApplication::applicationDirPath()); +#ifndef VCMI_IOS console = new CConsoleHandler(); +#endif CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Launcher_log.txt", console); logConfig.configureDefault(); diff --git a/lib/logging/CLogger.cpp b/lib/logging/CLogger.cpp index 2fa3a933c..564e6a6de 100644 --- a/lib/logging/CLogger.cpp +++ b/lib/logging/CLogger.cpp @@ -346,7 +346,11 @@ EConsoleTextColor::EConsoleTextColor CColorMapping::getColorFor(const CLoggerDom throw std::runtime_error("failed to find color for requested domain/level pair"); } -CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(console), threshold(ELogLevel::INFO), coloredOutputEnabled(true) +CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : +#ifndef VCMI_IOS + console(console), +#endif + threshold(ELogLevel::INFO), coloredOutputEnabled(true) { formatter.setPattern("%m"); } diff --git a/lib/logging/CLogger.h b/lib/logging/CLogger.h index 4f5ee2773..1f602db51 100644 --- a/lib/logging/CLogger.h +++ b/lib/logging/CLogger.h @@ -198,7 +198,9 @@ public: void write(const LogRecord & record) override; private: +#ifndef VCMI_IOS CConsoleHandler * console; +#endif ELogLevel::ELogLevel threshold; bool coloredOutputEnabled; CLogFormatter formatter; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 6015608c7..742ff5194 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -935,7 +935,9 @@ int main(int argc, char * argv[]) signal(SIGSEGV, handleLinuxSignal); #endif +#ifndef VCMI_IOS console = new CConsoleHandler(); +#endif CBasicLogConfigurator logConfig(VCMIDirs::get().userLogsPath() / "VCMI_Server_log.txt", console); logConfig.configureDefault(); logGlobal->info(SERVER_NAME); From 1dc7ccb7d0efcef89457461c13e7f29d03f18544 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 07:06:17 +0300 Subject: [PATCH 32/74] remove declaration of non-existent function --- client/CPlayerInterface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 62463f048..af9287e0a 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -84,8 +84,6 @@ using namespace CSDL_Ext; -void processCommand(const std::string &message, CClient *&client); - extern std::queue SDLEventsQueue; extern boost::mutex eventsM; boost::recursive_mutex * CPlayerInterface::pim = new boost::recursive_mutex; From d38b6297f82129f6de3489412b0f3777795fa03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Tue, 27 Sep 2022 07:53:21 +0200 Subject: [PATCH 33/74] missing line --- lib/Terrain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index 6619f64b0..cbf67eda5 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -500,4 +500,6 @@ RoadType& RoadType::operator=(const RoadType& other) movementCost = other.movementCost; return *this; -} \ No newline at end of file +} + +VCMI_LIB_NAMESPACE_END \ No newline at end of file From f0b909f77267674bf40d8a8621a36a0de7251b0f Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:37:31 +0300 Subject: [PATCH 34/74] code improvement --- client/lobby/CSavingScreen.cpp | 4 --- client/lobby/CSavingScreen.h | 1 - client/windows/GUIClasses.cpp | 7 ++--- launcher/jsonutils.cpp | 30 +++++++-------------- launcher/modManager/cmodmanager.cpp | 4 +-- launcher/settingsView/csettingsview_moc.cpp | 28 +++++++++---------- 6 files changed, 29 insertions(+), 45 deletions(-) diff --git a/client/lobby/CSavingScreen.cpp b/client/lobby/CSavingScreen.cpp index 7632ac691..06071c533 100644 --- a/client/lobby/CSavingScreen.cpp +++ b/client/lobby/CSavingScreen.cpp @@ -44,10 +44,6 @@ CSavingScreen::CSavingScreen() buttonStart->assignedKeys.insert(SDLK_RETURN); } -CSavingScreen::~CSavingScreen() -{ -} - const CMapInfo * CSavingScreen::getMapInfo() { return localMi.get(); diff --git a/client/lobby/CSavingScreen.h b/client/lobby/CSavingScreen.h index ac966a457..b7ac05012 100644 --- a/client/lobby/CSavingScreen.h +++ b/client/lobby/CSavingScreen.h @@ -27,7 +27,6 @@ public: std::shared_ptr localMi; CSavingScreen(); - ~CSavingScreen(); void changeSelection(std::shared_ptr to); void saveGame(); diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 2afd8c033..33372b30b 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -562,10 +562,11 @@ void CSystemOptionsWindow::selectGameRes() std::vector items; const JsonNode & texts = CGI->generaltexth->localizedTexts["systemOptions"]["resolutionMenu"]; - for( config::CConfigHandler::GuiOptionsMap::value_type& value : conf.guiOptions) + for(const auto & it : conf.guiOptions) { - std::string resX = boost::lexical_cast(value.first.first); - std::string resY = boost::lexical_cast(value.first.second); + const auto & resolution = it.first; + std::string resX = boost::lexical_cast(resolution.first); + std::string resY = boost::lexical_cast(resolution.second); items.push_back(resX + 'x' + resY); } diff --git a/launcher/jsonutils.cpp b/launcher/jsonutils.cpp index ccf7bd629..fa19739db 100644 --- a/launcher/jsonutils.cpp +++ b/launcher/jsonutils.cpp @@ -16,7 +16,7 @@ static QVariantMap JsonToMap(const JsonMap & json) QVariantMap map; for(auto & entry : json) { - map.insert(QString::fromUtf8(entry.first.c_str()), JsonUtils::toVariant(entry.second)); + map.insert(QString::fromStdString(entry.first), JsonUtils::toVariant(entry.second)); } return map; } @@ -60,22 +60,16 @@ QVariant toVariant(const JsonNode & node) { switch(node.getType()) { - break; case JsonNode::JsonType::DATA_NULL: return QVariant(); - break; case JsonNode::JsonType::DATA_BOOL: return QVariant(node.Bool()); - break; case JsonNode::JsonType::DATA_FLOAT: return QVariant(node.Float()); - break; case JsonNode::JsonType::DATA_STRING: - return QVariant(QString::fromUtf8(node.String().c_str())); - break; + return QVariant(QString::fromStdString(node.String())); case JsonNode::JsonType::DATA_VECTOR: return JsonToList(node.Vector()); - break; case JsonNode::JsonType::DATA_STRUCT: return JsonToMap(node.Struct()); } @@ -85,19 +79,15 @@ QVariant toVariant(const JsonNode & node) QVariant JsonFromFile(QString filename) { QFile file(filename); - file.open(QFile::ReadOnly); - auto data = file.readAll(); + if(!file.open(QFile::ReadOnly)) + { + logGlobal->error("Failed to open file %s. Reason: %s", qUtf8Printable(filename), qUtf8Printable(file.errorString())); + return {}; + } - if(data.size() == 0) - { - logGlobal->error("Failed to open file %s", filename.toUtf8().data()); - return QVariant(); - } - else - { - JsonNode node(data.data(), data.size()); - return toVariant(node); - } + const auto data = file.readAll(); + JsonNode node(data.data(), data.size()); + return toVariant(node); } JsonNode toJson(QVariant object) diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index eea55af17..f5cb03627 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -291,7 +291,7 @@ bool CModManager::doInstallMod(QString modname, QString archivePath) bool CModManager::doUninstallMod(QString modname) { - ResourceID resID(std::string("Mods/") + modname.toUtf8().data(), EResType::DIRECTORY); + ResourceID resID(std::string("Mods/") + modname.toStdString(), EResType::DIRECTORY); // Get location of the mod, in case-insensitive way QString modDir = pathToQString(*CResourceHandler::get()->getResourceName(resID)); @@ -300,7 +300,7 @@ bool CModManager::doUninstallMod(QString modname) QDir modFullDir(modDir); if(!removeModDir(modDir)) - return addError(modname, "Mod is located in protected directory, plase remove it manually:\n" + modFullDir.absolutePath()); + return addError(modname, "Mod is located in protected directory, please remove it manually:\n" + modFullDir.absolutePath()); CResourceHandler::get("initial")->updateFilteredFiles([](const std::string &){ return true; }); loadMods(); diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 95c2a872a..58c71d378 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -19,6 +19,14 @@ #include "../../lib/CConfigHandler.h" #include "../../lib/VCMIDirs.h" +namespace +{ +QString resolutionToString(const QSize & resolution) +{ + return QString{"%1x%2"}.arg(resolution.width()).arg(resolution.height()); +} +} + /// List of encoding which can be selected from Launcher. /// Note that it is possible to specify enconding manually in settings.json static const std::string knownEncodingsList[] = //TODO: remove hardcode @@ -39,12 +47,7 @@ void CSettingsView::setDisplayList() QStringList list; for (const auto screen : QGuiApplication::screens()) - { - QString string; - const auto & rect = screen->geometry(); - QTextStream(&string) << screen->name() << " - " << rect.width() << "x" << rect.height(); - list << string; - } + list << QString{"%1 - %2"}.arg(screen->name(), resolutionToString(screen->size())); if(list.count() < 2) { @@ -79,15 +82,10 @@ void CSettingsView::loadSettings() ui->checkBoxFullScreen->setChecked(settings["video"]["realFullscreen"].Bool()); #endif - int friendlyAIIndex = ui->comboBoxFriendlyAI->findText(QString::fromUtf8(settings["server"]["friendlyAI"].String().c_str())); - int neutralAIIndex = ui->comboBoxNeutralAI->findText(QString::fromUtf8(settings["server"]["neutralAI"].String().c_str())); - int enemyAIIndex = ui->comboBoxEnemyAI->findText(QString::fromUtf8(settings["server"]["enemyAI"].String().c_str())); - int playerAIIndex = ui->comboBoxPlayerAI->findText(QString::fromUtf8(settings["server"]["playerAI"].String().c_str())); - - ui->comboBoxFriendlyAI->setCurrentIndex(friendlyAIIndex); - ui->comboBoxNeutralAI->setCurrentIndex(neutralAIIndex); - ui->comboBoxEnemyAI->setCurrentIndex(enemyAIIndex); - ui->comboBoxPlayerAI->setCurrentIndex(playerAIIndex); + ui->comboBoxFriendlyAI->setCurrentText(QString::fromStdString(settings["server"]["friendlyAI"].String())); + ui->comboBoxNeutralAI->setCurrentText(QString::fromStdString(settings["server"]["neutralAI"].String())); + ui->comboBoxEnemyAI->setCurrentText(QString::fromStdString(settings["server"]["enemyAI"].String())); + ui->comboBoxPlayerAI->setCurrentText(QString::fromStdString(settings["server"]["playerAI"].String())); ui->spinBoxNetworkPort->setValue(settings["server"]["port"].Integer()); From cfba8a537356f66028194c40a611b0a08ca8666c Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:39:10 +0300 Subject: [PATCH 35/74] replace deprecated signal --- launcher/settingsView/csettingsview_moc.cpp | 2 +- launcher/settingsView/csettingsview_moc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 58c71d378..75a4f382d 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -122,7 +122,7 @@ CSettingsView::~CSettingsView() } -void CSettingsView::on_comboBoxResolution_currentIndexChanged(const QString & arg1) +void CSettingsView::on_comboBoxResolution_currentTextChanged(const QString & arg1) { QStringList list = arg1.split("x"); diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index b2084a78a..56d4cc834 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -29,7 +29,7 @@ public: private slots: void on_checkBoxFullScreen_stateChanged(int state); - void on_comboBoxResolution_currentIndexChanged(const QString & arg1); + void on_comboBoxResolution_currentTextChanged(const QString & arg1); void on_comboBoxFullScreen_currentIndexChanged(int index); From 36cbb2f6057e671e602b5298d6cee1dd4a016e67 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:44:02 +0300 Subject: [PATCH 36/74] make Display Index combobox empty by default --- launcher/settingsView/csettingsview_moc.cpp | 1 - launcher/settingsView/csettingsview_moc.ui | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 75a4f382d..234980242 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -57,7 +57,6 @@ void CSettingsView::setDisplayList() else { int displayIndex = settings["video"]["displayIndex"].Integer(); - ui->comboBoxDisplayIndex->clear(); ui->comboBoxDisplayIndex->addItems(list); ui->comboBoxDisplayIndex->setCurrentIndex(displayIndex); } diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index ece3135b5..cf5b3135d 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -417,13 +417,7 @@ - - - - 0 - - - + From 9aad1ae95e34f48eee1cd3eaf140a1af43dd0744 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:38:37 +0300 Subject: [PATCH 37/74] handle integer type in vcmi <-> Qt JSON interoperability --- launcher/jsonutils.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/launcher/jsonutils.cpp b/launcher/jsonutils.cpp index fa19739db..9b144cb8a 100644 --- a/launcher/jsonutils.cpp +++ b/launcher/jsonutils.cpp @@ -66,6 +66,8 @@ QVariant toVariant(const JsonNode & node) return QVariant(node.Bool()); case JsonNode::JsonType::DATA_FLOAT: return QVariant(node.Float()); + case JsonNode::JsonType::DATA_INTEGER: + return QVariant{static_cast(node.Integer())}; case JsonNode::JsonType::DATA_STRING: return QVariant(QString::fromStdString(node.String())); case JsonNode::JsonType::DATA_VECTOR: @@ -102,6 +104,8 @@ JsonNode toJson(QVariant object) ret.String() = object.toString().toUtf8().data(); else if(object.userType() == QMetaType::Bool) ret.Bool() = object.toBool(); + else if(object.canConvert()) + ret.Integer() = object.toInt(); else if(object.canConvert()) ret.Float() = object.toFloat(); From 6e6bf1e77b1e205a7d43961faf175e3cf9a82474 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:39:30 +0300 Subject: [PATCH 38/74] don't list resolutions larger than the current screen's in the game options --- client/windows/GUIClasses.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 33372b30b..302c61a0a 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -562,9 +562,15 @@ void CSystemOptionsWindow::selectGameRes() std::vector items; const JsonNode & texts = CGI->generaltexth->localizedTexts["systemOptions"]["resolutionMenu"]; + SDL_Rect displayBounds; + SDL_GetDisplayBounds(std::max(0, SDL_GetWindowDisplayIndex(mainWindow)), &displayBounds); + for(const auto & it : conf.guiOptions) { const auto & resolution = it.first; + if(displayBounds.w < resolution.first || displayBounds.h < resolution.second) + continue; + std::string resX = boost::lexical_cast(resolution.first); std::string resY = boost::lexical_cast(resolution.second); items.push_back(resX + 'x' + resY); From 063f80fac3785abf90568344ddac9c657b5c7bad Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:58:27 +0300 Subject: [PATCH 39/74] don't list resolutions larger than the selected screen's in the launcher --- launcher/settingsView/csettingsview_moc.cpp | 59 ++++++++++++++-- launcher/settingsView/csettingsview_moc.h | 2 + launcher/settingsView/csettingsview_moc.ui | 76 +-------------------- 3 files changed, 57 insertions(+), 80 deletions(-) diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 234980242..46ee67fc3 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -11,6 +11,8 @@ #include "csettingsview_moc.h" #include "ui_csettingsview_moc.h" +#include "../jsonutils.h" +#include "../launcherdirs.h" #include "../updatedialog_moc.h" #include @@ -53,22 +55,19 @@ void CSettingsView::setDisplayList() { ui->comboBoxDisplayIndex->hide(); ui->labelDisplayIndex->hide(); + fillValidResolutionsForScreen(0); } else { int displayIndex = settings["video"]["displayIndex"].Integer(); ui->comboBoxDisplayIndex->addItems(list); + // calls fillValidResolutions() in slot ui->comboBoxDisplayIndex->setCurrentIndex(displayIndex); } } void CSettingsView::loadSettings() { - int resX = settings["video"]["screenRes"]["width"].Float(); - int resY = settings["video"]["screenRes"]["height"].Float(); - int resIndex = ui->comboBoxResolution->findText(QString("%1x%2").arg(resX).arg(resY)); - - ui->comboBoxResolution->setCurrentIndex(resIndex); ui->comboBoxShowIntro->setCurrentIndex(settings["video"]["showIntro"].Bool()); #ifdef Q_OS_IOS @@ -107,6 +106,54 @@ void CSettingsView::loadSettings() ui->comboBoxAutoSave->setCurrentIndex(settings["general"]["saveFrequency"].Integer() > 0 ? 1 : 0); } +void CSettingsView::fillValidResolutionsForScreen(int screenIndex) +{ + ui->comboBoxResolution->blockSignals(true); // avoid saving wrong resolution after adding first item from the list + ui->comboBoxResolution->clear(); + + // TODO: read available resolutions from all mods + const QLatin1String extrasResolutionsPath{"/vcmi-extras/Mods/extraResolutions/Content/config/resolutions.json"}; + const auto extrasResolutionsJson = JsonUtils::JsonFromFile(CLauncherDirs::get().modsPath() + extrasResolutionsPath); + const auto resolutions = extrasResolutionsJson.toMap().value(QLatin1String{"GUISettings"}).toList(); + if(resolutions.isEmpty()) + { + ui->comboBoxResolution->blockSignals(false); + ui->comboBoxResolution->addItem(resolutionToString({800, 600})); + return; + } + + const auto screens = qGuiApp->screens(); + const auto currentScreen = screenIndex < screens.size() ? screens[screenIndex] : qGuiApp->primaryScreen(); + const auto screenSize = currentScreen->size(); + for(const auto & entry : resolutions) + { + const auto resolutionMap = entry.toMap().value(QLatin1String{"resolution"}).toMap(); + if(resolutionMap.isEmpty()) + continue; + + const auto widthValue = resolutionMap[QLatin1String{"x"}]; + const auto heightValue = resolutionMap[QLatin1String{"y"}]; + if(!widthValue.isValid() || !heightValue.isValid()) + continue; + + const QSize resolution{widthValue.toInt(), heightValue.toInt()}; + if(screenSize.width() < resolution.width() || screenSize.height() < resolution.height()) + continue; + ui->comboBoxResolution->addItem(resolutionToString(resolution)); + } + + int resX = settings["video"]["screenRes"]["width"].Integer(); + int resY = settings["video"]["screenRes"]["height"].Integer(); + int resIndex = ui->comboBoxResolution->findText(resolutionToString({resX, resY})); + ui->comboBoxResolution->setCurrentIndex(resIndex); + + ui->comboBoxResolution->blockSignals(false); + + // if selected resolution no longer exists, force update value to the first resolution + if(resIndex == -1) + ui->comboBoxResolution->setCurrentIndex(0); +} + CSettingsView::CSettingsView(QWidget * parent) : QWidget(parent), ui(new Ui::CSettingsView) { @@ -152,6 +199,8 @@ void CSettingsView::on_comboBoxDisplayIndex_currentIndexChanged(int index) { Settings node = settings.write["video"]; node["displayIndex"].Float() = index; + + fillValidResolutionsForScreen(index); } void CSettingsView::on_comboBoxPlayerAI_currentIndexChanged(const QString & arg1) diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index 56d4cc834..92a349057 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -67,4 +67,6 @@ private slots: private: Ui::CSettingsView * ui; + + void fillValidResolutionsForScreen(int screenIndex); }; diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index cf5b3135d..a9e05775d 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -333,81 +333,7 @@ - - - 11 - - - - 800x600 - - - - - 1024x600 - - - - - 1024x768 - - - - - 1181x664 - - - - - 1280x720 - - - - - 1280x768 - - - - - 1280x800 - - - - - 1280x960 - - - - - 1280x1024 - - - - - 1366x768 - - - - - 1440x900 - - - - - 1600x1200 - - - - - 1680x1050 - - - - - 1920x1080 - - - + From 76b36b8951de8cbcf5a0ead05d08317c69d9fb5c Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 26 Sep 2022 16:59:59 +0300 Subject: [PATCH 40/74] iOS can use any resolution --- client/windows/GUIClasses.cpp | 4 ++++ launcher/settingsView/csettingsview_moc.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 302c61a0a..445145bb6 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -562,14 +562,18 @@ void CSystemOptionsWindow::selectGameRes() std::vector items; const JsonNode & texts = CGI->generaltexth->localizedTexts["systemOptions"]["resolutionMenu"]; +#ifndef VCMI_IOS SDL_Rect displayBounds; SDL_GetDisplayBounds(std::max(0, SDL_GetWindowDisplayIndex(mainWindow)), &displayBounds); +#endif for(const auto & it : conf.guiOptions) { const auto & resolution = it.first; +#ifndef VCMI_IOS if(displayBounds.w < resolution.first || displayBounds.h < resolution.second) continue; +#endif std::string resX = boost::lexical_cast(resolution.first); std::string resY = boost::lexical_cast(resolution.second); diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 46ee67fc3..cfdfd312a 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -137,8 +137,10 @@ void CSettingsView::fillValidResolutionsForScreen(int screenIndex) continue; const QSize resolution{widthValue.toInt(), heightValue.toInt()}; +#ifndef VCMI_IOS if(screenSize.width() < resolution.width() || screenSize.height() < resolution.height()) continue; +#endif ui->comboBoxResolution->addItem(resolutionToString(resolution)); } From d06977ecbbb8b1cc4215c188ffa955ece80435b8 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 11:51:49 +0300 Subject: [PATCH 41/74] handle enabling/disabling Extra Resolutions mod --- launcher/mainwindow_moc.cpp | 4 ++++ launcher/modManager/cmodlistview_moc.cpp | 8 +++++++ launcher/modManager/cmodlistview_moc.h | 4 ++++ launcher/modManager/cmodmanager.cpp | 23 +++++++++++++++++++-- launcher/modManager/cmodmanager.h | 11 +++++++++- launcher/settingsView/csettingsview_moc.cpp | 16 +++++++++++--- launcher/settingsView/csettingsview_moc.h | 5 +++++ 7 files changed, 65 insertions(+), 6 deletions(-) diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index 82769300f..3dff2b4ff 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -82,7 +82,11 @@ MainWindow::MainWindow(QWidget * parent) ui->tabSelectList->setMaximumWidth(width + 4); } ui->tabListWidget->setCurrentIndex(0); + + ui->settingsView->isExtraResolutionsModEnabled = ui->stackedWidgetPage2->isExtraResolutionsModEnabled(); ui->settingsView->setDisplayList(); + connect(ui->stackedWidgetPage2, &CModListView::extraResolutionsEnabledChanged, + ui->settingsView, &CSettingsView::fillValidResolutions); connect(ui->tabSelectList, SIGNAL(currentRowChanged(int)), ui->tabListWidget, SLOT(setCurrentIndex(int))); diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index 63d0d36e1..423822999 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -28,6 +28,9 @@ void CModListView::setupModModel() { modModel = new CModListModel(this); manager = vstd::make_unique(modModel); + + connect(manager.get(), &CModManager::extraResolutionsEnabledChanged, + this, &CModListView::extraResolutionsEnabledChanged); } void CModListView::setupFilterModel() @@ -320,6 +323,11 @@ void CModListView::selectMod(const QModelIndex & index) } } +bool CModListView::isExtraResolutionsModEnabled() const +{ + return manager->isExtraResolutionsModEnabled(); +} + void CModListView::keyPressEvent(QKeyEvent * event) { if(event->key() == Qt::Key_Escape && ui->modInfoWidget->isVisible()) diff --git a/launcher/modManager/cmodlistview_moc.h b/launcher/modManager/cmodlistview_moc.h index dd80ef860..2cc93f64e 100644 --- a/launcher/modManager/cmodlistview_moc.h +++ b/launcher/modManager/cmodlistview_moc.h @@ -63,6 +63,9 @@ class CModListView : public QWidget QString genChangelogText(CModEntry & mod); QString genModInfoText(CModEntry & mod); +signals: + void extraResolutionsEnabledChanged(bool enabled); + public: explicit CModListView(QWidget * parent = 0); ~CModListView(); @@ -75,6 +78,7 @@ public: void disableModInfo(); void selectMod(const QModelIndex & index); + bool isExtraResolutionsModEnabled() const; private slots: void dataChanged(const QModelIndex & topleft, const QModelIndex & bottomRight); diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index f5cb03627..4595abe31 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -18,7 +18,11 @@ #include "../jsonutils.h" #include "../launcherdirs.h" -static QString detectModArchive(QString path, QString modName) +namespace +{ +const QLatin1String extraResolutionsMod{"vcmi-extras.extraresolutions"}; + +QString detectModArchive(QString path, QString modName) { auto files = ZipArchive::listFiles(qstringToPath(path)); @@ -40,6 +44,8 @@ static QString detectModArchive(QString path, QString modName) return ""; } +} + CModManager::CModManager(CModList * modList) : modList(modList) @@ -219,6 +225,11 @@ bool CModManager::canDisableMod(QString modname) return true; } +bool CModManager::isExtraResolutionsModEnabled() const +{ + return modList->hasMod(extraResolutionsMod) && modList->getMod(extraResolutionsMod).isEnabled(); +} + static QVariant writeValue(QString path, QVariantMap input, QVariant value) { if(path.size() > 1) @@ -246,6 +257,9 @@ bool CModManager::doEnableMod(QString mod, bool on) modList->setModSettings(modSettings["activeMods"]); modList->modChanged(mod); + if(mod == extraResolutionsMod) + sendExtraResolutionsEnabledChanged(on); + JsonUtils::JsonToFile(settingsPath(), modSettings); return true; @@ -261,7 +275,7 @@ bool CModManager::doInstallMod(QString modname, QString archivePath) if(localMods.contains(modname)) return addError(modname, "Mod with such name is already installed"); - QString modDirName = detectModArchive(archivePath, modname); + QString modDirName = ::detectModArchive(archivePath, modname); if(!modDirName.size()) return addError(modname, "Mod archive is invalid or corrupted"); @@ -326,3 +340,8 @@ bool CModManager::removeModDir(QString path) return dir.removeRecursively(); } + +void CModManager::sendExtraResolutionsEnabledChanged(bool enabled) +{ + emit extraResolutionsEnabledChanged(enabled); +} diff --git a/launcher/modManager/cmodmanager.h b/launcher/modManager/cmodmanager.h index 1c0401a94..0ce64c101 100644 --- a/launcher/modManager/cmodmanager.h +++ b/launcher/modManager/cmodmanager.h @@ -11,8 +11,10 @@ #include "cmodlist.h" -class CModManager +class CModManager : public QObject { + Q_OBJECT + CModList * modList; QString settingsPath(); @@ -29,6 +31,11 @@ class CModManager bool addError(QString modname, QString message); bool removeModDir(QString mod); + void sendExtraResolutionsEnabledChanged(bool enabled); + +signals: + void extraResolutionsEnabledChanged(bool enabled); + public: CModManager(CModList * modList); @@ -51,4 +58,6 @@ public: bool canUninstallMod(QString mod); bool canEnableMod(QString mod); bool canDisableMod(QString mod); + + bool isExtraResolutionsModEnabled() const; }; diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index cfdfd312a..d753329be 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -106,15 +106,25 @@ void CSettingsView::loadSettings() ui->comboBoxAutoSave->setCurrentIndex(settings["general"]["saveFrequency"].Integer() > 0 ? 1 : 0); } +void CSettingsView::fillValidResolutions(bool isExtraResolutionsModEnabled) +{ + this->isExtraResolutionsModEnabled = isExtraResolutionsModEnabled; + fillValidResolutionsForScreen(ui->comboBoxDisplayIndex->isVisible() ? ui->comboBoxDisplayIndex->currentIndex() : 0); +} + void CSettingsView::fillValidResolutionsForScreen(int screenIndex) { ui->comboBoxResolution->blockSignals(true); // avoid saving wrong resolution after adding first item from the list ui->comboBoxResolution->clear(); // TODO: read available resolutions from all mods - const QLatin1String extrasResolutionsPath{"/vcmi-extras/Mods/extraResolutions/Content/config/resolutions.json"}; - const auto extrasResolutionsJson = JsonUtils::JsonFromFile(CLauncherDirs::get().modsPath() + extrasResolutionsPath); - const auto resolutions = extrasResolutionsJson.toMap().value(QLatin1String{"GUISettings"}).toList(); + QVariantList resolutions; + if(isExtraResolutionsModEnabled) + { + const QLatin1String extrasResolutionsPath{"/vcmi-extras/Mods/extraResolutions/Content/config/resolutions.json"}; + const auto extrasResolutionsJson = JsonUtils::JsonFromFile(CLauncherDirs::get().modsPath() + extrasResolutionsPath); + resolutions = extrasResolutionsJson.toMap().value(QLatin1String{"GUISettings"}).toList(); + } if(resolutions.isEmpty()) { ui->comboBoxResolution->blockSignals(false); diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index 92a349057..fba5bd2c6 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -26,6 +26,11 @@ public: void loadSettings(); void setDisplayList(); + bool isExtraResolutionsModEnabled{}; + +public slots: + void fillValidResolutions(bool isExtraResolutionsModEnabled); + private slots: void on_checkBoxFullScreen_stateChanged(int state); From 42ea458ccffa19bfd71b6e42840acb6c68f8c852 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 11:52:09 +0300 Subject: [PATCH 42/74] handle (un)installing Extra Resolutions mod --- launcher/modManager/cmodmanager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index 4595abe31..6c096c937 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -300,6 +300,9 @@ bool CModManager::doInstallMod(QString modname, QString archivePath) loadMods(); modList->reloadRepositories(); + if(modname == extraResolutionsMod) + sendExtraResolutionsEnabledChanged(true); + return true; } @@ -320,6 +323,9 @@ bool CModManager::doUninstallMod(QString modname) loadMods(); modList->reloadRepositories(); + if(modname == extraResolutionsMod) + sendExtraResolutionsEnabledChanged(false); + return true; } From e8396401f9e40c25652419c62db3fbff655eef7a Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Tue, 27 Sep 2022 11:55:03 +0300 Subject: [PATCH 43/74] fetch Extra Resolutions mod path from the settings schema --- config/schemas/settings.json | 6 +++++- launcher/settingsView/csettingsview_moc.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/config/schemas/settings.json b/config/schemas/settings.json index 66d39b630..85e4d4463 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -363,7 +363,7 @@ "type" : "object", "default": {}, "additionalProperties" : false, - "required" : [ "repositoryURL", "enableInstalledMods", "autoCheckRepositories", "updateOnStartup", "updateConfigUrl" ], + "required" : [ "repositoryURL", "enableInstalledMods", "extraResolutionsModPath", "autoCheckRepositories", "updateOnStartup", "updateConfigUrl" ], "properties" : { "repositoryURL" : { "type" : "array", @@ -378,6 +378,10 @@ "type" : "boolean", "default" : true }, + "extraResolutionsModPath" : { + "type" : "string", + "default" : "/vcmi-extras/Mods/extraResolutions/Content/config/resolutions.json" + }, "autoCheckRepositories" : { "type" : "boolean", "default" : true diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index d753329be..d5ebbbb2a 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -121,7 +121,7 @@ void CSettingsView::fillValidResolutionsForScreen(int screenIndex) QVariantList resolutions; if(isExtraResolutionsModEnabled) { - const QLatin1String extrasResolutionsPath{"/vcmi-extras/Mods/extraResolutions/Content/config/resolutions.json"}; + const auto extrasResolutionsPath = settings["launcher"]["extraResolutionsModPath"].String().c_str(); const auto extrasResolutionsJson = JsonUtils::JsonFromFile(CLauncherDirs::get().modsPath() + extrasResolutionsPath); resolutions = extrasResolutionsJson.toMap().value(QLatin1String{"GUISettings"}).toList(); } From 475f8357694b246e8e9e3844d7c58bbbb31c1078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Wed, 28 Sep 2022 11:38:08 +0200 Subject: [PATCH 44/74] More style tweaks --- client/mapHandler.cpp | 1 - lib/CHeroHandler.cpp | 4 ++-- lib/mapObjects/CObjectClassesHandler.cpp | 14 +++++++------- lib/mapping/CMap.cpp | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/client/mapHandler.cpp b/client/mapHandler.cpp index 922bc1103..d24a720eb 100644 --- a/client/mapHandler.cpp +++ b/client/mapHandler.cpp @@ -172,7 +172,6 @@ void CMapHandler::initTerrainGraphics() } }; - //TODO: use id as a key std::map terrainFiles; std::map riverFiles; std::map roadFiles; diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 94b6b09bf..cc1312053 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -346,9 +346,9 @@ CHeroHandler::~CHeroHandler() = default; CHeroHandler::CHeroHandler() { loadTerrains(); - for(int i = 0; i < VLC->terrainTypeHandler->terrains().size(); ++i) + for(const auto & terrain : VLC->terrainTypeHandler->terrains()) { - VLC->modh->identifiers.registerObject("core", "terrain", VLC->terrainTypeHandler->terrains()[i].name, i); + VLC->modh->identifiers.registerObject("core", "terrain", terrain.name, terrain.id); } loadBallistics(); loadExperience(); diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index 0039f35d4..c90e1b8eb 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -486,15 +486,15 @@ void AObjectTypeHandler::init(const JsonNode & input, boost::optionalid = Obj(type); + tmpl->subid = subtype; + tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template? try { - entry.second.setType(JsonNode::JsonType::DATA_STRUCT); - JsonUtils::inherit(entry.second, base); - - auto tmpl = new ObjectTemplate; - tmpl->id = Obj(type); - tmpl->subid = subtype; - tmpl->stringID = entry.first; // FIXME: create "fullID" - type.object.template? tmpl->readJson(entry.second); templates.push_back(std::shared_ptr(tmpl)); } diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index b811c4f0d..b2583721b 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -128,9 +128,9 @@ CCastleEvent::CCastleEvent() : town(nullptr) TerrainTile::TerrainTile(): terType(nullptr), terView(0), - riverType(const_cast(&VLC->terrainTypeHandler->rivers()[0])), + riverType(const_cast(&VLC->terrainTypeHandler->rivers()[River::NO_RIVER])), riverDir(0), - roadType(const_cast(&VLC->terrainTypeHandler->roads()[0])), + roadType(const_cast(&VLC->terrainTypeHandler->roads()[Road::NO_ROAD])), roadDir(0), extTileFlags(0), visitable(false), From d1d274382c1101d4681c892d77ec06c914c4164b Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Thu, 29 Sep 2022 12:17:37 +0300 Subject: [PATCH 45/74] [iOS] prevent keyboard appearing automatically after switching tab in launcher --- launcher/mainwindow_moc.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index 82769300f..5ae162e75 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -84,8 +84,12 @@ MainWindow::MainWindow(QWidget * parent) ui->tabListWidget->setCurrentIndex(0); ui->settingsView->setDisplayList(); - connect(ui->tabSelectList, SIGNAL(currentRowChanged(int)), - ui->tabListWidget, SLOT(setCurrentIndex(int))); + connect(ui->tabSelectList, &QListWidget::currentRowChanged, [this](int i) { +#ifdef Q_OS_IOS + qApp->focusWidget()->clearFocus(); +#endif + ui->tabListWidget->setCurrentIndex(i); + }); if(settings["launcher"]["updateOnStartup"].Bool()) UpdateDialog::showUpdateDialog(false); From 20c102e648de2135a3a4b8bc1a9e60d135dca760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 29 Sep 2022 11:44:46 +0200 Subject: [PATCH 46/74] Remove T prefix from new typedefs --- client/CMusicHandler.h | 2 +- client/CPlayerInterface.cpp | 4 ++-- client/widgets/AdventureMapClasses.cpp | 4 ++-- client/widgets/AdventureMapClasses.h | 4 ++-- lib/CCreatureHandler.cpp | 4 ++-- lib/CCreatureHandler.h | 4 ++-- lib/CGeneralTextHandler.h | 2 +- lib/CHeroHandler.h | 2 +- lib/CPathfinder.h | 2 +- lib/CStack.cpp | 2 +- lib/CStack.h | 4 ++-- lib/CTownHandler.cpp | 10 ++++----- lib/CTownHandler.h | 10 ++++----- lib/GameConstants.h | 6 ++--- lib/HeroBonus.cpp | 2 +- lib/HeroBonus.h | 4 ++-- lib/NetPacksLib.cpp | 2 +- lib/ObstacleHandler.cpp | 2 +- lib/ObstacleHandler.h | 4 ++-- lib/Terrain.cpp | 24 ++++++++++---------- lib/Terrain.h | 28 ++++++++++++------------ lib/battle/BattleInfo.cpp | 4 ++-- lib/battle/BattleInfo.h | 6 ++--- lib/battle/BattleProxy.cpp | 2 +- lib/battle/BattleProxy.h | 2 +- lib/battle/CBattleInfoEssentials.cpp | 4 ++-- lib/battle/CBattleInfoEssentials.h | 2 +- lib/battle/IBattleInfoCallback.h | 2 +- lib/battle/IBattleState.h | 2 +- lib/mapObjects/CGHeroInstance.cpp | 6 ++--- lib/mapObjects/CGHeroInstance.h | 2 +- lib/mapObjects/CObjectClassesHandler.cpp | 4 ++-- lib/mapObjects/CObjectClassesHandler.h | 4 ++-- lib/mapObjects/ObjectTemplate.cpp | 4 ++-- lib/mapObjects/ObjectTemplate.h | 4 ++-- lib/mapping/CDrawRoadsOperation.cpp | 4 ++-- lib/mapping/CDrawRoadsOperation.h | 8 +++---- lib/mapping/CMapEditManager.cpp | 6 ++--- lib/mapping/CMapEditManager.h | 6 ++--- lib/mapping/CMapOperation.cpp | 2 +- lib/mapping/CMapOperation.h | 4 ++-- lib/mapping/MapEditUtils.cpp | 4 ++-- lib/mapping/MapEditUtils.h | 4 ++-- lib/rmg/CRmgTemplate.cpp | 4 ++-- lib/rmg/CRmgTemplate.h | 6 ++--- lib/rmg/Functions.cpp | 6 ++--- lib/rmg/Functions.h | 4 ++-- lib/rmg/ObstaclePlacer.cpp | 2 +- lib/rmg/ObstaclePlacer.h | 2 +- lib/rmg/RmgMap.cpp | 2 +- lib/rmg/RmgMap.h | 2 +- lib/rmg/RmgObject.cpp | 4 ++-- lib/rmg/RmgObject.h | 4 ++-- lib/rmg/RoadPlacer.cpp | 2 +- lib/rmg/RockPlacer.h | 2 +- lib/rmg/TileInfo.cpp | 6 ++--- lib/rmg/TileInfo.h | 10 ++++----- lib/rmg/TreasurePlacer.cpp | 2 +- lib/rmg/TreasurePlacer.h | 2 +- lib/rmg/Zone.cpp | 4 ++-- lib/rmg/Zone.h | 6 ++--- server/CGameHandler.cpp | 2 +- test/game/CGameStateTest.cpp | 2 +- test/mock/mock_IBattleInfoCallback.h | 2 +- test/mock/mock_battle_IBattleState.h | 2 +- 65 files changed, 145 insertions(+), 145 deletions(-) diff --git a/client/CMusicHandler.h b/client/CMusicHandler.h index 401185b5f..fa69d8a28 100644 --- a/client/CMusicHandler.h +++ b/client/CMusicHandler.h @@ -84,7 +84,7 @@ public: // Sets std::vector pickupSounds; std::vector battleIntroSounds; - std::map horseSounds; + std::map horseSounds; }; // Helper //now it looks somewhat useless diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 7cf8463d3..2b6bea79b 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2746,8 +2746,8 @@ void CPlayerInterface::doMoveHero(const CGHeroInstance * h, CGPath path) { path.convert(0); - TTerrainId currentTerrain = Terrain::BORDER; // not init yet - TTerrainId newTerrain; + TerrainId currentTerrain = Terrain::BORDER; // not init yet + TerrainId newTerrain; int sh = -1; auto canStop = [&](CGPathNode * node) -> bool diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 4f9697cb3..23c2f03d1 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -495,9 +495,9 @@ void CMinimapInstance::showAll(SDL_Surface * to) } } -std::map > CMinimap::loadColors() +std::map > CMinimap::loadColors() { - std::map > ret; + std::map > ret; for(const auto & terrain : CGI->terrainTypeHandler->terrains()) { diff --git a/client/widgets/AdventureMapClasses.h b/client/widgets/AdventureMapClasses.h index a1b3c4242..9eb592c3c 100644 --- a/client/widgets/AdventureMapClasses.h +++ b/client/widgets/AdventureMapClasses.h @@ -222,7 +222,7 @@ protected: int level; //to initialize colors - std::map > loadColors(); + std::map > loadColors(); void clickLeft(tribool down, bool previousState) override; void clickRight(tribool down, bool previousState) override; @@ -233,7 +233,7 @@ protected: public: // terrainID -> (normal color, blocked color) - const std::map > colors; + const std::map > colors; CMinimap(const Rect & position); diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 1cf20badc..a2ff1389d 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -285,13 +285,13 @@ std::string CCreature::nodeName() const return "\"" + namePl + "\""; } -bool CCreature::isItNativeTerrain(TTerrainId terrain) const +bool CCreature::isItNativeTerrain(TerrainId terrain) const { auto native = getNativeTerrain(); return native == terrain || native == Terrain::ANY_TERRAIN; } -TTerrainId CCreature::getNativeTerrain() const +TerrainId CCreature::getNativeTerrain() const { const std::string cachingStringNoTerrainPenalty = "type_NO_TERRAIN_PENALTY"; static const auto selectorNoTerrainPenalty = Selector::type()(Bonus::NO_TERRAIN_PENALTY); diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index a49df00b1..edf730767 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -121,14 +121,14 @@ public: ArtifactID warMachine; - bool isItNativeTerrain(TTerrainId terrain) const; + bool isItNativeTerrain(TerrainId terrain) const; /** Returns creature native terrain considering some terrain bonuses. @param considerBonus is used to avoid Dead Lock when this method is called inside getAllBonuses considerBonus = true is called from Pathfinder and fills actual nativeTerrain considering bonus(es). considerBonus = false is called on Battle init and returns already prepared nativeTerrain without Bonus system calling. */ - TTerrainId getNativeTerrain() const; + TerrainId getNativeTerrain() const; int32_t getIndex() const override; int32_t getIconIndex() const override; const std::string & getName() const override; diff --git a/lib/CGeneralTextHandler.h b/lib/CGeneralTextHandler.h index 606ad929d..bc5dcc07b 100644 --- a/lib/CGeneralTextHandler.h +++ b/lib/CGeneralTextHandler.h @@ -124,7 +124,7 @@ public: std::vector advobtxt; std::vector xtrainfo; std::vector restypes; //names of resources - std::map terrainNames; + std::map terrainNames; std::vector randsign; std::vector> mines; //first - name; second - event description std::vector seerEmpty; diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h index 44113ce5d..023015705 100644 --- a/lib/CHeroHandler.h +++ b/lib/CHeroHandler.h @@ -266,7 +266,7 @@ public: CHeroClassHandler classes; //default costs of going through terrains. -1 means terrain is impassable - std::map terrCosts; + std::map terrCosts; struct SBallisticsLevelInfo { diff --git a/lib/CPathfinder.h b/lib/CPathfinder.h index 817d31a29..daa28c6b4 100644 --- a/lib/CPathfinder.h +++ b/lib/CPathfinder.h @@ -529,7 +529,7 @@ struct DLL_LINKAGE TurnInfo TConstBonusListPtr bonuses; mutable int maxMovePointsLand; mutable int maxMovePointsWater; - TTerrainId nativeTerrain; + TerrainId nativeTerrain; TurnInfo(const CGHeroInstance * Hero, const int Turn = 0); bool isLayerAvailable(const EPathfindingLayer layer) const; diff --git a/lib/CStack.cpp b/lib/CStack.cpp index 9d538dc68..6e9a50b4a 100644 --- a/lib/CStack.cpp +++ b/lib/CStack.cpp @@ -334,7 +334,7 @@ bool CStack::isOnNativeTerrain() const return res; } -bool CStack::isOnTerrain(TTerrainId terrain) const +bool CStack::isOnTerrain(TerrainId terrain) const { return battle->getTerrainType() == terrain; } diff --git a/lib/CStack.h b/lib/CStack.h index 574903697..fa31a3d03 100644 --- a/lib/CStack.h +++ b/lib/CStack.h @@ -31,7 +31,7 @@ public: ui32 ID; //unique ID of stack const CCreature * type; - TTerrainId nativeTerrain; //tmp variable to save native terrain value on battle init + TerrainId nativeTerrain; //tmp variable to save native terrain value on battle init ui32 baseAmount; PlayerColor owner; //owner - player color (255 for neutrals) @@ -53,7 +53,7 @@ public: bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines bool isOnNativeTerrain() const; - bool isOnTerrain(TTerrainId terrain) const; + bool isOnTerrain(TerrainId terrain) const; ui32 level() const; si32 magicResistance() const override; //include aura of resistance diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 571c067f7..c50d097d4 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -28,9 +28,9 @@ VCMI_LIB_NAMESPACE_BEGIN const int NAMES_PER_TOWN=16; // number of town names per faction in H3 files. Json can define any number -const TTerrainId CTownHandler::defaultGoodTerrain(Terrain::GRASS); -const TTerrainId CTownHandler::defaultEvilTerrain(Terrain::LAVA); -const TTerrainId CTownHandler::defaultNeutralTerrain(Terrain::ROUGH); +const TerrainId CTownHandler::defaultGoodTerrain(Terrain::GRASS); +const TerrainId CTownHandler::defaultEvilTerrain(Terrain::LAVA); +const TerrainId CTownHandler::defaultNeutralTerrain(Terrain::ROUGH); const std::map CBuilding::MODES = { @@ -944,9 +944,9 @@ void CTownHandler::loadPuzzle(CFaction &faction, const JsonNode &source) assert(faction.puzzleMap.size() == GameConstants::PUZZLE_MAP_PIECES); } -TTerrainId CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const +TerrainId CTownHandler::getDefaultTerrainForAlignment(EAlignment::EAlignment alignment) const { - TTerrainId terrain = defaultGoodTerrain; + TerrainId terrain = defaultGoodTerrain; switch(alignment) { diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index d87afd7a0..0128b44b3 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -187,7 +187,7 @@ public: TFaction index; - TTerrainId nativeTerrain; + TerrainId nativeTerrain; EAlignment::EAlignment alignment; bool preferUndergroundPlacement; @@ -360,9 +360,9 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase requirementsToLoad; std::vector overriddenBidsToLoad; //list of buildings, which bonuses should be overridden. - const static TTerrainId defaultGoodTerrain; - const static TTerrainId defaultEvilTerrain; - const static TTerrainId defaultNeutralTerrain; + const static TerrainId defaultGoodTerrain; + const static TerrainId defaultEvilTerrain; + const static TerrainId defaultNeutralTerrain; static TPropagatorPtr & emptyPropagator(); @@ -393,7 +393,7 @@ class DLL_LINKAGE CTownHandler : public CHandlerBase TDmgRange; typedef si32 TBonusSubtype; typedef si32 TQuantity; -typedef si8 TTerrainId; -typedef si8 TRoadId; -typedef si8 TRiverId; +typedef si8 TerrainId; +typedef si8 RoadId; +typedef si8 RiverId; typedef int TRmgTemplateZoneId; diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index daf11989d..b43346658 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -2113,7 +2113,7 @@ CreatureTerrainLimiter::CreatureTerrainLimiter() { } -CreatureTerrainLimiter::CreatureTerrainLimiter(TTerrainId terrain): +CreatureTerrainLimiter::CreatureTerrainLimiter(TerrainId terrain): terrainType(terrain) { } diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 9901657e5..482671e5f 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -1062,9 +1062,9 @@ public: class DLL_LINKAGE CreatureTerrainLimiter : public ILimiter //applies only to creatures that are on specified terrain, default native terrain { public: - TTerrainId terrainType; + TerrainId terrainType; CreatureTerrainLimiter(); - CreatureTerrainLimiter(TTerrainId terrain); + CreatureTerrainLimiter(TerrainId terrain); int limit(const BonusLimitationContext &context) const override; virtual std::string toString() const override; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index a6c57d1fd..ea70103b8 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -703,7 +703,7 @@ DLL_LINKAGE void GiveHero::applyGs(CGameState *gs) DLL_LINKAGE void NewObject::applyGs(CGameState *gs) { - TTerrainId terrainType = Terrain::BORDER; + TerrainId terrainType = Terrain::BORDER; if(ID == Obj::BOAT && !gs->isInTheMap(pos)) //special handling for bug #3060 - pos outside map but visitablePos is not { diff --git a/lib/ObstacleHandler.cpp b/lib/ObstacleHandler.cpp index 5e5f22536..37019cb2a 100644 --- a/lib/ObstacleHandler.cpp +++ b/lib/ObstacleHandler.cpp @@ -68,7 +68,7 @@ std::vector ObstacleInfo::getBlocked(BattleHex hex) const return ret; } -bool ObstacleInfo::isAppropriate(const TTerrainId terrainType, const BattleField & battlefield) const +bool ObstacleInfo::isAppropriate(const TerrainId terrainType, const BattleField & battlefield) const { auto bgInfo = battlefield.getInfo(); diff --git a/lib/ObstacleHandler.h b/lib/ObstacleHandler.h index 0aa0e5c6c..f79ff6877 100644 --- a/lib/ObstacleHandler.h +++ b/lib/ObstacleHandler.h @@ -33,7 +33,7 @@ public: si32 iconIndex; std::string identifier; std::string appearAnimation, animation, dissapearAnimation; - std::vector allowedTerrains; + std::vector allowedTerrains; std::vector allowedSpecialBfields; //TODO: here is extra field to implement it's logic in the future but save backward compatibility @@ -52,7 +52,7 @@ public: std::vector getBlocked(BattleHex hex) const; //returns vector of hexes blocked by obstacle when it's placed on hex 'hex' - bool isAppropriate(const TTerrainId terrainType, const BattleField & specialBattlefield) const; + bool isAppropriate(const TerrainId terrainType, const BattleField & specialBattlefield) const; template void serialize(Handler &h, const int version) { diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index cbf67eda5..b6f399d12 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -149,16 +149,16 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig if(!terr.second["originalTerrainId"].isNull()) { //place in reserved slot - info.id = (TTerrainId)(terr.second["originalTerrainId"].Float()); + info.id = (TerrainId)(terr.second["originalTerrainId"].Float()); objects[info.id] = info; } else { //append at the end - info.id = static_cast(objects.size()); + info.id = static_cast(objects.size()); objects.push_back(info); } - TTerrainId id = info.id; + TerrainId id = info.id; //Update terrain with this id in the future, after all terrain types are populated @@ -226,12 +226,12 @@ void TerrainTypeHandler::initRivers(const std::vector & allConfigs) if (!river.second["originalRiverId"].isNull()) { - info.id = static_cast(river.second["originalRiverId"].Float()); + info.id = static_cast(river.second["originalRiverId"].Float()); riverTypes[info.id] = info; } else { - info.id = static_cast(riverTypes.size()); + info.id = static_cast(riverTypes.size()); riverTypes.push_back(info); } } @@ -261,12 +261,12 @@ void TerrainTypeHandler::initRoads(const std::vector & allConfigs) if (!road.second["originalRoadId"].isNull()) { - info.id = static_cast(road.second["originalRoadId"].Float()); + info.id = static_cast(road.second["originalRoadId"].Float()); roadTypes[info.id] = info; } else { - info.id = static_cast(roadTypes.size()); + info.id = static_cast(roadTypes.size()); roadTypes.push_back(info); } } @@ -339,7 +339,7 @@ const TerrainType* TerrainTypeHandler::getInfoByCode(const std::string& terrainC return terrainInfoByCode.at(terrainCode); } -const TerrainType* TerrainTypeHandler::getInfoById(TTerrainId id) const +const TerrainType* TerrainTypeHandler::getInfoById(TerrainId id) const { return terrainInfoById.at(id); } @@ -354,7 +354,7 @@ const RiverType* TerrainTypeHandler::getRiverByCode(const std::string& riverCode return riverInfoByCode.at(riverCode); } -const RiverType* TerrainTypeHandler::getRiverById(TRiverId id) const +const RiverType* TerrainTypeHandler::getRiverById(RiverId id) const { return riverInfoById.at(id); } @@ -369,7 +369,7 @@ const RoadType* TerrainTypeHandler::getRoadByCode(const std::string& roadCode) c return roadInfoByCode.at(roadCode); } -const RoadType* TerrainTypeHandler::getRoadById(TRoadId id) const +const RoadType* TerrainTypeHandler::getRoadById(RoadId id) const { return roadInfoById.at(id); } @@ -467,7 +467,7 @@ bool TerrainType::isTransitionRequired() const return transitionRequired; } -RiverType::RiverType(const std::string & fileName, const std::string & code, TRiverId id): +RiverType::RiverType(const std::string & fileName, const std::string & code, RiverId id): fileName(fileName), code(code), id(id) @@ -484,7 +484,7 @@ RiverType& RiverType::operator=(const RiverType& other) return *this; } -RoadType::RoadType(const std::string& fileName, const std::string& code, TRoadId id): +RoadType::RoadType(const std::string& fileName, const std::string& code, RoadId id): fileName(fileName), code(code), id(id), diff --git a/lib/Terrain.h b/lib/Terrain.h index 0d0a9fdf4..a4aae7b8a 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -30,7 +30,7 @@ public: }; std::vector battleFields; - std::vector prohibitTransitions; + std::vector prohibitTransitions; std::array minimapBlocked; std::array minimapUnblocked; std::string name; @@ -39,10 +39,10 @@ public: std::string terrainText; std::string typeCode; std::string terrainViewPatterns; - TRiverId river; + RiverId river; - TTerrainId id; - TTerrainId rockTerrain; + TerrainId id; + TerrainId rockTerrain; int moveCost; int horseSoundId; ui8 passabilityType; @@ -95,9 +95,9 @@ public: std::string fileName; std::string code; std::string deltaName; - TRiverId id; + RiverId id; - RiverType(const std::string & fileName = "", const std::string & code = "", TRiverId id = River::NO_RIVER); + RiverType(const std::string & fileName = "", const std::string & code = "", RiverId id = River::NO_RIVER); RiverType& operator=(const RiverType & other); @@ -115,10 +115,10 @@ class DLL_LINKAGE RoadType public: std::string fileName; std::string code; - TRoadId id; + RoadId id; ui8 movementCost; - RoadType(const std::string & fileName = "", const std::string& code = "", TRoadId id = Road::NO_ROAD); + RoadType(const std::string & fileName = "", const std::string& code = "", RoadId id = Road::NO_ROAD); RoadType& operator=(const RoadType & other); @@ -143,17 +143,17 @@ public: const std::vector & terrains() const; const TerrainType * getInfoByName(const std::string & terrainName) const; const TerrainType * getInfoByCode(const std::string & terrainCode) const; - const TerrainType * getInfoById(TTerrainId id) const; + const TerrainType * getInfoById(TerrainId id) const; const std::vector & rivers() const; const RiverType * getRiverByName(const std::string & riverName) const; const RiverType * getRiverByCode(const std::string & riverCode) const; - const RiverType * getRiverById(TRiverId id) const; + const RiverType * getRiverById(RiverId id) const; const std::vector & roads() const; const RoadType * getRoadByName(const std::string & roadName) const; const RoadType * getRoadByCode(const std::string & roadCode) const; - const RoadType * getRoadById(TRoadId id) const; + const RoadType * getRoadById(RoadId id) const; template void serialize(Handler &h, const int version) { @@ -177,15 +177,15 @@ private: std::unordered_map terrainInfoByName; std::unordered_map terrainInfoByCode; - std::unordered_map terrainInfoById; + std::unordered_map terrainInfoById; std::unordered_map riverInfoByName; std::unordered_map riverInfoByCode; - std::unordered_map riverInfoById; + std::unordered_map riverInfoById; std::unordered_map roadInfoByName; std::unordered_map roadInfoByCode; - std::unordered_map roadInfoById; + std::unordered_map roadInfoById; void initTerrains(const std::vector & allConfigs); void initRivers(const std::vector & allConfigs); diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index 4d9edbabd..ea5e7e776 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -191,7 +191,7 @@ struct RangeGenerator std::function myRand; }; -BattleInfo * BattleInfo::setupBattle(const int3 & tile, TTerrainId terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) +BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town) { CMP_stack cmpst; auto curB = new BattleInfo(); @@ -565,7 +565,7 @@ BattleField BattleInfo::getBattlefieldType() const return battlefieldType; } -TTerrainId BattleInfo::getTerrainType() const +TerrainId BattleInfo::getTerrainType() const { return terrainType; } diff --git a/lib/battle/BattleInfo.h b/lib/battle/BattleInfo.h index a5243dd06..76d3a9db2 100644 --- a/lib/battle/BattleInfo.h +++ b/lib/battle/BattleInfo.h @@ -39,7 +39,7 @@ public: SiegeInfo si; BattleField battlefieldType; //like !!BA:B - TTerrainId terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) + TerrainId terrainType; //used for some stack nativity checks (not the bonus limiters though that have their own copy) ui8 tacticsSide; //which side is requested to play tactics phase ui8 tacticDistance; //how many hexes we can go forward (1 = only hexes adjacent to margin line) @@ -75,7 +75,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - TTerrainId getTerrainType() const override; + TerrainId getTerrainType() const override; ObstacleCList getAllObstacles() const override; @@ -140,7 +140,7 @@ public: const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player void localInit(); - static BattleInfo * setupBattle(const int3 & tile, TTerrainId, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); + static BattleInfo * setupBattle(const int3 & tile, TerrainId, const BattleField & battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town); ui8 whatSide(PlayerColor player) const; diff --git a/lib/battle/BattleProxy.cpp b/lib/battle/BattleProxy.cpp index 9b8646d3d..0ebb475ba 100644 --- a/lib/battle/BattleProxy.cpp +++ b/lib/battle/BattleProxy.cpp @@ -49,7 +49,7 @@ BattleField BattleProxy::getBattlefieldType() const return subject->battleGetBattlefieldType(); } -TTerrainId BattleProxy::getTerrainType() const +TerrainId BattleProxy::getTerrainType() const { return subject->battleTerrainType(); } diff --git a/lib/battle/BattleProxy.h b/lib/battle/BattleProxy.h index d95fbf440..8a7b0e13d 100644 --- a/lib/battle/BattleProxy.h +++ b/lib/battle/BattleProxy.h @@ -32,7 +32,7 @@ public: battle::Units getUnitsIf(battle::UnitFilter predicate) const override; BattleField getBattlefieldType() const override; - TTerrainId getTerrainType() const override; + TerrainId getTerrainType() const override; ObstacleCList getAllObstacles() const override; diff --git a/lib/battle/CBattleInfoEssentials.cpp b/lib/battle/CBattleInfoEssentials.cpp index b5a1b1d25..53fcd6dd8 100644 --- a/lib/battle/CBattleInfoEssentials.cpp +++ b/lib/battle/CBattleInfoEssentials.cpp @@ -16,9 +16,9 @@ VCMI_LIB_NAMESPACE_BEGIN -TTerrainId CBattleInfoEssentials::battleTerrainType() const +TerrainId CBattleInfoEssentials::battleTerrainType() const { - RETURN_IF_NOT_BATTLE(TTerrainId()); + RETURN_IF_NOT_BATTLE(TerrainId()); return getBattle()->getTerrainType(); } diff --git a/lib/battle/CBattleInfoEssentials.h b/lib/battle/CBattleInfoEssentials.h index e920adc2a..6903e66bc 100644 --- a/lib/battle/CBattleInfoEssentials.h +++ b/lib/battle/CBattleInfoEssentials.h @@ -48,7 +48,7 @@ public: BattlePerspective::BattlePerspective battleGetMySide() const; const IBonusBearer * getBattleNode() const; - TTerrainId battleTerrainType() const override; + TerrainId battleTerrainType() const override; BattleField battleGetBattlefieldType() const override; int32_t battleGetEnchanterCounter(ui8 side) const; diff --git a/lib/battle/IBattleInfoCallback.h b/lib/battle/IBattleInfoCallback.h index cb9e8b8d4..38e57f0dc 100644 --- a/lib/battle/IBattleInfoCallback.h +++ b/lib/battle/IBattleInfoCallback.h @@ -40,7 +40,7 @@ public: virtual scripting::Pool * getContextPool() const = 0; #endif - virtual TTerrainId battleTerrainType() const = 0; + virtual TerrainId battleTerrainType() const = 0; virtual BattleField battleGetBattlefieldType() const = 0; ///return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw diff --git a/lib/battle/IBattleState.h b/lib/battle/IBattleState.h index 7e60154ad..62536f4c1 100644 --- a/lib/battle/IBattleState.h +++ b/lib/battle/IBattleState.h @@ -44,7 +44,7 @@ public: virtual battle::Units getUnitsIf(battle::UnitFilter predicate) const = 0; virtual BattleField getBattlefieldType() const = 0; - virtual TTerrainId getTerrainType() const = 0; + virtual TerrainId getTerrainType() const = 0; virtual ObstacleCList getAllObstacles() const = 0; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index fcb4457fb..49305863b 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -98,7 +98,7 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile & dest, const TerrainTile & f return (ui32)ret; } -TTerrainId CGHeroInstance::getNativeTerrain() const +TerrainId CGHeroInstance::getNativeTerrain() const { // NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army. // This is clearly bug in H3 however intended behaviour is not clear. @@ -106,11 +106,11 @@ TTerrainId CGHeroInstance::getNativeTerrain() const // will always have best penalty without any influence from player-defined stacks order // TODO: What should we do if all hero stacks are neutral creatures? - TTerrainId nativeTerrain = Terrain::BORDER; + TerrainId nativeTerrain = Terrain::BORDER; for(auto stack : stacks) { - TTerrainId stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. + TerrainId stackNativeTerrain = stack.second->type->getNativeTerrain(); //consider terrain bonuses e.g. Lodestar. if(stackNativeTerrain == Terrain::BORDER) //where does this value come from? continue; diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index 281d30eeb..7cd11583e 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -157,7 +157,7 @@ public: bool needsLastStack()const override; ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling - TTerrainId getNativeTerrain() const; + TerrainId getNativeTerrain() const; ui32 getLowestCreatureSpeed() const; int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index c90e1b8eb..bc0736774 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -590,7 +590,7 @@ BattleField AObjectTypeHandler::getBattlefield() const return battlefield ? BattleField::fromString(battlefield.get()) : BattleField::NONE; } -std::vector>AObjectTypeHandler::getTemplates(TTerrainId terrainType) const +std::vector>AObjectTypeHandler::getTemplates(TerrainId terrainType) const { std::vector> templates = getTemplates(); std::vector> filtered; @@ -607,7 +607,7 @@ std::vector>AObjectTypeHandler::getTemplat return filtered; } -std::shared_ptr AObjectTypeHandler::getOverride(TTerrainId terrainType, const CGObjectInstance * object) const +std::shared_ptr AObjectTypeHandler::getOverride(TerrainId terrainType, const CGObjectInstance * object) const { std::vector> ret = getTemplates(terrainType); for (const auto & tmpl: ret) diff --git a/lib/mapObjects/CObjectClassesHandler.h b/lib/mapObjects/CObjectClassesHandler.h index 0bc297380..224a95bb3 100644 --- a/lib/mapObjects/CObjectClassesHandler.h +++ b/lib/mapObjects/CObjectClassesHandler.h @@ -184,11 +184,11 @@ public: /// returns all templates matching parameters std::vector> getTemplates() const; - std::vector> getTemplates(const TTerrainId terrainType) const; + std::vector> getTemplates(const TerrainId terrainType) const; /// returns preferred template for this object, if present (e.g. one of 3 possible templates for town - village, fort and castle) /// note that appearance will not be changed - this must be done separately (either by assignment or via pack from server) - std::shared_ptr getOverride(TTerrainId terrainType, const CGObjectInstance * object) const; + std::shared_ptr getOverride(TerrainId terrainType, const CGObjectInstance * object) const; BattleField getBattlefield() const; diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index ef2fd91d3..a23b3db36 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -158,7 +158,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain assert(terrStr.size() == Terrain::ROCK - 1); // all terrains but rock - for(TTerrainId i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) + for(TerrainId i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) { if (terrStr[8-i] == '1') allowedTerrains.insert(i); @@ -557,7 +557,7 @@ void ObjectTemplate::calculateVisitableOffset() visitableOffset = int3(0, 0, 0); } -bool ObjectTemplate::canBePlacedAt(TTerrainId terrain) const +bool ObjectTemplate::canBePlacedAt(TerrainId terrain) const { return vstd::contains(allowedTerrains, terrain); } diff --git a/lib/mapObjects/ObjectTemplate.h b/lib/mapObjects/ObjectTemplate.h index 2ac3825f6..b492d1770 100644 --- a/lib/mapObjects/ObjectTemplate.h +++ b/lib/mapObjects/ObjectTemplate.h @@ -33,7 +33,7 @@ class DLL_LINKAGE ObjectTemplate /// directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7) ui8 visitDir; /// list of terrains on which this object can be placed - std::set allowedTerrains; + std::set allowedTerrains; void afterLoadFixup(); @@ -100,7 +100,7 @@ public: }; // Checks if object can be placed on specific terrain - bool canBePlacedAt(TTerrainId terrain) const; + bool canBePlacedAt(TerrainId terrain) const; ObjectTemplate(); //custom copy constructor is required diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 0c09e2d15..4c529b17f 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -158,14 +158,14 @@ CDrawLinesOperation::CDrawLinesOperation(CMap * map, const CTerrainSelection & t } ///CDrawRoadsOperation -CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen): +CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel,gen), roadType(roadType) { } ///CDrawRiversOperation -CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRiverId riverType, CRandomGenerator * gen): +CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId riverType, CRandomGenerator * gen): CDrawLinesOperation(map, terrainSel, gen), riverType(riverType) { diff --git a/lib/mapping/CDrawRoadsOperation.h b/lib/mapping/CDrawRoadsOperation.h index fb4e27af7..bb31868d0 100644 --- a/lib/mapping/CDrawRoadsOperation.h +++ b/lib/mapping/CDrawRoadsOperation.h @@ -63,7 +63,7 @@ protected: class CDrawRoadsOperation : public CDrawLinesOperation { public: - CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen); + CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -74,13 +74,13 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - TRoadId roadType; + RoadId roadType; }; class CDrawRiversOperation : public CDrawLinesOperation { public: - CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, TRoadId roadType, CRandomGenerator * gen); + CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, CRandomGenerator * gen); std::string getLabel() const override; protected: @@ -91,7 +91,7 @@ protected: void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override; private: - TRiverId riverType; + RiverId riverType; }; VCMI_LIB_NAMESPACE_END diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 814012c4b..1935ca6b8 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -126,19 +126,19 @@ void CMapEditManager::clearTerrain(CRandomGenerator * gen) execute(make_unique(map, gen ? gen : &(this->gen))); } -void CMapEditManager::drawTerrain(TTerrainId terType, CRandomGenerator * gen) +void CMapEditManager::drawTerrain(TerrainId terType, CRandomGenerator * gen) { execute(make_unique(map, terrainSel, terType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); } -void CMapEditManager::drawRoad(TRoadId roadType, CRandomGenerator* gen) +void CMapEditManager::drawRoad(RoadId roadType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, roadType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); } -void CMapEditManager::drawRiver(TRiverId riverType, CRandomGenerator* gen) +void CMapEditManager::drawRiver(RiverId riverType, CRandomGenerator* gen) { execute(make_unique(map, terrainSel, riverType, gen ? gen : &(this->gen))); terrainSel.clearSelection(); diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 279a74217..c8dcbabbc 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -72,13 +72,13 @@ public: void clearTerrain(CRandomGenerator * gen = nullptr); /// Draws terrain at the current terrain selection. The selection will be cleared automatically. - void drawTerrain(TTerrainId terType, CRandomGenerator * gen = nullptr); + void drawTerrain(TerrainId terType, CRandomGenerator * gen = nullptr); /// Draws roads at the current terrain selection. The selection will be cleared automatically. - void drawRoad(TRoadId roadType, CRandomGenerator * gen = nullptr); + void drawRoad(RoadId roadType, CRandomGenerator * gen = nullptr); /// Draws rivers at the current terrain selection. The selection will be cleared automatically. - void drawRiver(TRiverId riverType, CRandomGenerator * gen = nullptr); + void drawRiver(RiverId riverType, CRandomGenerator * gen = nullptr); void insertObject(CGObjectInstance * obj); void insertObjects(std::set & objects); diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 00682e236..b7a6872cb 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -83,7 +83,7 @@ void CComposedOperation::addOperation(std::unique_ptr&& operation operations.push_back(std::move(operation)); } -CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, TTerrainId terType, CRandomGenerator* gen): +CDrawTerrainOperation::CDrawTerrainOperation(CMap* map, const CTerrainSelection& terrainSel, TerrainId terType, CRandomGenerator* gen): CMapOperation(map), terrainSel(terrainSel), terType(terType), diff --git a/lib/mapping/CMapOperation.h b/lib/mapping/CMapOperation.h index cc20afb65..96e110699 100644 --- a/lib/mapping/CMapOperation.h +++ b/lib/mapping/CMapOperation.h @@ -63,7 +63,7 @@ private: class CDrawTerrainOperation : public CMapOperation { public: - CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, TTerrainId terType, CRandomGenerator * gen); + CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, TerrainId terType, CRandomGenerator * gen); void execute() override; void undo() override; @@ -100,7 +100,7 @@ private: ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const; CTerrainSelection terrainSel; - TTerrainId terType; + TerrainId terType; CRandomGenerator* gen; std::set invalidatedTerViews; }; diff --git a/lib/mapping/MapEditUtils.cpp b/lib/mapping/MapEditUtils.cpp index 849659094..b0e9dc822 100644 --- a/lib/mapping/MapEditUtils.cpp +++ b/lib/mapping/MapEditUtils.cpp @@ -270,7 +270,7 @@ CTerrainViewPatternConfig::~CTerrainViewPatternConfig() } -const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TTerrainId terrain) const +const std::vector & CTerrainViewPatternConfig::getTerrainViewPatterns(TerrainId terrain) const { auto iter = terrainViewPatterns.find(VLC->terrainTypeHandler->terrains()[terrain].terrainViewPatterns); if (iter == terrainViewPatterns.end()) @@ -295,7 +295,7 @@ boost::optional CTerrainViewPatternConfig::getTerrai return boost::optional(); } -boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(TTerrainId terrain, const std::string & id) const +boost::optional CTerrainViewPatternConfig::getTerrainViewPatternsById(TerrainId terrain, const std::string & id) const { const std::vector & groupPatterns = getTerrainViewPatterns(terrain); for (const TVPVector & patternFlips : groupPatterns) diff --git a/lib/mapping/MapEditUtils.h b/lib/mapping/MapEditUtils.h index bdb3c1df6..288cc7b5a 100644 --- a/lib/mapping/MapEditUtils.h +++ b/lib/mapping/MapEditUtils.h @@ -217,9 +217,9 @@ public: CTerrainViewPatternConfig(); ~CTerrainViewPatternConfig(); - const std::vector & getTerrainViewPatterns(TTerrainId terrain) const; + const std::vector & getTerrainViewPatterns(TerrainId terrain) const; boost::optional getTerrainViewPatternById(std::string patternId, const std::string & id) const; - boost::optional getTerrainViewPatternsById(TTerrainId terrain, const std::string & id) const; + boost::optional getTerrainViewPatternsById(TerrainId terrain, const std::string & id) const; const TVPVector * getTerrainTypePatternById(const std::string & id) const; void flipPattern(TerrainViewPattern & pattern, int flip) const; diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index fae27e980..7e1051a5f 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -217,12 +217,12 @@ boost::optional ZoneOptions::getOwner() const return owner; } -const std::set & ZoneOptions::getTerrainTypes() const +const std::set & ZoneOptions::getTerrainTypes() const { return terrainTypes; } -void ZoneOptions::setTerrainTypes(const std::set & value) +void ZoneOptions::setTerrainTypes(const std::set & value) { //assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() && // value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end()); diff --git a/lib/rmg/CRmgTemplate.h b/lib/rmg/CRmgTemplate.h index eaeb82f02..2b8ba45e3 100644 --- a/lib/rmg/CRmgTemplate.h +++ b/lib/rmg/CRmgTemplate.h @@ -105,8 +105,8 @@ public: void setSize(int value); boost::optional getOwner() const; - const std::set & getTerrainTypes() const; - void setTerrainTypes(const std::set & value); + const std::set & getTerrainTypes() const; + void setTerrainTypes(const std::set & value); const CTownInfo & getPlayerTowns() const; const CTownInfo & getNeutralTowns() const; @@ -146,7 +146,7 @@ protected: CTownInfo playerTowns; CTownInfo neutralTowns; bool matchTerrainToTown; - std::set terrainTypes; + std::set terrainTypes; bool townsAreSameType; std::set townTypes; diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index de90ee8c1..c73184bd9 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -95,14 +95,14 @@ void createBorder(RmgMap & gen, Zone & zone) } } -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrainId terrain) +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TerrainId terrain) { auto v = zone.getArea().getTilesVector(); map.getEditManager()->getTerrainSelection().setSelection(v); map.getEditManager()->drawTerrain(terrain, &generator); } -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrainId terrain) +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TerrainId terrain) { auto factories = VLC->objtypeh->knownSubObjects(ObjID); vstd::erase_if(factories, [ObjID, &terrain](si32 f) @@ -118,7 +118,7 @@ void initTerrainType(Zone & zone, CMapGenerator & gen) if(zone.getType()==ETemplateZoneType::WATER) { //collect all water terrain types - std::vector waterTerrains; + std::vector waterTerrains; for(const auto & terrain : VLC->terrainTypeHandler->terrains()) if(terrain.isWater()) waterTerrains.push_back(terrain.id); diff --git a/lib/rmg/Functions.h b/lib/rmg/Functions.h index fe9f35225..9e60506cf 100644 --- a/lib/rmg/Functions.h +++ b/lib/rmg/Functions.h @@ -42,11 +42,11 @@ rmg::Tileset collectDistantTiles(const Zone & zone, int distance); void createBorder(RmgMap & gen, Zone & zone); -void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TTerrainId terrainType); +void paintZoneTerrain(const Zone & zone, CRandomGenerator & generator, RmgMap & map, TerrainId terrainType); void initTerrainType(Zone & zone, CMapGenerator & gen); -int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TTerrainId terrain); +int chooseRandomAppearance(CRandomGenerator & generator, si32 ObjID, TerrainId terrain); VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/ObstaclePlacer.cpp b/lib/rmg/ObstaclePlacer.cpp index adcad19d4..48eba161f 100644 --- a/lib/rmg/ObstaclePlacer.cpp +++ b/lib/rmg/ObstaclePlacer.cpp @@ -26,7 +26,7 @@ VCMI_LIB_NAMESPACE_BEGIN -void ObstacleProxy::collectPossibleObstacles(TTerrainId terrain) +void ObstacleProxy::collectPossibleObstacles(TerrainId terrain) { //get all possible obstacles for this terrain for(auto primaryID : VLC->objtypeh->knownObjects()) diff --git a/lib/rmg/ObstaclePlacer.h b/lib/rmg/ObstaclePlacer.h index beeabde74..b18a1bae0 100644 --- a/lib/rmg/ObstaclePlacer.h +++ b/lib/rmg/ObstaclePlacer.h @@ -26,7 +26,7 @@ public: rmg::Area blockedArea; - void collectPossibleObstacles(TTerrainId terrain); + void collectPossibleObstacles(TerrainId terrain); void placeObstacles(CMap * map, CRandomGenerator & rand); diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index 924e57638..c1aac566e 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -231,7 +231,7 @@ void RmgMap::setOccupied(const int3 &tile, ETileType::ETileType state) tiles[tile.x][tile.y][tile.z].setOccupied(state); } -void RmgMap::setRoad(const int3& tile, TRoadId roadType) +void RmgMap::setRoad(const int3& tile, RoadId roadType) { assertOnMap(tile); diff --git a/lib/rmg/RmgMap.h b/lib/rmg/RmgMap.h index 920e94449..16b160d54 100644 --- a/lib/rmg/RmgMap.h +++ b/lib/rmg/RmgMap.h @@ -46,7 +46,7 @@ public: bool isOnMap(const int3 & tile) const; void setOccupied(const int3 &tile, ETileType::ETileType state); - void setRoad(const int3 &tile, TRoadId roadType); + void setRoad(const int3 &tile, RoadId roadType); TileInfo getTile(const int3 & tile) const; diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index eb3bebc70..9758e94ad 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -105,7 +105,7 @@ void Object::Instance::setPositionRaw(const int3 & position) dObject.pos = dPosition + dParent.getPosition(); } -void Object::Instance::setTemplate(const TTerrainId & terrain) +void Object::Instance::setTemplate(const TerrainId & terrain) { if(dObject.appearance->id == Obj::NO_OBJ) { @@ -259,7 +259,7 @@ void Object::setPosition(const int3 & position) i.setPositionRaw(i.getPosition()); } -void Object::setTemplate(const TTerrainId & terrain) +void Object::setTemplate(const TerrainId & terrain) { for(auto& i : dInstances) i.setTemplate(terrain); diff --git a/lib/rmg/RmgObject.h b/lib/rmg/RmgObject.h index 36365cba2..627cd9599 100644 --- a/lib/rmg/RmgObject.h +++ b/lib/rmg/RmgObject.h @@ -35,7 +35,7 @@ public: int3 getVisitablePosition() const; bool isVisitableFrom(const int3 & tile) const; const Area & getAccessibleArea() const; - void setTemplate(const TTerrainId & terrain); //cache invalidation + void setTemplate(const TerrainId & terrain); //cache invalidation int3 getPosition(bool isAbsolute = false) const; void setPosition(const int3 & position); //cache invalidation @@ -71,7 +71,7 @@ public: const int3 & getPosition() const; void setPosition(const int3 & position); - void setTemplate(const TTerrainId & terrain); + void setTemplate(const TerrainId & terrain); const Area & getArea() const; //lazy cache invalidation diff --git a/lib/rmg/RoadPlacer.cpp b/lib/rmg/RoadPlacer.cpp index d58f59648..a435395af 100644 --- a/lib/rmg/RoadPlacer.cpp +++ b/lib/rmg/RoadPlacer.cpp @@ -72,7 +72,7 @@ void RoadPlacer::drawRoads(bool secondary) zone.freePaths().unite(roads); map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector()); std::string roadCode = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType); - TRoadId roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id; + RoadId roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id; map.getEditManager()->drawRoad(roadType, &generator.rand); } diff --git a/lib/rmg/RockPlacer.h b/lib/rmg/RockPlacer.h index bd2b690e5..63789b1bf 100644 --- a/lib/rmg/RockPlacer.h +++ b/lib/rmg/RockPlacer.h @@ -28,7 +28,7 @@ public: protected: rmg::Area rockArea, accessibleArea; - TTerrainId rockTerrain; + TerrainId rockTerrain; }; VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/TileInfo.cpp b/lib/rmg/TileInfo.cpp index 3aad32ffd..4b37f2d99 100644 --- a/lib/rmg/TileInfo.cpp +++ b/lib/rmg/TileInfo.cpp @@ -63,17 +63,17 @@ ETileType::ETileType TileInfo::getTileType() const return occupied; } -TTerrainId TileInfo::getTerrainType() const +TerrainId TileInfo::getTerrainType() const { return terrain; } -void TileInfo::setTerrainType(TTerrainId type) +void TileInfo::setTerrainType(TerrainId type) { terrain = type; } -void TileInfo::setRoadType(TRoadId type) +void TileInfo::setRoadType(RoadId type) { roadType = type; // setOccupied(ETileType::FREE); diff --git a/lib/rmg/TileInfo.h b/lib/rmg/TileInfo.h index 0ac60d35d..951334b6d 100644 --- a/lib/rmg/TileInfo.h +++ b/lib/rmg/TileInfo.h @@ -30,16 +30,16 @@ public: bool isUsed() const; bool isRoad() const; void setOccupied(ETileType::ETileType value); - TTerrainId getTerrainType() const; + TerrainId getTerrainType() const; ETileType::ETileType getTileType() const; - void setTerrainType(TTerrainId value); + void setTerrainType(TerrainId value); - void setRoadType(TRoadId type); + void setRoadType(RoadId type); private: float nearestObjectDistance; ETileType::ETileType occupied; - TTerrainId terrain; - TRoadId roadType; + TerrainId terrain; + RoadId roadType; }; VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 789d31eb7..0af06497c 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -813,7 +813,7 @@ ObjectInfo::ObjectInfo() } -void ObjectInfo::setTemplate(si32 type, si32 subtype, TTerrainId terrainType) +void ObjectInfo::setTemplate(si32 type, si32 subtype, TerrainId terrainType) { auto templHandler = VLC->objtypeh->getHandlerFor(type, subtype); if(!templHandler) diff --git a/lib/rmg/TreasurePlacer.h b/lib/rmg/TreasurePlacer.h index 63c77a0e4..eea60f255 100644 --- a/lib/rmg/TreasurePlacer.h +++ b/lib/rmg/TreasurePlacer.h @@ -28,7 +28,7 @@ struct ObjectInfo //ui32 maxPerMap; //unused std::function generateObject; - void setTemplate(si32 type, si32 subtype, TTerrainId terrain); + void setTemplate(si32 type, si32 subtype, TerrainId terrain); ObjectInfo(); diff --git a/lib/rmg/Zone.cpp b/lib/rmg/Zone.cpp index 6e59b56e5..fef80250f 100644 --- a/lib/rmg/Zone.cpp +++ b/lib/rmg/Zone.cpp @@ -134,12 +134,12 @@ void Zone::setTownType(si32 town) townType = town; } -TTerrainId Zone::getTerrainType() const +TerrainId Zone::getTerrainType() const { return terrainType; } -void Zone::setTerrainType(TTerrainId terrain) +void Zone::setTerrainType(TerrainId terrain) { terrainType = terrain; } diff --git a/lib/rmg/Zone.h b/lib/rmg/Zone.h index 01c152f21..d5d9521e2 100644 --- a/lib/rmg/Zone.h +++ b/lib/rmg/Zone.h @@ -100,8 +100,8 @@ public: si32 getTownType() const; void setTownType(si32 town); - TTerrainId getTerrainType() const; - void setTerrainType(TTerrainId terrain); + TerrainId getTerrainType() const; + void setTerrainType(TerrainId terrain); void connectPath(const rmg::Path & path); rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, std::function areafilter = AREA_NO_FILTER) const; @@ -140,7 +140,7 @@ protected: //template info si32 townType; - TTerrainId terrainType; + TerrainId terrainType; }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index d37e6902e..73587ed1f 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2241,7 +2241,7 @@ void CGameHandler::setupBattle(int3 tile, const CArmedInstance *armies[2], const battleResult.set(nullptr); const auto & t = *getTile(tile); - TTerrainId terrain = t.terType->id; + TerrainId terrain = t.terType->id; if (gs->map->isCoastalTile(tile)) //coastal tile is always ground terrain = Terrain::SAND; diff --git a/test/game/CGameStateTest.cpp b/test/game/CGameStateTest.cpp index cbda7d01e..67d7d49d8 100644 --- a/test/game/CGameStateTest.cpp +++ b/test/game/CGameStateTest.cpp @@ -193,7 +193,7 @@ public: const auto & t = *gameCallback->getTile(tile); - TTerrainId terrain = t.terType->id; + TerrainId terrain = t.terType->id; BattleField terType = BattleField::fromString("grass_hills"); //send info about battles diff --git a/test/mock/mock_IBattleInfoCallback.h b/test/mock/mock_IBattleInfoCallback.h index aa9183de7..b051f4355 100644 --- a/test/mock/mock_IBattleInfoCallback.h +++ b/test/mock/mock_IBattleInfoCallback.h @@ -17,7 +17,7 @@ class IBattleInfoCallbackMock : public IBattleInfoCallback { public: MOCK_CONST_METHOD0(getContextPool, scripting::Pool *()); - MOCK_CONST_METHOD0(battleTerrainType, TTerrainId()); + MOCK_CONST_METHOD0(battleTerrainType, TerrainId()); MOCK_CONST_METHOD0(battleGetBattlefieldType, BattleField()); MOCK_CONST_METHOD0(battleIsFinished, boost::optional()); diff --git a/test/mock/mock_battle_IBattleState.h b/test/mock/mock_battle_IBattleState.h index c63d2716f..779c12773 100644 --- a/test/mock/mock_battle_IBattleState.h +++ b/test/mock/mock_battle_IBattleState.h @@ -19,7 +19,7 @@ public: MOCK_CONST_METHOD1(getStacksIf, TStacks(TStackFilter)); MOCK_CONST_METHOD1(getUnitsIf, battle::Units(battle::UnitFilter)); MOCK_CONST_METHOD0(getBattlefieldType, BattleField()); - MOCK_CONST_METHOD0(getTerrainType, TTerrainId()); + MOCK_CONST_METHOD0(getTerrainType, TerrainId()); MOCK_CONST_METHOD0(getAllObstacles, IBattleInfo::ObstacleCList()); MOCK_CONST_METHOD0(getDefendedTown, const CGTownInstance *()); MOCK_CONST_METHOD1(getWallState, si8(int)); From e8a1709fc4e9cd57290fe51193f570c22a60dfcc Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Thu, 29 Sep 2022 12:47:31 +0300 Subject: [PATCH 47/74] fix typo in file name --- client/CMakeLists.txt | 4 ++-- ...ChatKeyboardHanlder.h => GameChatKeyboardHandler.h} | 4 ++-- ...ChatKeyboardHanlder.m => GameChatKeyboardHandler.m} | 10 +++++----- client/ios/startSDL.mm | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) rename client/ios/{GameChatKeyboardHanlder.h => GameChatKeyboardHandler.h} (78%) rename client/ios/{GameChatKeyboardHanlder.m => GameChatKeyboardHandler.m} (93%) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ac82ff72e..7c6c0a507 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -148,14 +148,14 @@ set(client_HEADERS if(APPLE_IOS) set(client_SRCS ${client_SRCS} CFocusableHelper.cpp - ios/GameChatKeyboardHanlder.m + ios/GameChatKeyboardHandler.m ios/main.m ios/startSDL.mm ios/utils.mm ) set(client_HEADERS ${client_HEADERS} CFocusableHelper.h - ios/GameChatKeyboardHanlder.h + ios/GameChatKeyboardHandler.h ios/startSDL.h ios/utils.h ) diff --git a/client/ios/GameChatKeyboardHanlder.h b/client/ios/GameChatKeyboardHandler.h similarity index 78% rename from client/ios/GameChatKeyboardHanlder.h rename to client/ios/GameChatKeyboardHandler.h index 8f4f8e9c2..76f13a6c9 100644 --- a/client/ios/GameChatKeyboardHanlder.h +++ b/client/ios/GameChatKeyboardHandler.h @@ -1,5 +1,5 @@ /* - * GameChatKeyboardHanlder.h, part of VCMI engine + * GameChatKeyboardHandler.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * @@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface GameChatKeyboardHanlder : NSObject +@interface GameChatKeyboardHandler : NSObject @property (nonatomic, weak) UITextField * textFieldSDL; diff --git a/client/ios/GameChatKeyboardHanlder.m b/client/ios/GameChatKeyboardHandler.m similarity index 93% rename from client/ios/GameChatKeyboardHanlder.m rename to client/ios/GameChatKeyboardHandler.m index 24336f592..4a3d100be 100644 --- a/client/ios/GameChatKeyboardHanlder.m +++ b/client/ios/GameChatKeyboardHandler.m @@ -1,5 +1,5 @@ /* - * GameChatKeyboardHanlder.m, part of VCMI engine + * GameChatKeyboardHandler.m, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * @@ -8,7 +8,7 @@ * */ -#import "GameChatKeyboardHanlder.h" +#import "GameChatKeyboardHandler.h" #include @@ -32,11 +32,11 @@ static CGRect keyboardFrameBegin(NSNotification * n) { return keyboardFrame(n, U static CGRect keyboardFrameEnd (NSNotification * n) { return keyboardFrame(n, UIKeyboardFrameEndUserInfoKey); } -@interface GameChatKeyboardHanlder () +@interface GameChatKeyboardHandler () @property (nonatomic) BOOL wasChatMessageSent; @end -@implementation GameChatKeyboardHanlder +@implementation GameChatKeyboardHandler - (void)triggerInput { __auto_type notificationCenter = NSNotificationCenter.defaultCenter; @@ -99,7 +99,7 @@ static int watchReturnKey(void * userdata, SDL_Event * event) { if(event->type == SDL_KEYDOWN && event->key.keysym.scancode == SDL_SCANCODE_RETURN) { - __auto_type self = (__bridge GameChatKeyboardHanlder *)userdata; + __auto_type self = (__bridge GameChatKeyboardHandler *)userdata; self.wasChatMessageSent = YES; SDL_DelEventWatch(watchReturnKey, userdata); } diff --git a/client/ios/startSDL.mm b/client/ios/startSDL.mm index 6cf867478..feb03d6ca 100644 --- a/client/ios/startSDL.mm +++ b/client/ios/startSDL.mm @@ -8,7 +8,7 @@ * */ #import "startSDL.h" -#import "GameChatKeyboardHanlder.h" +#import "GameChatKeyboardHandler.h" #include "../Global.h" #include "CMT.h" @@ -23,7 +23,7 @@ #import @interface SDLViewObserver : NSObject -@property (nonatomic, strong) GameChatKeyboardHanlder * gameChatHandler; +@property (nonatomic, strong) GameChatKeyboardHandler * gameChatHandler; @end @implementation SDLViewObserver @@ -131,7 +131,7 @@ int startSDL(int argc, char * argv[], BOOL startManually) { @autoreleasepool { auto observer = [SDLViewObserver new]; - observer.gameChatHandler = [GameChatKeyboardHanlder new]; + observer.gameChatHandler = [GameChatKeyboardHandler new]; id __block sdlWindowCreationObserver = [NSNotificationCenter.defaultCenter addObserverForName:UIWindowDidBecomeKeyNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { [NSNotificationCenter.defaultCenter removeObserver:sdlWindowCreationObserver]; From 593df25df51a35b70eca21fca1bd900c872562d8 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Thu, 29 Sep 2022 13:23:15 +0300 Subject: [PATCH 48/74] [iOS] use SDL's standard input handling for in-game chat --- client/ios/GameChatKeyboardHandler.h | 2 -- client/ios/GameChatKeyboardHandler.m | 37 ---------------------------- client/ios/startSDL.mm | 20 --------------- 3 files changed, 59 deletions(-) diff --git a/client/ios/GameChatKeyboardHandler.h b/client/ios/GameChatKeyboardHandler.h index 76f13a6c9..01d8fd694 100644 --- a/client/ios/GameChatKeyboardHandler.h +++ b/client/ios/GameChatKeyboardHandler.h @@ -14,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN @interface GameChatKeyboardHandler : NSObject -@property (nonatomic, weak) UITextField * textFieldSDL; - - (void)triggerInput; @end diff --git a/client/ios/GameChatKeyboardHandler.m b/client/ios/GameChatKeyboardHandler.m index 4a3d100be..276ece8bb 100644 --- a/client/ios/GameChatKeyboardHandler.m +++ b/client/ios/GameChatKeyboardHandler.m @@ -24,13 +24,6 @@ static void sendKeyEvent(SDL_KeyCode keyCode) SDL_PushEvent(&keyEvent); } -static CGRect keyboardFrame(NSNotification * n, NSString * userInfoKey) -{ - return [n.userInfo[userInfoKey] CGRectValue]; -} -static CGRect keyboardFrameBegin(NSNotification * n) { return keyboardFrame(n, UIKeyboardFrameBeginUserInfoKey); } -static CGRect keyboardFrameEnd (NSNotification * n) { return keyboardFrame(n, UIKeyboardFrameEndUserInfoKey); } - @interface GameChatKeyboardHandler () @property (nonatomic) BOOL wasChatMessageSent; @@ -42,56 +35,26 @@ static CGRect keyboardFrameEnd (NSNotification * n) { return keyboardFrame(n, U __auto_type notificationCenter = NSNotificationCenter.defaultCenter; [notificationCenter addObserver:self selector:@selector(textDidBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil]; [notificationCenter addObserver:self selector:@selector(textDidEndEditing:) name:UITextFieldTextDidEndEditingNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; - [notificationCenter addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil]; self.wasChatMessageSent = NO; sendKeyEvent(SDLK_TAB); } -- (void)positionTextFieldAboveKeyboardRect:(CGRect)kbFrame { - __auto_type r = kbFrame; - r.size.height = CGRectGetHeight(self.textFieldSDL.frame); - r.origin.y -= r.size.height; - self.textFieldSDL.frame = r; -} - #pragma mark - Notifications - (void)textDidBeginEditing:(NSNotification *)n { - self.textFieldSDL.hidden = NO; - self.textFieldSDL.text = nil; - // watch for pressing Return to ignore sending Escape key after keyboard is closed SDL_AddEventWatch(watchReturnKey, (__bridge void *)self); } - (void)textDidEndEditing:(NSNotification *)n { [NSNotificationCenter.defaultCenter removeObserver:self]; - self.textFieldSDL.hidden = YES; // discard chat message if(!self.wasChatMessageSent) sendKeyEvent(SDLK_ESCAPE); } -- (void)keyboardWillChangeFrame:(NSNotification *)n { - // animate textfield together with keyboard - [UIView performWithoutAnimation:^{ - [self positionTextFieldAboveKeyboardRect:keyboardFrameBegin(n)]; - }]; - - NSTimeInterval kbAnimationDuration = [n.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; - NSUInteger kbAnimationCurve = [n.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]; - [UIView animateWithDuration:kbAnimationDuration delay:0 options:(kbAnimationCurve << 16) animations:^{ - [self positionTextFieldAboveKeyboardRect:keyboardFrameEnd(n)]; - } completion:nil]; -} - -- (void)keyboardDidChangeFrame:(NSNotification *)n { - [self positionTextFieldAboveKeyboardRect:keyboardFrameEnd(n)]; -} - @end diff --git a/client/ios/startSDL.mm b/client/ios/startSDL.mm index feb03d6ca..c9ada242b 100644 --- a/client/ios/startSDL.mm +++ b/client/ios/startSDL.mm @@ -33,26 +33,6 @@ UIView * view = [object valueForKeyPath:keyPath]; - UITextField * textField; - for (UIView * v in view.subviews) { - if ([v isKindOfClass:[UITextField class]]) { - textField = (UITextField *)v; - break; - } - } - - auto r = textField.frame; - r.size.height = 40; - textField.frame = r; - self.gameChatHandler.textFieldSDL = textField; - -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 - if(@available(iOS 13.0, *)) - textField.backgroundColor = UIColor.systemBackgroundColor; - else -#endif - textField.backgroundColor = UIColor.whiteColor; - auto longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; longPress.minimumPressDuration = 0.2; [view addGestureRecognizer:longPress]; From 8c8394b6ed2e1347c622218a794a793955e5b9c5 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Thu, 29 Sep 2022 13:24:23 +0300 Subject: [PATCH 49/74] fix passing coordinates of the status bar when triggering in-game console input --- client/widgets/AdventureMapClasses.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/widgets/AdventureMapClasses.cpp b/client/widgets/AdventureMapClasses.cpp index 4aead3f7a..a561ee089 100644 --- a/client/widgets/AdventureMapClasses.cpp +++ b/client/widgets/AdventureMapClasses.cpp @@ -1129,7 +1129,7 @@ void CInGameConsole::textEdited(const SDL_TextEditingEvent & event) void CInGameConsole::startEnteringText() { - CSDL_Ext::startTextInput(&pos); + CSDL_Ext::startTextInput(&GH.statusbar->pos); enteredText = "_"; if(GH.topInt() == adventureInt) From 836d7dc2d64387011956a2c4af0d09d1b478946b Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Thu, 29 Sep 2022 15:52:28 +0300 Subject: [PATCH 50/74] prohibit digging while waiting for your turn to start --- client/windows/CAdvmapInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/windows/CAdvmapInterface.cpp b/client/windows/CAdvmapInterface.cpp index 13c8fc232..00ee474b9 100644 --- a/client/windows/CAdvmapInterface.cpp +++ b/client/windows/CAdvmapInterface.cpp @@ -1234,7 +1234,7 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) return; case SDLK_d: { - if(h && isActive() && key.state == SDL_PRESSED) + if(h && isActive() && LOCPLINT->makingTurn && key.state == SDL_PRESSED) LOCPLINT->tryDiggging(h); return; } From 127d7ec40b46aac7b09fc7d9e41fb51e12b37d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 29 Sep 2022 21:10:44 +0200 Subject: [PATCH 51/74] Fixed asserts (only for debug build) --- lib/Terrain.cpp | 2 +- lib/mapObjects/ObjectTemplate.cpp | 2 +- lib/rmg/WaterProxy.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index b6f399d12..ea42f3774 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -194,7 +194,7 @@ void TerrainTypeHandler::initTerrains(const std::vector & allConfig for(size_t i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ORIGINAL_TERRAIN_COUNT; i++) { //Make sure that original terrains are loaded - assert(objects(i).id != Terrain::WRONG); + assert(objects[i].id != Terrain::WRONG); } recreateTerrainMaps(); diff --git a/lib/mapObjects/ObjectTemplate.cpp b/lib/mapObjects/ObjectTemplate.cpp index a23b3db36..9caec2379 100644 --- a/lib/mapObjects/ObjectTemplate.cpp +++ b/lib/mapObjects/ObjectTemplate.cpp @@ -157,7 +157,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser) // so these two fields can be interpreted as "strong affinity" and "weak affinity" towards terrains std::string & terrStr = strings[4]; // allowed terrains, 1 = object can be placed on this terrain - assert(terrStr.size() == Terrain::ROCK - 1); // all terrains but rock + assert(terrStr.size() == Terrain::ROCK); // all terrains but rock - counting from 0 for(TerrainId i = Terrain::FIRST_REGULAR_TERRAIN; i < Terrain::ROCK; i++) { if (terrStr[8-i] == '1') diff --git a/lib/rmg/WaterProxy.cpp b/lib/rmg/WaterProxy.cpp index 8405a7640..84f62cf93 100644 --- a/lib/rmg/WaterProxy.cpp +++ b/lib/rmg/WaterProxy.cpp @@ -43,7 +43,7 @@ void WaterProxy::process() for(auto & t : zone.area().getTilesVector()) { assert(map.isOnMap(t)); - assert(map.map().getTile(t).terType == zone.getTerrainType()); + assert(map.map().getTile(t).terType->id == zone.getTerrainType()); } for(auto z : map.getZones()) From 48150211d960f9db34af52373b02c60b9c36b9cc Mon Sep 17 00:00:00 2001 From: Alexander Wilms Date: Thu, 29 Sep 2022 23:07:54 +0200 Subject: [PATCH 52/74] Update bug tracker URL in metainfo --- launcher/eu.vcmi.VCMI.metainfo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/eu.vcmi.VCMI.metainfo.xml b/launcher/eu.vcmi.VCMI.metainfo.xml index b5240d3d4..1a17c278b 100644 --- a/launcher/eu.vcmi.VCMI.metainfo.xml +++ b/launcher/eu.vcmi.VCMI.metainfo.xml @@ -35,7 +35,7 @@ https://vcmi.eu/ - https://bugs.vcmi.eu/ + https://github.com/vcmi/vcmi/issues https://vcmi.eu/faq/ From a11135152c72c83e74c8205bcb88a2e98e4ae2f3 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 11:26:36 +0300 Subject: [PATCH 53/74] remove trivial manual implementation of assignment operator fixes clang warning: Definition of implicit copy constructor for 'RiverType' is deprecated because it has a user-provided copy assignment operator --- lib/Terrain.cpp | 46 +--------------------------------------------- lib/Terrain.h | 6 ------ 2 files changed, 1 insertion(+), 51 deletions(-) diff --git a/lib/Terrain.cpp b/lib/Terrain.cpp index ea42f3774..fff98de34 100644 --- a/lib/Terrain.cpp +++ b/lib/Terrain.cpp @@ -397,30 +397,6 @@ TerrainType::TerrainType(const std::string& _name): transitionRequired(false) { } - -TerrainType& TerrainType::operator=(const TerrainType & other) -{ - battleFields = other.battleFields; - prohibitTransitions = other.prohibitTransitions; - minimapBlocked = other.minimapBlocked; - minimapUnblocked = other.minimapUnblocked; - name = other.name; - musicFilename = other.musicFilename; - tilesFilename = other.tilesFilename; - terrainText = other.terrainText; - typeCode = other.typeCode; - terrainViewPatterns = other.terrainViewPatterns; - rockTerrain = other.rockTerrain; - river = other.river; - - id = other.id; - moveCost = other.moveCost; - horseSoundId = other.horseSoundId; - passabilityType = other.passabilityType; - transitionRequired = other.transitionRequired; - - return *this; -} bool TerrainType::operator==(const TerrainType& other) { @@ -474,16 +450,6 @@ RiverType::RiverType(const std::string & fileName, const std::string & code, Riv { } -RiverType& RiverType::operator=(const RiverType& other) -{ - fileName = other.fileName; - code = other.code; - deltaName = other.deltaName; - id = other.id; - - return *this; -} - RoadType::RoadType(const std::string& fileName, const std::string& code, RoadId id): fileName(fileName), code(code), @@ -492,14 +458,4 @@ RoadType::RoadType(const std::string& fileName, const std::string& code, RoadId { } -RoadType& RoadType::operator=(const RoadType& other) -{ - fileName = other.fileName; - code = other.code; - id = other.id; - movementCost = other.movementCost; - - return *this; -} - -VCMI_LIB_NAMESPACE_END \ No newline at end of file +VCMI_LIB_NAMESPACE_END diff --git a/lib/Terrain.h b/lib/Terrain.h index a4aae7b8a..6e23a9ca2 100644 --- a/lib/Terrain.h +++ b/lib/Terrain.h @@ -49,8 +49,6 @@ public: bool transitionRequired; TerrainType(const std::string & name = ""); - - TerrainType& operator=(const TerrainType & other); bool operator==(const TerrainType & other); bool operator!=(const TerrainType & other); @@ -99,8 +97,6 @@ public: RiverType(const std::string & fileName = "", const std::string & code = "", RiverId id = River::NO_RIVER); - RiverType& operator=(const RiverType & other); - template void serialize(Handler& h, const int version) { h & fileName; @@ -120,8 +116,6 @@ public: RoadType(const std::string & fileName = "", const std::string& code = "", RoadId id = Road::NO_ROAD); - RoadType& operator=(const RoadType & other); - template void serialize(Handler& h, const int version) { h & fileName; From 4a1933bac374e39cf41609d1ee8589a5ea68bc85 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 11:27:03 +0300 Subject: [PATCH 54/74] display build version in the launcher --- launcher/settingsView/csettingsview_moc.cpp | 1 + launcher/settingsView/csettingsview_moc.ui | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index 95c2a872a..668d12e43 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -115,6 +115,7 @@ CSettingsView::CSettingsView(QWidget * parent) { ui->setupUi(this); + ui->labelBuildVersion->setText(QString::fromStdString(GameConstants::VCMI_VERSION)); loadSettings(); } diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index ece3135b5..55ce6eb59 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -652,6 +652,20 @@ + + + + Build version + + + + + + + + + + From 3f61e6f964b40ed7b0c19a5f892981f19b7d6b3a Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 11:44:13 +0300 Subject: [PATCH 55/74] [iOS] allow setting custom app name --- CMakeLists.txt | 2 ++ client/ios/Info.plist | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c918facbd..a30aa67e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ option(ENABLE_LUA "Enable compilation of LUA scripting module" OFF) option(ENABLE_LAUNCHER "Enable compilation of launcher" ON) if(APPLE_IOS) set(BUNDLE_IDENTIFIER_PREFIX "" CACHE STRING "Bundle identifier prefix") + set(APP_DISPLAY_NAME "VCMI" CACHE STRING "App name on the home screen") else() option(ENABLE_TEST "Enable compilation of unit tests" ON) endif() @@ -155,6 +156,7 @@ set(CMAKE_MAP_IMPORTED_CONFIG_MINSIZEREL MinSizeRel Release RelWithDebInfo "") # Release falls back to RelWithDebInfo, then MinSizeRel set(CMAKE_MAP_IMPORTED_CONFIG_RELEASE Release RelWithDebInfo MinSizeRel "") +set(CMAKE_XCODE_ATTRIBUTE_APP_DISPLAY_NAME ${APP_DISPLAY_NAME}) set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Debug] dwarf) set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE NO) diff --git a/client/ios/Info.plist b/client/ios/Info.plist index 153c44960..61199ca88 100644 --- a/client/ios/Info.plist +++ b/client/ios/Info.plist @@ -11,7 +11,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - VCMI + $(APP_DISPLAY_NAME) CFBundlePackageType APPL CFBundleShortVersionString From 8e066a00bc59c642eea44e2fb551f8d83f6a4902 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 12:33:00 +0300 Subject: [PATCH 56/74] [iOS] set bundle version to date-commit --- client/CMakeLists.txt | 4 +++- ios/set_build_version.sh | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 ios/set_build_version.sh diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ac82ff72e..9fc4fa213 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -269,8 +269,10 @@ enable_pch(vcmiclient) if(APPLE_IOS) add_custom_command(TARGET vcmiclient POST_BUILD + COMMAND ios/set_build_version.sh "$" COMMAND ${CMAKE_COMMAND} --install "${CMAKE_BINARY_DIR}" --component "${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}" --config "$" --prefix "$" - COMMAND ${CMAKE_SOURCE_DIR}/ios/codesign.sh + COMMAND ios/codesign.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) install(TARGETS vcmiclient DESTINATION Payload COMPONENT app) # for ipa generation with cpack else() diff --git a/ios/set_build_version.sh b/ios/set_build_version.sh new file mode 100755 index 000000000..4e37f3279 --- /dev/null +++ b/ios/set_build_version.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +today=$(date '+%Y-%m-%d') +commitShort=$(git rev-parse --short HEAD) +bundleVersion="$today-$commitShort" + +/usr/libexec/PlistBuddy "$1/Info.plist" -c "Set :CFBundleVersion $bundleVersion" From 7801a2ad85c3c3219614863a4bb5c6f35a294997 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 12:52:45 +0300 Subject: [PATCH 57/74] [iOS] show app and bundle version in system settings --- client/ios/Settings.bundle/Root.plist | 20 +++++++++++++++++++ .../ios/Settings.bundle/en.lproj/Root.strings | 3 +++ .../ios/Settings.bundle/ru.lproj/Root.strings | 3 +++ ios/set_build_version.sh | 3 +++ 4 files changed, 29 insertions(+) diff --git a/client/ios/Settings.bundle/Root.plist b/client/ios/Settings.bundle/Root.plist index 747935f4d..74eab78c0 100644 --- a/client/ios/Settings.bundle/Root.plist +++ b/client/ios/Settings.bundle/Root.plist @@ -6,6 +6,26 @@ Root PreferenceSpecifiers + + Type + PSTitleValueSpecifier + Title + AppVersion + Key + foo1 + DefaultValue + + + + Type + PSTitleValueSpecifier + Title + BuildVersion + Key + foo2 + DefaultValue + + Type PSRadioGroupSpecifier diff --git a/client/ios/Settings.bundle/en.lproj/Root.strings b/client/ios/Settings.bundle/en.lproj/Root.strings index 4348ab181..04e4bb2f0 100644 --- a/client/ios/Settings.bundle/en.lproj/Root.strings +++ b/client/ios/Settings.bundle/en.lproj/Root.strings @@ -1,3 +1,6 @@ "LaunchType" = "App start type"; "Launcher" = "Launcher"; "Game" = "Game"; + +"AppVersion" = "Application version"; +"BuildVersion" = "Build version"; diff --git a/client/ios/Settings.bundle/ru.lproj/Root.strings b/client/ios/Settings.bundle/ru.lproj/Root.strings index 8661a436c..2b4f0738f 100644 --- a/client/ios/Settings.bundle/ru.lproj/Root.strings +++ b/client/ios/Settings.bundle/ru.lproj/Root.strings @@ -1,3 +1,6 @@ "LaunchType" = "Тип запуска приложения"; "Launcher" = "Конфигурация (лаунчер)"; "Game" = "Игра"; + +"AppVersion" = "Версия приложения"; +"BuildVersion" = "Версия сборки"; diff --git a/ios/set_build_version.sh b/ios/set_build_version.sh index 4e37f3279..0b95d1589 100755 --- a/ios/set_build_version.sh +++ b/ios/set_build_version.sh @@ -5,3 +5,6 @@ commitShort=$(git rev-parse --short HEAD) bundleVersion="$today-$commitShort" /usr/libexec/PlistBuddy "$1/Info.plist" -c "Set :CFBundleVersion $bundleVersion" + +/usr/libexec/PlistBuddy "$1/Settings.bundle/Root.plist" -c "Set :PreferenceSpecifiers:0:DefaultValue $MARKETING_VERSION" +/usr/libexec/PlistBuddy "$1/Settings.bundle/Root.plist" -c "Set :PreferenceSpecifiers:1:DefaultValue $bundleVersion" From 4e1b441399320da7429279d5550a768c54c688f8 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 13:25:14 +0300 Subject: [PATCH 58/74] [macOS] set app and bundle version in app bundle's Info.plist generated by CPack --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a30aa67e4..ec3146dfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -581,8 +581,13 @@ elseif(APPLE_MACOS AND NOT ENABLE_MONOLITHIC_INSTALL) # Pre-generated DS_Store use absolute path to background image set(CPACK_DMG_VOLUME_NAME "${CMAKE_PROJECT_NAME}") + include(GetGitRevisionDescription) + get_git_head_revision(GIT_REFSPEC GIT_SHA1) + set(MACOSX_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") set(MACOSX_BUNDLE_BUNDLE_NAME "${CMAKE_PROJECT_NAME}") + set(MACOSX_BUNDLE_BUNDLE_VERSION ${GIT_SHA1}) + set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${APP_SHORT_VERSION}) if(ENABLE_LAUNCHER) set(MACOSX_BUNDLE_EXECUTABLE_NAME "vcmilauncher") else() From 4de0300c769ce9c8b1b2aaba698a32fbc5665f90 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 15:06:50 +0300 Subject: [PATCH 59/74] unlock adventure map UI after closing battle result dialog --- client/CPlayerInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 6003d8105..5d8c0be22 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -930,7 +930,6 @@ void CPlayerInterface::battleEnd(const BattleResult *br) isAutoFightOn = false; cb->unregisterBattleInterface(autofightingAI); autofightingAI.reset(); - adventureInt->quickCombatUnlock(); if (!battleInt) { @@ -938,6 +937,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br) // #1490 - during AI turn when quick combat is on, we need to display the message and wait for user to close it. // Otherwise NewTurn causes freeze. waitWhileDialog(); + adventureInt->quickCombatUnlock(); return; } } @@ -945,6 +945,7 @@ void CPlayerInterface::battleEnd(const BattleResult *br) BATTLE_EVENT_POSSIBLE_RETURN; battleInt->battleFinished(*br); + adventureInt->quickCombatUnlock(); } void CPlayerInterface::battleLogMessage(const std::vector & lines) From c4c2e03b6ecb508e0346b038e7222980c8ee5474 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Fri, 30 Sep 2022 15:06:56 +0300 Subject: [PATCH 60/74] fix typo --- client/battle/CBattleInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index e0e0b6713..6606e6dd8 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -1884,7 +1884,7 @@ void CBattleInterface::blockUI(bool on) bSurrender->block(on || curInt->cb->battleGetSurrenderCost() < 0); // block only if during enemy turn and auto-fight is off - // othervice - crash on accessing non-exisiting active stack + // otherwise - crash on accessing non-exisiting active stack bAutofight->block(!curInt->isAutoFightOn && !activeStack); if (tacticsMode && btactEnd && btactNext) From 86708841f8f630505cb16b98a8d2014ba41417e5 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 09:24:58 +0300 Subject: [PATCH 61/74] code improvement --- lib/mapObjects/CQuest.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/mapObjects/CQuest.h b/lib/mapObjects/CQuest.h index a2cb8b75f..e5302a2bc 100644 --- a/lib/mapObjects/CQuest.h +++ b/lib/mapObjects/CQuest.h @@ -19,7 +19,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CGCreature; -class DLL_LINKAGE CQuest +class DLL_LINKAGE CQuest final { public: enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4, @@ -52,7 +52,6 @@ public: bool isCustomFirst, isCustomNext, isCustomComplete; CQuest(); - virtual ~CQuest(){}; static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army); virtual bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not @@ -161,7 +160,7 @@ protected: class DLL_LINKAGE CGQuestGuard : public CGSeerHut { public: - CGQuestGuard() : CGSeerHut(){}; + CGQuestGuard() = default; void init(CRandomGenerator & rand) override; void completeQuest (const CGHeroInstance * h) const override; @@ -209,7 +208,7 @@ public: class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject { public: - CGBorderGuard() : IQuestObject(){}; + CGBorderGuard() = default; void initObj(CRandomGenerator & rand) override; void onHeroVisit(const CGHeroInstance * h) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; @@ -231,7 +230,7 @@ public: class DLL_LINKAGE CGBorderGate : public CGBorderGuard { public: - CGBorderGate() : CGBorderGuard(){}; + CGBorderGate() = default; void onHeroVisit(const CGHeroInstance * h) const override; bool passableFor(PlayerColor color) const override; From aa217236b37f4bd558341f7331785d37d12f2414 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 09:28:32 +0300 Subject: [PATCH 62/74] check amount of artifacts on hero when checking requirements of a quest that requires artifact(s) fixes case when 2 or more identical artifacts are required --- lib/CArtHandler.cpp | 32 ++++++++++++++++++++++++++------ lib/CArtHandler.h | 2 ++ lib/mapObjects/CQuest.cpp | 19 +++++++++++++++---- lib/mapObjects/CQuest.h | 5 ++++- lib/mapping/MapFormatH3M.cpp | 4 ++-- lib/rmg/TreasurePlacer.cpp | 6 +++--- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 4cf2d9d69..ee57823f9 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1191,18 +1191,27 @@ CArtifactInstance* CArtifactSet::getArt(ArtifactPosition pos, bool excludeLocked ArtifactPosition CArtifactSet::getArtPos(int aid, bool onlyWorn, bool allowLocked) const { + const auto result = getAllArtPositions(aid, onlyWorn, allowLocked, false); + return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0]; +} + +std::vector CArtifactSet::getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const +{ + std::vector result; for(auto i = artifactsWorn.cbegin(); i != artifactsWorn.cend(); i++) if(i->second.artifact->artType->id == aid && (allowLocked || !i->second.locked)) - return i->first; + result.push_back(i->first); if(onlyWorn) - return ArtifactPosition::PRE_FIRST; + return result; + if(!getAll && !result.empty()) + return result; for(int i = 0; i < artifactsInBackpack.size(); i++) if(artifactsInBackpack[i].artifact->artType->id == aid) - return ArtifactPosition(GameConstants::BACKPACK_START + i); + result.push_back(ArtifactPosition(GameConstants::BACKPACK_START + i)); - return ArtifactPosition::PRE_FIRST; + return result; } ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const @@ -1237,8 +1246,19 @@ bool CArtifactSet::hasArt( bool searchBackpackAssemblies, bool allowLocked) const { - return getArtPos(aid, onlyWorn, allowLocked) != ArtifactPosition::PRE_FIRST || - (searchBackpackAssemblies && getHiddenArt(aid)); + return getArtPosCount(aid, onlyWorn, searchBackpackAssemblies, allowLocked) > 0; +} + +unsigned CArtifactSet::getArtPosCount(int aid, bool onlyWorn, bool searchBackpackAssemblies, bool allowLocked) const +{ + const auto allPositions = getAllArtPositions(aid, onlyWorn, allowLocked, true); + if(!allPositions.empty()) + return allPositions.size(); + + if(searchBackpackAssemblies && getHiddenArt(aid)) + return 1; + + return 0; } std::pair diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 9a0d55be0..a933b70a3 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -328,6 +328,7 @@ public: /// (if more than one such artifact lower ID is returned) ArtifactPosition getArtPos(int aid, bool onlyWorn = true, bool allowLocked = true) const; ArtifactPosition getArtPos(const CArtifactInstance *art) const; + std::vector getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const; const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const; /// Search for constituents of assemblies in backpack which do not have an ArtifactPosition const CArtifactInstance *getHiddenArt(int aid) const; @@ -335,6 +336,7 @@ public: /// Checks if hero possess artifact of given id (either in backack or worn) bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const; bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const; + unsigned getArtPosCount(int aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const; virtual ArtBearer::ArtBearer bearerType() const = 0; virtual void putArtifact(ArtifactPosition pos, CArtifactInstance * art) = 0; diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index f22327ed7..04aa4efac 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -112,11 +112,16 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const return true; return false; case MISSION_ART: - for(auto & elem : m5arts) + // if the object was deserialized + if(artifactsRequirements.empty()) + for(auto id : m5arts) + ++artifactsRequirements[id]; + + for(const auto & elem : artifactsRequirements) { - if(h->hasArt(elem, false, true)) - continue; - return false; //if the artifact was not found + // check required amount of artifacts + if(h->getArtPosCount(elem.first, false, true, true) < elem.second) + return false; } return true; case MISSION_ARMY: @@ -417,6 +422,12 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector &compo } } +void CQuest::addArtifactID(ui16 id) +{ + m5arts.push_back(id); + ++artifactsRequirements[id]; +} + void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName) { auto q = handler.enterStruct(fieldName); diff --git a/lib/mapObjects/CQuest.h b/lib/mapObjects/CQuest.h index e5302a2bc..a8fe68b32 100644 --- a/lib/mapObjects/CQuest.h +++ b/lib/mapObjects/CQuest.h @@ -21,6 +21,8 @@ class CGCreature; class DLL_LINKAGE CQuest final { + mutable std::unordered_map artifactsRequirements; // artifact ID -> required count + public: enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4, MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10}; @@ -34,7 +36,7 @@ public: ui32 m13489val; std::vector m2stats; - std::vector m5arts; //artifacts id + std::vector m5arts; // artifact IDs. Add IDs through addArtifactID(), not directly to the field. std::vector m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant std::vector m7resources; //TODO: use resourceset? @@ -60,6 +62,7 @@ public: virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry virtual void completeQuest (const CGHeroInstance * h) const {}; virtual void addReplacements(MetaString &out, const std::string &base) const; + void addArtifactID(ui16 id); bool operator== (const CQuest & quest) const { diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index c67cec4fe..d45d15029 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -1758,7 +1758,7 @@ CGSeerHut * CMapLoaderH3M::readSeerHut() if (artID != 255) { //not none quest - hut->quest->m5arts.push_back (artID); + hut->quest->addArtifactID(artID); hut->quest->missionType = CQuest::MISSION_ART; } else @@ -1887,7 +1887,7 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard) for(int yy = 0; yy < artNumber; ++yy) { int artid = reader.readUInt16(); - guard->quest->m5arts.push_back(artid); + guard->quest->addArtifactID(artid); map->allowedArtifact[artid] = false; //these are unavailable for random generation } break; diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 0af06497c..66bfe792e 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -430,7 +430,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->missionType = CQuest::MISSION_ART; ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand); - obj->quest->m5arts.push_back(artid); + obj->quest->addArtifactID(artid); obj->quest->lastDay = -1; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; @@ -467,7 +467,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->missionType = CQuest::MISSION_ART; ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand); - obj->quest->m5arts.push_back(artid); + obj->quest->addArtifactID(artid); obj->quest->lastDay = -1; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; @@ -490,7 +490,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->missionType = CQuest::MISSION_ART; ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand); - obj->quest->m5arts.push_back(artid); + obj->quest->addArtifactID(artid); obj->quest->lastDay = -1; obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; From c9ae43abe815fe150dc106b09d655433d3a5a165 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 10:33:48 +0300 Subject: [PATCH 63/74] highlight current resolution in the resolution selector in game options --- client/windows/GUIClasses.cpp | 32 +++++++++++++++++++------------- client/windows/GUIClasses.h | 4 ++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 445145bb6..4bce0f2d0 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -438,6 +438,11 @@ static void setBoolSetting(std::string group, std::string field, bool value) fullscreen->Bool() = value; } +static std::string resolutionToString(int w, int h) +{ + return std::to_string(w) + 'x' + std::to_string(h); +} + CSystemOptionsWindow::CSystemOptionsWindow() : CWindowObject(PLAYER_COLORED, "SysOpBck"), onFullscreenChanged(settings.listen["video"]["fullscreen"]) @@ -550,11 +555,8 @@ CSystemOptionsWindow::CSystemOptionsWindow() gameResButton = std::make_shared(Point(28, 275),"buttons/resolution", CButton::tooltip(texts["resolutionButton"]), std::bind(&CSystemOptionsWindow::selectGameRes, this), SDLK_g); - std::string resText; - resText += boost::lexical_cast(settings["video"]["screenRes"]["width"].Float()); - resText += "x"; - resText += boost::lexical_cast(settings["video"]["screenRes"]["height"].Float()); - gameResLabel = std::make_shared(170, 292, FONT_MEDIUM, CENTER, Colors::YELLOW, resText); + const auto & screenRes = settings["video"]["screenRes"]; + gameResLabel = std::make_shared(170, 292, FONT_MEDIUM, CENTER, Colors::YELLOW, resolutionToString(screenRes["width"].Integer(), screenRes["height"].Integer())); } void CSystemOptionsWindow::selectGameRes() @@ -567,6 +569,8 @@ void CSystemOptionsWindow::selectGameRes() SDL_GetDisplayBounds(std::max(0, SDL_GetWindowDisplayIndex(mainWindow)), &displayBounds); #endif + size_t currentResolutionIndex = 0; + size_t i = 0; for(const auto & it : conf.guiOptions) { const auto & resolution = it.first; @@ -575,12 +579,14 @@ void CSystemOptionsWindow::selectGameRes() continue; #endif - std::string resX = boost::lexical_cast(resolution.first); - std::string resY = boost::lexical_cast(resolution.second); - items.push_back(resX + 'x' + resY); + auto resolutionStr = resolutionToString(resolution.first, resolution.second); + if(gameResLabel->text == resolutionStr) + currentResolutionIndex = i; + items.push_back(std::move(resolutionStr)); + ++i; } - GH.pushIntT(items, nullptr, texts["label"].String(), texts["help"].String(), std::bind(&CSystemOptionsWindow::setGameRes, this, _1)); + GH.pushIntT(items, nullptr, texts["label"].String(), texts["help"].String(), std::bind(&CSystemOptionsWindow::setGameRes, this, _1), currentResolutionIndex); } void CSystemOptionsWindow::setGameRes(int index) @@ -2213,10 +2219,10 @@ void CObjectListWindow::CItem::clickLeft(tribool down, bool previousState) parent->changeSelection(index); } -CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback) +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection) : CWindowObject(PLAYER_COLORED, "TPGATE"), onSelect(Callback), - selected(0) + selected(initialSelection) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); items.reserve(_items.size()); @@ -2228,10 +2234,10 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, std::share init(titleWidget_, _title, _descr); } -CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback) +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection) : CWindowObject(PLAYER_COLORED, "TPGATE"), onSelect(Callback), - selected(0) + selected(initialSelection) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); items.reserve(_items.size()); diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 98494cfb6..a56f87d35 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -185,8 +185,8 @@ public: /// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item /// Image can be nullptr ///item names will be taken from map objects - CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback); - CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0); std::shared_ptr genItem(size_t index); void elementSelected();//call callback and close this window From ebeff94130ab3355d263fe0724dc9e6f827b072b Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 11:21:16 +0300 Subject: [PATCH 64/74] inherit CHeroWindow from CStatusbarWindow for proper status bar support --- client/windows/CHeroWindow.cpp | 4 ++-- client/windows/CHeroWindow.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index e5ebb79d2..82f0627aa 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -100,7 +100,7 @@ CHeroSwitcher::CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInsta } CHeroWindow::CHeroWindow(const CGHeroInstance * hero) - : CWindowObject(PLAYER_COLORED, "HeroScr4"), + : CStatusbarWindow(PLAYER_COLORED, "HeroScr4"), heroWArt(this, hero) { auto & heroscrn = CGI->generaltexth->heroscrn; @@ -112,7 +112,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero) name = std::make_shared(190, 38, EFonts::FONT_BIG, EAlignment::CENTER, Colors::YELLOW); title = std::make_shared(190, 65, EFonts::FONT_MEDIUM, EAlignment::CENTER, Colors::WHITE); - statusBar = CGStatusBar::create(7, 559, "ADROLLVR.bmp", 660); + statusbar = CGStatusBar::create(7, 559, "ADROLLVR.bmp", 660); quitButton = std::make_shared(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, SDLK_RETURN); quitButton->assignedKeys.insert(SDLK_ESCAPE); diff --git a/client/windows/CHeroWindow.h b/client/windows/CHeroWindow.h index 685741b23..8c92eb907 100644 --- a/client/windows/CHeroWindow.h +++ b/client/windows/CHeroWindow.h @@ -57,13 +57,12 @@ public: int64_t getTreeVersion() const override; }; -class CHeroWindow : public CWindowObject, public CGarrisonHolder, public CWindowWithArtifacts +class CHeroWindow : public CStatusbarWindow, public CGarrisonHolder, public CWindowWithArtifacts { std::shared_ptr name; std::shared_ptr title; std::shared_ptr banner; - std::shared_ptr statusBar; std::vector> heroList; std::shared_ptr listSelection; From b766edb6afbb023c7f89b5ae40fed9fcc7e24556 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 12:36:48 +0300 Subject: [PATCH 65/74] [iOS] don't nest AI and scripting libs under subdirectories 3rd party signing tools may ignore such directory layout --- CMakeLists.txt | 10 ++++++++-- lib/VCMIDirs.cpp | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c918facbd..6993140dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -402,8 +402,14 @@ else() add_definitions(-DM_LIB_DIR="${CMAKE_INSTALL_PREFIX}/${LIB_DIR}") endif() -set(AI_LIB_DIR "${LIB_DIR}/AI") -set(SCRIPTING_LIB_DIR "${LIB_DIR}/scripting") +# iOS has flat libs directory structure +if(APPLE_IOS) + set(AI_LIB_DIR "${LIB_DIR}") + set(SCRIPTING_LIB_DIR "${LIB_DIR}") +else() + set(AI_LIB_DIR "${LIB_DIR}/AI") + set(SCRIPTING_LIB_DIR "${LIB_DIR}/scripting") +endif() ####################################### # Add subdirectories # diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp index 86749fb17..d8f630da2 100644 --- a/lib/VCMIDirs.cpp +++ b/lib/VCMIDirs.cpp @@ -391,6 +391,7 @@ public: std::vector dataPaths() const override; bfs::path libraryPath() const override; + bfs::path fullLibraryPath(const std::string & desiredFolder, const std::string & baseLibName) const override; bfs::path binaryPath() const override; }; @@ -411,6 +412,12 @@ std::vector VCMIDirsIOS::dataPaths() const return paths; } +bfs::path VCMIDirsIOS::fullLibraryPath(const std::string & desiredFolder, const std::string & baseLibName) const +{ + // iOS has flat libs directory structure + return libraryPath() / libraryName(baseLibName); +} + bfs::path VCMIDirsIOS::libraryPath() const { return {iOS_utils::frameworksPath()}; } bfs::path VCMIDirsIOS::binaryPath() const { return {iOS_utils::bundlePath()}; } #elif defined(VCMI_MAC) From 796845d173e40242b03c59c50b86cae707439d12 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 12:37:23 +0300 Subject: [PATCH 66/74] [iOS] clear focus in launcher only when something has focus --- launcher/mainwindow_moc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launcher/mainwindow_moc.cpp b/launcher/mainwindow_moc.cpp index 04b51018c..95d8be728 100644 --- a/launcher/mainwindow_moc.cpp +++ b/launcher/mainwindow_moc.cpp @@ -92,7 +92,8 @@ MainWindow::MainWindow(QWidget * parent) connect(ui->tabSelectList, &QListWidget::currentRowChanged, [this](int i) { #ifdef Q_OS_IOS - qApp->focusWidget()->clearFocus(); + if(auto widget = qApp->focusWidget()) + widget->clearFocus(); #endif ui->tabListWidget->setCurrentIndex(i); }); From 2434fe3f6fc7beecd19bba1ef6e2e44f1ccea36b Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Tue, 6 Sep 2022 21:14:22 +0300 Subject: [PATCH 67/74] NK: fix AI speed --- AI/Nullkiller/AIGateway.cpp | 4 +- AI/Nullkiller/Analyzers/ObjectClusterizer.cpp | 19 ++- AI/Nullkiller/Behaviors/DefenceBehavior.cpp | 28 +++- AI/Nullkiller/Engine/Nullkiller.cpp | 142 +++++++++------- AI/Nullkiller/Engine/Nullkiller.h | 4 +- AI/Nullkiller/Goals/AbstractGoal.h | 1 + AI/Nullkiller/Goals/CGoal.h | 2 + AI/Nullkiller/Goals/Composition.cpp | 5 + AI/Nullkiller/Goals/Composition.h | 1 + AI/Nullkiller/Goals/ExecuteHeroChain.h | 2 + AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 152 ++++++++++-------- AI/Nullkiller/Pathfinding/AINodeStorage.h | 19 ++- AI/Nullkiller/Pathfinding/Actors.cpp | 3 + server/CVCMIServer.cpp | 32 ++-- 14 files changed, 264 insertions(+), 150 deletions(-) diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 00434ca0c..f657d3ecf 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -766,10 +766,10 @@ void AIGateway::makeTurn() logAi->debug("Making turn thread has been interrupted. We'll end without calling endTurn."); return; } - /*catch (std::exception & e) + catch (std::exception & e) { logAi->debug("Making turn thread has caught an exception: %s", e.what()); - }*/ + } endTurn(); } diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index dacacf393..65301992b 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -120,18 +120,23 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons auto blocker = blockers.front(); + if(isObjectPassable(ai, blocker)) + continue; + if(blocker->ID == Obj::GARRISON - || blocker->ID == Obj::MONSTER - || blocker->ID == Obj::GARRISON2 - || blocker->ID == Obj::BORDERGUARD - || blocker->ID == Obj::BORDER_GATE - || blocker->ID == Obj::SHIPYARD) + || blocker->ID == Obj::GARRISON2) { - if(!isObjectPassable(ai, blocker)) + if(dynamic_cast(blocker)->getArmyStrength() == 0) + continue; + else return blocker; } - if(blocker->ID == Obj::QUEST_GUARD && node->actionIsBlocked) + if(blocker->ID == Obj::MONSTER + || blocker->ID == Obj::BORDERGUARD + || blocker->ID == Obj::BORDER_GATE + || blocker->ID == Obj::SHIPYARD + || (blocker->ID == Obj::QUEST_GUARD && node->actionIsBlocked)) { return blocker; } diff --git a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp index da108da88..41422b0b9 100644 --- a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp +++ b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp @@ -47,14 +47,14 @@ Goals::TGoalVec DefenceBehavior::decompose() const void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInstance * town) const { - logAi->debug("Evaluating defence for %s", town->name); + logAi->trace("Evaluating defence for %s", town->name); auto treatNode = ai->nullkiller->dangerHitMap->getObjectTreat(town); auto treats = { treatNode.fastestDanger, treatNode.maximumDanger }; if(!treatNode.fastestDanger.hero) { - logAi->debug("No treat found for town %s", town->name); + logAi->trace("No treat found for town %s", town->name); return; } @@ -73,7 +73,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta return; } - logAi->debug( + logAi->trace( "Hero %s in garrison of town %s is suposed to defend the town", town->garrisonHero->name, town->name); @@ -85,7 +85,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta if(reinforcement) { - logAi->debug("Town %s can buy defence army %lld", town->name, reinforcement); + logAi->trace("Town %s can buy defence army %lld", town->name, reinforcement); tasks.push_back(Goals::sptr(Goals::BuyArmy(town, reinforcement).setpriority(0.5f))); } @@ -93,7 +93,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta for(auto & treat : treats) { - logAi->debug( + logAi->trace( "Town %s has treat %lld in %s turns, hero: %s", town->name, treat.danger, @@ -104,6 +104,12 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta for(AIPath & path : paths) { + if(town->visitingHero && path.targetHero != town->visitingHero.get()) + continue; + + if(town->visitingHero && path.getHeroStrength() < town->visitingHero->getHeroStrength()) + continue; + if(path.getHeroStrength() > treat.danger) { if((path.turn() <= treat.turn && dayOfWeek + treat.turn < 6 && isSafeToVisit(path.targetHero, path.heroArmy, treat.danger)) @@ -111,11 +117,13 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta || path.turn() < treat.turn - 1 || (path.turn() < treat.turn && treat.turn >= 2)) { - logAi->debug( +#if AI_TRACE_LEVEL >= 1 + logAi->trace( "Hero %s can eliminate danger for town %s using path %s.", path.targetHero->name, town->name, path.toString()); +#endif treatIsUnderControl = true; break; @@ -140,7 +148,9 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta if(cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES) { - logAi->debug("Hero %s can be recruited to defend %s", hero->name, town->name); +#if AI_TRACE_LEVEL >= 1 + logAi->trace("Hero %s can be recruited to defend %s", hero->name, town->name); +#endif tasks.push_back(Goals::sptr(Goals::RecruitHero(town, hero).setpriority(1))); continue; } @@ -174,7 +184,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta if(paths.empty()) { - logAi->debug("No ways to defend town %s", town->name); + logAi->trace("No ways to defend town %s", town->name); continue; } @@ -197,9 +207,11 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta #endif if(path.turn() <= treat.turn - 2) { +#if AI_TRACE_LEVEL >= 1 logAi->trace("Deffer defence of %s by %s because he has enough time to rich the town next trun", town->name, path.targetHero->name); +#endif defferedPaths[path.targetHero].push_back(i); diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index 2ef3cc580..add63e4bd 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -116,9 +116,10 @@ void Nullkiller::resetAiState() playerID = ai->playerID; lockedHeroes.clear(); dangerHitMap->reset(); + useHeroChain = true; } -void Nullkiller::updateAiState(int pass) +void Nullkiller::updateAiState(int pass, bool fast) { boost::this_thread::interruption_point(); @@ -126,39 +127,42 @@ void Nullkiller::updateAiState(int pass) activeHero = nullptr; - memory->removeInvisibleObjects(cb.get()); - - dangerHitMap->updateHitMap(); - - boost::this_thread::interruption_point(); - - heroManager->update(); - logAi->trace("Updating paths"); - - std::map activeHeroes; - - for(auto hero : cb->getHeroesInfo()) + if(!fast) { - if(getHeroLockedReason(hero) == HeroLockedReason::DEFENCE) - continue; + memory->removeInvisibleObjects(cb.get()); - activeHeroes[hero] = heroManager->getHeroRole(hero); + dangerHitMap->updateHitMap(); + + boost::this_thread::interruption_point(); + + heroManager->update(); + logAi->trace("Updating paths"); + + std::map activeHeroes; + + for(auto hero : cb->getHeroesInfo()) + { + if(getHeroLockedReason(hero) == HeroLockedReason::DEFENCE) + continue; + + activeHeroes[hero] = heroManager->getHeroRole(hero); + } + + PathfinderSettings cfg; + cfg.useHeroChain = useHeroChain; + cfg.scoutTurnDistanceLimit = SCOUT_TURN_DISTANCE_LIMIT; + + if(scanDepth != ScanDepth::FULL) + { + cfg.mainTurnDistanceLimit = MAIN_TURN_DISTANCE_LIMIT * ((int)scanDepth + 1); + } + + pathfinder->updatePaths(activeHeroes, cfg); + + objectClusterizer->clusterize(); } - PathfinderSettings cfg; - cfg.useHeroChain = true; - cfg.scoutTurnDistanceLimit = SCOUT_TURN_DISTANCE_LIMIT; - - if(scanDepth != ScanDepth::FULL) - { - cfg.mainTurnDistanceLimit = MAIN_TURN_DISTANCE_LIMIT * ((int)scanDepth + 1); - } - - pathfinder->updatePaths(activeHeroes, cfg); - armyManager->update(); - - objectClusterizer->clusterize(); buildAnalyzer->update(); decomposer->reset(); @@ -213,13 +217,30 @@ void Nullkiller::makeTurn() { updateAiState(i); + Goals::TTask bestTask = taskptr(Goals::Invalid()); + + do + { + Goals::TTaskVec fastTasks = { + choseBestTask(sptr(BuyArmyBehavior()), 1), + choseBestTask(sptr(RecruitHeroBehavior()), 1), + choseBestTask(sptr(BuildingBehavior()), 1) + }; + + bestTask = choseBestTask(fastTasks); + + if(bestTask->priority >= 1) + { + executeTask(bestTask); + updateAiState(i, true); + } + } while(bestTask->priority >= 1); + Goals::TTaskVec bestTasks = { - choseBestTask(sptr(BuyArmyBehavior()), 1), + bestTask, choseBestTask(sptr(CaptureObjectsBehavior()), 1), choseBestTask(sptr(ClusterBehavior()), MAX_DEPTH), - choseBestTask(sptr(RecruitHeroBehavior()), 1), choseBestTask(sptr(DefenceBehavior()), MAX_DEPTH), - choseBestTask(sptr(BuildingBehavior()), 1), choseBestTask(sptr(GatherArmyBehavior()), MAX_DEPTH) }; @@ -228,19 +249,25 @@ void Nullkiller::makeTurn() bestTasks.push_back(choseBestTask(sptr(StartupBehavior()), 1)); } - Goals::TTask bestTask = choseBestTask(bestTasks); + bestTask = choseBestTask(bestTasks); + HeroPtr hero = bestTask->getHero(); + HeroRole heroRole = HeroRole::MAIN; + + if(hero.validAndSet()) + heroRole = heroManager->getHeroRole(hero); + + if(heroRole != HeroRole::MAIN || bestTask->getHeroExchangeCount() <= 1) + useHeroChain = false; + if(bestTask->priority < NEXT_SCAN_MIN_PRIORITY && scanDepth != ScanDepth::FULL) { - HeroRole heroRole = HeroRole::MAIN; - - if(hero.validAndSet()) - heroRole = heroManager->getHeroRole(hero); - if(heroRole == HeroRole::MAIN || bestTask->priority < MIN_PRIORITY) { + useHeroChain = false; + logAi->trace( "Goal %s has too low priority %f so increasing scan depth", bestTask->toString(), @@ -258,26 +285,31 @@ void Nullkiller::makeTurn() return; } - std::string taskDescr = bestTask->toString(); + executeTask(bestTask); + } +} - boost::this_thread::interruption_point(); - logAi->debug("Trying to realize %s (value %2.3f)", taskDescr, bestTask->priority); +void Nullkiller::executeTask(Goals::TTask task) +{ + std::string taskDescr = task->toString(); - try - { - bestTask->accept(ai.get()); - } - catch(goalFulfilledException &) - { - logAi->trace("Task %s completed", bestTask->toString()); - } - catch(std::exception & e) - { - logAi->debug("Failed to realize subgoal of type %s, I will stop.", taskDescr); - logAi->debug("The error message was: %s", e.what()); + boost::this_thread::interruption_point(); + logAi->debug("Trying to realize %s (value %2.3f)", taskDescr, task->priority); - return; - } + try + { + task->accept(ai.get()); + } + catch(goalFulfilledException &) + { + logAi->trace("Task %s completed", task->toString()); + } + catch(std::exception & e) + { + logAi->debug("Failed to realize subgoal of type %s, I will stop.", taskDescr); + logAi->debug("The error message was: %s", e.what()); + + throw; } } diff --git a/AI/Nullkiller/Engine/Nullkiller.h b/AI/Nullkiller/Engine/Nullkiller.h index 6f95ba17f..9bb3304c0 100644 --- a/AI/Nullkiller/Engine/Nullkiller.h +++ b/AI/Nullkiller/Engine/Nullkiller.h @@ -51,6 +51,7 @@ private: std::map lockedHeroes; ScanDepth scanDepth; TResources lockedResources; + bool useHeroChain; public: std::unique_ptr dangerHitMap; @@ -86,7 +87,8 @@ public: private: void resetAiState(); - void updateAiState(int pass); + void updateAiState(int pass, bool fast = false); Goals::TTask choseBestTask(Goals::TSubgoal behavior, int decompositionMaxDepth) const; Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const; + void executeTask(Goals::TTask task); }; diff --git a/AI/Nullkiller/Goals/AbstractGoal.h b/AI/Nullkiller/Goals/AbstractGoal.h index 64bcd6b8d..7407a5fc4 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.h +++ b/AI/Nullkiller/Goals/AbstractGoal.h @@ -162,6 +162,7 @@ namespace Goals virtual std::string toString() const = 0; virtual HeroPtr getHero() const = 0; virtual ~ITask() {} + virtual int getHeroExchangeCount() const = 0; }; } diff --git a/AI/Nullkiller/Goals/CGoal.h b/AI/Nullkiller/Goals/CGoal.h index 5e0d341c8..e5f9679c8 100644 --- a/AI/Nullkiller/Goals/CGoal.h +++ b/AI/Nullkiller/Goals/CGoal.h @@ -90,6 +90,8 @@ namespace Goals virtual bool isElementar() const override { return true; } virtual HeroPtr getHero() const override { return AbstractGoal::hero; } + + virtual int getHeroExchangeCount() const override { return 0; } }; class DLL_EXPORT Invalid : public ElementarGoal diff --git a/AI/Nullkiller/Goals/Composition.cpp b/AI/Nullkiller/Goals/Composition.cpp index 61151f388..4adafdfe0 100644 --- a/AI/Nullkiller/Goals/Composition.cpp +++ b/AI/Nullkiller/Goals/Composition.cpp @@ -72,4 +72,9 @@ Composition & Composition::addNext(TSubgoal goal) bool Composition::isElementar() const { return subtasks.back()->isElementar(); +} + +int Composition::getHeroExchangeCount() const +{ + return isElementar() ? taskptr(*subtasks.back())->getHeroExchangeCount() : 0; } \ No newline at end of file diff --git a/AI/Nullkiller/Goals/Composition.h b/AI/Nullkiller/Goals/Composition.h index 7906b4841..ce8b66313 100644 --- a/AI/Nullkiller/Goals/Composition.h +++ b/AI/Nullkiller/Goals/Composition.h @@ -36,5 +36,6 @@ namespace Goals Composition & addNext(TSubgoal goal); virtual TGoalVec decompose() const override; virtual bool isElementar() const override; + virtual int getHeroExchangeCount() const override; }; } diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.h b/AI/Nullkiller/Goals/ExecuteHeroChain.h index 8e3b4085b..7aaf20ad3 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.h +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.h @@ -31,6 +31,8 @@ namespace Goals virtual bool operator==(const ExecuteHeroChain & other) const override; const AIPath & getPath() const { return chainPath; } + virtual int getHeroExchangeCount() const override { return chainPath.exchangeCount; } + private: bool moveHeroToTile(const CGHeroInstance * hero, const int3 & tile); }; diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 44159791c..b62e047cb 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -23,23 +23,17 @@ std::shared_ptr> AISharedStorage::shared; std::set commitedTiles; std::set commitedTilesInitial; -#ifdef ENVIRONMENT64 -const int BUCKET_COUNT = 11; -#else -const int BUCKET_COUNT = 7; -#endif // ENVIRONMENT64 const uint64_t FirstActorMask = 1; -const int BUCKET_SIZE = GameConstants::MAX_HEROES_PER_PLAYER; -const int NUM_CHAINS = BUCKET_COUNT * BUCKET_SIZE; const uint64_t MIN_ARMY_STRENGTH_FOR_CHAIN = 5000; const uint64_t MIN_ARMY_STRENGTH_FOR_NEXT_ACTOR = 1000; +const uint64_t CHAIN_MAX_DEPTH = 4; AISharedStorage::AISharedStorage(int3 sizes) { if(!shared){ shared.reset(new boost::multi_array( - boost::extents[EPathfindingLayer::NUM_LAYERS][sizes.z][sizes.x][sizes.y][NUM_CHAINS])); + boost::extents[EPathfindingLayer::NUM_LAYERS][sizes.z][sizes.x][sizes.y][AIPathfinding::NUM_CHAINS])); } nodes = shared; @@ -139,16 +133,16 @@ boost::optional AINodeStorage::getOrCreateNode( const EPathfindingLayer layer, const ChainActor * actor) { - int bucketIndex = ((uintptr_t)actor) % BUCKET_COUNT; - int bucketOffset = bucketIndex * BUCKET_SIZE; - auto chains = nodes.get(pos, layer); //FIXME: chain was the innermost layer + int bucketIndex = ((uintptr_t)actor) % AIPathfinding::BUCKET_COUNT; + int bucketOffset = bucketIndex * AIPathfinding::BUCKET_SIZE; + auto chains = nodes.get(pos, layer); if(chains[0].blocked()) { return boost::none; } - for(auto i = BUCKET_SIZE - 1; i >= 0; i--) + for(auto i = AIPathfinding::BUCKET_SIZE - 1; i >= 0; i--) { AIPathNode & node = chains[i + bucketOffset]; @@ -171,8 +165,9 @@ boost::optional AINodeStorage::getOrCreateNode( std::vector AINodeStorage::getInitialNodes() { if(heroChainPass) -{ - calculateTownPortalTeleportations(heroChain); + { + if(heroChainTurn == 0) + calculateTownPortalTeleportations(heroChain); return heroChain; } @@ -207,7 +202,8 @@ std::vector AINodeStorage::getInitialNodes() } } - calculateTownPortalTeleportations(initialNodes); + if(heroChainTurn == 0) + calculateTownPortalTeleportations(initialNodes); return initialNodes; } @@ -406,8 +402,8 @@ public: AINodeStorage & storage, AISharedStorage & nodes, const std::vector & tiles, uint64_t chainMask, int heroChainTurn) :existingChains(), newChains(), delayedWork(), nodes(nodes), storage(storage), chainMask(chainMask), heroChainTurn(heroChainTurn), heroChain(), tiles(tiles) { - existingChains.reserve(NUM_CHAINS); - newChains.reserve(NUM_CHAINS); + existingChains.reserve(AIPathfinding::NUM_CHAINS); + newChains.reserve(AIPathfinding::NUM_CHAINS); } void execute(const blocked_range& r) @@ -623,6 +619,9 @@ void HeroChainCalculationTask::calculateHeroChain( if((node->actor->chainMask & chainMask) == 0 && (srcNode->actor->chainMask & chainMask) == 0) continue; + if(node->actor->actorExchangeCount + srcNode->actor->actorExchangeCount > CHAIN_MAX_DEPTH) + continue; + if(node->action == CGPathNode::ENodeAction::BATTLE || node->action == CGPathNode::ENodeAction::TELEPORT_BATTLE || node->action == CGPathNode::ENodeAction::TELEPORT_NORMAL @@ -994,8 +993,6 @@ struct TowmPortalFinder CGPathNode * getBestInitialNodeForTownPortal(const CGTownInstance * targetTown) { - CGPathNode * bestNode = nullptr; - for(CGPathNode * node : initialNodes) { auto aiNode = nodeStorage->getAINode(node); @@ -1018,11 +1015,10 @@ struct TowmPortalFinder continue; } - if(!bestNode || bestNode->getCost() > node->getCost()) - bestNode = node; + return node; } - return bestNode; + return nullptr; } boost::optional createTownPortalNode(const CGTownInstance * targetTown) @@ -1060,6 +1056,55 @@ struct TowmPortalFinder } }; +template +void AINodeStorage::calculateTownPortal( + const ChainActor * actor, + const std::map & maskMap, + const std::vector & initialNodes, + TVector & output) +{ + auto towns = cb->getTownsInfo(false); + + vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool + { + return cb->getPlayerRelations(actor->hero->tempOwner, t->tempOwner) == PlayerRelations::ENEMIES; + }); + + if(!towns.size()) + { + return; // no towns no need to run loop further + } + + TowmPortalFinder townPortalFinder(actor, initialNodes, towns, this); + + if(townPortalFinder.actorCanCastTownPortal()) + { + for(const CGTownInstance * targetTown : towns) + { + // TODO: allow to hide visiting hero in garrison + if(targetTown->visitingHero) + { + auto basicMask = maskMap.at(targetTown->visitingHero.get()); + bool heroIsInChain = (actor->chainMask & basicMask) != 0; + bool sameActorInTown = actor->chainMask == basicMask; + + if(sameActorInTown || !heroIsInChain) + continue; + } + + auto nodeOptional = townPortalFinder.createTownPortalNode(targetTown); + + if(nodeOptional) + { +#if PATHFINDER_TRACE_LEVEL >= 1 + logAi->trace("Adding town portal node at %s", targetTown->name); +#endif + output.push_back(nodeOptional.get()); + } + } + } +} + void AINodeStorage::calculateTownPortalTeleportations(std::vector & initialNodes) { std::set actorsOfInitial; @@ -1068,7 +1113,8 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector { auto aiNode = getAINode(node); - actorsOfInitial.insert(aiNode->actor->baseActor); + if(aiNode->actor->hero) + actorsOfInitial.insert(aiNode->actor->baseActor); } std::map maskMap; @@ -1079,50 +1125,28 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector maskMap[basicActor->hero] = basicActor->chainMask; } - for(const ChainActor * actor : actorsOfInitial) + boost::sort(initialNodes, NodeComparer()); + + std::vector actorsVector(actorsOfInitial.begin(), actorsOfInitial.end()); + tbb::concurrent_vector output; + + if(actorsVector.size() * initialNodes.size() > 1000) { - if(!actor->hero) - continue; - - auto towns = cb->getTownsInfo(false); - - vstd::erase_if(towns, [&](const CGTownInstance * t) -> bool - { - return cb->getPlayerRelations(actor->hero->tempOwner, t->tempOwner) == PlayerRelations::ENEMIES; - }); - - if(!towns.size()) - { - return; // no towns no need to run loop further - } - - TowmPortalFinder townPortalFinder(actor, initialNodes, towns, this); - - if(townPortalFinder.actorCanCastTownPortal()) - { - for(const CGTownInstance * targetTown : towns) + parallel_for(blocked_range(0, actorsVector.size()), [&](const blocked_range & r) { - // TODO: allow to hide visiting hero in garrison - if(targetTown->visitingHero) + for(int i = r.begin(); i != r.end(); i++) { - auto basicMask = maskMap[targetTown->visitingHero.get()]; - bool heroIsInChain = (actor->chainMask & basicMask) != 0; - bool sameActorInTown = actor->chainMask == basicMask; - - if(sameActorInTown || !heroIsInChain) - continue; + calculateTownPortal(actorsVector[i], maskMap, initialNodes, output); } + }); - auto nodeOptional = townPortalFinder.createTownPortalNode(targetTown); - - if(nodeOptional) - { -#if PATHFINDER_TRACE_LEVEL >= 1 - logAi->trace("Adding town portal node at %s", targetTown->name); -#endif - initialNodes.push_back(nodeOptional.get()); - } - } + std::copy(output.begin(), output.end(), std::back_inserter(initialNodes)); + } + else + { + for(auto actor : actorsVector) + { + calculateTownPortal(actor, maskMap, initialNodes, initialNodes); } } } @@ -1206,7 +1230,7 @@ bool AINodeStorage::hasBetterChain( continue; } -#if AI_TRACE_LEVEL >= 2 +#if PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Block ineficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i", source->coord.toString(), @@ -1244,7 +1268,7 @@ std::vector AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand) { std::vector paths; - paths.reserve(NUM_CHAINS / 4); + paths.reserve(AIPathfinding::NUM_CHAINS / 4); auto chains = nodes.get(pos, isOnLand ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL); diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.h b/AI/Nullkiller/Pathfinding/AINodeStorage.h index bd97f88b6..075a90d32 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.h +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.h @@ -25,10 +25,16 @@ namespace AIPathfinding { - const int BUCKET_COUNT = 11; - const int BUCKET_SIZE = GameConstants::MAX_HEROES_PER_PLAYER; +#ifdef ENVIRONMENT64 + const int BUCKET_COUNT = 7; +#else + const int BUCKET_COUNT = 5; +#endif // ENVIRONMENT64 + + const int BUCKET_SIZE = 5; const int NUM_CHAINS = BUCKET_COUNT * BUCKET_SIZE; const int THREAD_COUNT = 8; + const int CHAIN_MAX_DEPTH = 4; } struct AIPathNode : public CGPathNode @@ -239,7 +245,14 @@ public: return ((uintptr_t)actor * 395) % AIPathfinding::BUCKET_COUNT; } - void calculateTownPortalTeleportations(std::vector & neighbours); void fillChainInfo(const AIPathNode * node, AIPath & path, int parentIndex) const; + +private: + template + void calculateTownPortal( + const ChainActor * actor, + const std::map & maskMap, + const std::vector & initialNodes, + TVector & output); }; diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index d4905d462..b5f730a12 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -275,6 +275,9 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other) if(!differentMasks) return result; + if(actor->allowSpellCast || other->allowSpellCast) + return result; + TResources resources = ai->cb->getResourceAmount(); if(!resources.canAfford(actor->armyCost + other->armyCost)) diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 742ff5194..12f972cd0 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -315,11 +315,28 @@ void CVCMIServer::threadHandleClient(std::shared_ptr c) setThreadName("CVCMIServer::handleConnection"); c->enterLobbyConnectionMode(); +#ifndef _MSC_VER try { +#endif while(c->connected) { - CPack * pack = c->retrievePack(); + CPack * pack; + + try + { + pack = c->retrievePack(); + } + catch(boost::system::system_error & e) + { + logNetwork->error("Network error receiving a pack. Connection %s dies. What happened: %s", c->toString(), e.what()); + + if(state != EServerState::LOBBY) + gh->handleClientDisconnection(c); + + break; + } + if(auto lobbyPack = dynamic_ptr_cast(pack)) { handleReceivedPack(std::unique_ptr(lobbyPack)); @@ -329,14 +346,8 @@ void CVCMIServer::threadHandleClient(std::shared_ptr c) gh->handleReceivedPack(serverPack); } } - } - catch(boost::system::system_error & e) - { - (void)e; - if(state != EServerState::LOBBY) - gh->handleClientDisconnection(c); - } - /* +#ifndef _MSC_VER + } catch(const std::exception & e) { (void)e; @@ -348,7 +359,8 @@ void CVCMIServer::threadHandleClient(std::shared_ptr c) state = EServerState::SHUTDOWN; handleException(); throw; - }*/ + } +#endif boost::unique_lock queueLock(mx); // if(state != ENDING_AND_STARTING_GAME) From acfdbe87feeeb11993936d71eb5ed15964b29a53 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 16:01:02 +0300 Subject: [PATCH 68/74] remove duplicate entry --- lib/mapObjects/CObjectClassesHandler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mapObjects/CObjectClassesHandler.cpp b/lib/mapObjects/CObjectClassesHandler.cpp index bc0736774..4f8326725 100644 --- a/lib/mapObjects/CObjectClassesHandler.cpp +++ b/lib/mapObjects/CObjectClassesHandler.cpp @@ -58,7 +58,6 @@ CObjectClassesHandler::CObjectClassesHandler() SET_HANDLER("randomDwelling", CGDwelling); SET_HANDLER("generic", CGObjectInstance); - SET_HANDLER("market", CGMarket); SET_HANDLER("cartographer", CCartographer); SET_HANDLER("artifact", CGArtifact); SET_HANDLER("blackMarket", CGBlackMarket); From b26db479d78d69acc915ed2eaf2a25bc1eca1940 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 16:01:47 +0300 Subject: [PATCH 69/74] don't add Necromancy to Witch Hut on random maps --- lib/mapObjects/MiscObjects.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index cd9b5a620..bb51fadb7 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -1452,8 +1452,10 @@ void CGWitchHut::initObj(CRandomGenerator & rand) { if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file { + // Necromancy can't be learned on random maps for(int i = 0; i < VLC->skillh->size(); i++) - allowedAbilities.push_back(i); + if(VLC->skillh->getByIndex(i)->getId() != SecondarySkill::NECROMANCY) + allowedAbilities.push_back(i); } ability = *RandomGeneratorUtil::nextItem(allowedAbilities, rand); } From 8f51a8756b360362281696f672cd519cc00a0b17 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 1 Oct 2022 17:41:12 +0300 Subject: [PATCH 70/74] restore last used address in Multiplayer join dialog in all other cases (when machine is host) hardcoded localhost address is displayed --- client/CServerHandler.cpp | 20 +++++++++++++++----- client/CServerHandler.h | 2 ++ client/mainmenu/CMainMenu.cpp | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index e8605fb39..91f8c6472 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -59,6 +59,8 @@ template class CApplyOnLobby; +const std::string CServerHandler::localhostAddress{"127.0.0.1"}; + #ifdef VCMI_ANDROID extern std::atomic_bool androidTestServerReadyFlag; #endif @@ -171,7 +173,7 @@ void CServerHandler::startLocalServerAndConnect() auto errorMsg = CGI->generaltexth->localizedTexts["server"]["errors"]["existingProcess"].String(); try { - CConnection testConnection(settings["server"]["server"].String(), getDefaultPort(), NAME, uuid); + CConnection testConnection(localhostAddress, getDefaultPort(), NAME, uuid); logNetwork->error("Port is busy, check if another instance of vcmiserver is working"); CInfoWindow::showInfoDialog(errorMsg, {}); return; @@ -243,7 +245,7 @@ void CServerHandler::startLocalServerAndConnect() #else const ui16 port = 0; #endif - justConnectToServer(settings["server"]["server"].String(), port); + justConnectToServer(localhostAddress, port); logNetwork->trace("\tConnecting to the server: %d ms", th->getDiff()); } @@ -269,9 +271,17 @@ void CServerHandler::justConnectToServer(const std::string & addr, const ui16 po } if(state == EClientState::CONNECTION_CANCELLED) + { logNetwork->info("Connection aborted by player!"); - else - c->handler = std::make_shared(&CServerHandler::threadHandleConnection, this); + return; + } + + c->handler = std::make_shared(&CServerHandler::threadHandleConnection, this); + + if(addr.empty() || addr == localhostAddress) + return; + Settings serverAddress = settings.write["server"]["server"]; + serverAddress->String() = addr; } void CServerHandler::applyPacksOnLobbyScreen() @@ -633,7 +643,7 @@ void CServerHandler::debugStartTest(std::string filename, bool save) screenType = ESelectionScreen::newGame; } if(settings["session"]["donotstartserver"].Bool()) - justConnectToServer("127.0.0.1", 3030); + justConnectToServer(localhostAddress, 3030); else startLocalServerAndConnect(); diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 4650bf4d9..58b122693 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -106,6 +106,8 @@ public: CondSh campaignServerRestartLock; + static const std::string localhostAddress; + CServerHandler(); void resetStateForLobby(const StartInfo::EMode mode, const std::vector * names = nullptr); diff --git a/client/mainmenu/CMainMenu.cpp b/client/mainmenu/CMainMenu.cpp index da9171f7a..83de1e91d 100644 --- a/client/mainmenu/CMainMenu.cpp +++ b/client/mainmenu/CMainMenu.cpp @@ -481,7 +481,7 @@ CSimpleJoinScreen::CSimpleJoinScreen(bool host) inputAddress->giveFocus(); } - inputAddress->setText(settings["server"]["server"].String(), true); + inputAddress->setText(host ? CServerHandler::localhostAddress : settings["server"]["server"].String(), true); inputPort->setText(CServerHandler::getDefaultPortStr(), true); buttonCancel = std::make_shared(Point(142, 142), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CSimpleJoinScreen::leaveScreen, this), SDLK_ESCAPE); From 8f599ed04338112f73c5ee35836571a3a0a4d632 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Sun, 2 Oct 2022 14:23:03 +0300 Subject: [PATCH 71/74] NKAI: android fixes --- cmake_modules/VCMI_lib.cmake | 55 +++++++++++++++++++----------------- lib/CGameInterface.cpp | 8 +++++- server/CVCMIServer.cpp | 6 +++- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index a3e8d48da..9ba3074c2 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -1,5 +1,8 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) - set(MAIN_LIB_DIR "${CMAKE_SOURCE_DIR}/lib") + if(NOT DEFINED MAIN_LIB_DIR) + set(MAIN_LIB_DIR "${CMAKE_SOURCE_DIR}/lib") + endif() + set(lib_SRCS ${MAIN_LIB_DIR}/StdInc.cpp @@ -203,33 +206,33 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) endif() set(lib_HEADERS - ${CMAKE_SOURCE_DIR}/include/vstd/CLoggerBase.h - ${CMAKE_SOURCE_DIR}/Global.h + ${MAIN_LIB_DIR}/../include/vstd/CLoggerBase.h + ${MAIN_LIB_DIR}/../Global.h ${MAIN_LIB_DIR}/StdInc.h - ${CMAKE_SOURCE_DIR}/include/vstd/ContainerUtils.h - ${CMAKE_SOURCE_DIR}/include/vstd/RNG.h - ${CMAKE_SOURCE_DIR}/include/vstd/StringUtils.h + ${MAIN_LIB_DIR}/../include/vstd/ContainerUtils.h + ${MAIN_LIB_DIR}/../include/vstd/RNG.h + ${MAIN_LIB_DIR}/../include/vstd/StringUtils.h - ${CMAKE_SOURCE_DIR}/include/vcmi/events/ApplyDamage.h - ${CMAKE_SOURCE_DIR}/include/vcmi/events/Event.h - ${CMAKE_SOURCE_DIR}/include/vcmi/events/EventBus.h - ${CMAKE_SOURCE_DIR}/include/vcmi/events/SubscriptionRegistry.h + ${MAIN_LIB_DIR}/../include/vcmi/events/ApplyDamage.h + ${MAIN_LIB_DIR}/../include/vcmi/events/Event.h + ${MAIN_LIB_DIR}/../include/vcmi/events/EventBus.h + ${MAIN_LIB_DIR}/../include/vcmi/events/SubscriptionRegistry.h - ${CMAKE_SOURCE_DIR}/include/vcmi/scripting/Service.h + ${MAIN_LIB_DIR}/../include/vcmi/scripting/Service.h - ${CMAKE_SOURCE_DIR}/include/vcmi/spells/Caster.h - ${CMAKE_SOURCE_DIR}/include/vcmi/spells/Magic.h - ${CMAKE_SOURCE_DIR}/include/vcmi/spells/Service.h - ${CMAKE_SOURCE_DIR}/include/vcmi/spells/Spell.h + ${MAIN_LIB_DIR}/../include/vcmi/spells/Caster.h + ${MAIN_LIB_DIR}/../include/vcmi/spells/Magic.h + ${MAIN_LIB_DIR}/../include/vcmi/spells/Service.h + ${MAIN_LIB_DIR}/../include/vcmi/spells/Spell.h - ${CMAKE_SOURCE_DIR}/include/vcmi/Artifact.h - ${CMAKE_SOURCE_DIR}/include/vcmi/ArtifactService.h - ${CMAKE_SOURCE_DIR}/include/vcmi/Creature.h - ${CMAKE_SOURCE_DIR}/include/vcmi/CreatureService.h - ${CMAKE_SOURCE_DIR}/include/vcmi/Entity.h - ${CMAKE_SOURCE_DIR}/include/vcmi/Environment.h - ${CMAKE_SOURCE_DIR}/include/vcmi/Services.h + ${MAIN_LIB_DIR}/../include/vcmi/Artifact.h + ${MAIN_LIB_DIR}/../include/vcmi/ArtifactService.h + ${MAIN_LIB_DIR}/../include/vcmi/Creature.h + ${MAIN_LIB_DIR}/../include/vcmi/CreatureService.h + ${MAIN_LIB_DIR}/../include/vcmi/Entity.h + ${MAIN_LIB_DIR}/../include/vcmi/Environment.h + ${MAIN_LIB_DIR}/../include/vcmi/Services.h ${MAIN_LIB_DIR}/abilities/Ability.h @@ -457,8 +460,8 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC ${CMAKE_SOURCE_DIR} - PUBLIC ${CMAKE_SOURCE_DIR}/include + PUBLIC ${MAIN_LIB_DIR}/.. + PUBLIC ${MAIN_LIB_DIR}/../include PUBLIC ${MAIN_LIB_DIR} PRIVATE ${SDL2_INCLUDE_DIR} ) @@ -484,8 +487,8 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/config ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Mods ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods + COMMAND ${CMAKE_COMMAND} -E copy_directory ${MAIN_LIB_DIR}/../config ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/config + COMMAND ${CMAKE_COMMAND} -E copy_directory ${MAIN_LIB_DIR}/../Mods ${CMAKE_BINARY_DIR}/bin/${CMAKE_CFG_INTDIR}/Mods ) endif() diff --git a/lib/CGameInterface.cpp b/lib/CGameInterface.cpp index 5abf49072..f47fa1bdf 100644 --- a/lib/CGameInterface.cpp +++ b/lib/CGameInterface.cpp @@ -25,6 +25,7 @@ #ifdef VCMI_ANDROID #include "AI/VCAI/VCAI.h" +#include "AI/Nullkiller/AIGateway.h" #include "AI/BattleAI/BattleAI.h" #endif @@ -96,7 +97,12 @@ std::shared_ptr createAny(const boost::filesystem::path & libpath, const s template<> std::shared_ptr createAny(const boost::filesystem::path & libpath, const std::string & methodName) { - return std::make_shared(); + if(libpath.stem() == "libNullkiller") { + return std::make_shared(); + } + else{ + return std::make_shared(); + } } template<> diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index 12f972cd0..78bfb692b 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -171,7 +171,10 @@ void CVCMIServer::run() startAsyncAccept(); -#if !defined(VCMI_ANDROID) && !defined(VCMI_IOS) +#if defined(VCMI_ANDROID) + CAndroidVMHelper vmHelper; + vmHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "onServerReady"); +#elif !defined(VCMI_IOS) if(shm) { shm->sr->setToReadyAndNotify(port); @@ -1011,6 +1014,7 @@ int main(int argc, char * argv[]) void CVCMIServer::create() { const char * foo[1] = {"android-server"}; + main(1, const_cast(foo)); } #elif defined(SINGLE_PROCESS_APP) From d280eca2416b17bdefd77ddc89daf8e37b7b47c7 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Mon, 3 Oct 2022 13:46:55 +0200 Subject: [PATCH 72/74] vcmibuilder: remove references to deprecated (and disabled) core.zip download Closes: #1038 --- vcmibuilder | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/vcmibuilder b/vcmibuilder index cdd1b337f..919878814 100755 --- a/vcmibuilder +++ b/vcmibuilder @@ -29,7 +29,6 @@ do --data) data_dir=$2 ; shift 2 ;; --dest) dest_dir=$2 ; shift 2 ;; --convertMP3) useffmpeg=true; shift 1 ;; -# --download) download=true ; shift 1 ;; --validate) validate=true ; shift 1 ;; *) print_help=true ; shift 1 ;; esac @@ -53,9 +52,6 @@ then echo " --convertMP3 " "Convert all mp3 files into ogg/vorbis" echo " " "Requires ffmpeg or avconv" echo -# echo " --download " "Automatically download optional package using wget" -# echo " " "Requires wget and Internet connection" -# echo echo " --dest DIRECTORY " "Path where resulting data will be placed. Default is ~/.local/share/vcmi" echo echo " --validate " "Run basic validness checks" @@ -137,11 +133,6 @@ then test_utility "unshield" "-V" fi -if [[ -n "$download" ]] -then - test_utility "unzip" -fi - if [[ -z "$gog_file" ]] && [[ -z "$data_dir" ]] && ( [[ -z "$cd1_dir" ]] || [[ -z "$cd2_dir" ]] ) then warning "Warning: Selected options will not create complete Heroes 3 data!" @@ -236,18 +227,6 @@ then cp -r "$data_dir"/[Mm][Pp]3 "$dest_dir" fi -if [[ -n "$download" ]] -then - wget "http://download.vcmi.eu/core.zip" -O "$temp_dir"/core.zip || fail "Error: failed to download VCMI archive!" "rm -f core.zip" - vcmi_archive="$temp_dir"/core.zip -fi - -if [[ -n "$vcmi_archive" ]] -then - echo "decompressing $vcmi_archive" - unzip -qo "$vcmi_archive" -d "$dest_dir" || fail "Error: failed to extract VCMI archive!" -fi - if [[ -n "$useffmpeg" ]] then # now when all music files were installed convert them to ogg From 52371a4d3e79cb0e077c754ecf1de5e209fa2acb Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Mon, 3 Oct 2022 15:45:33 +0300 Subject: [PATCH 73/74] allow healing ability before first turn attempt of each round --- server/CGameHandler.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 800ed5ed0..f227c8ec7 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5200,19 +5200,6 @@ void CGameHandler::stackTurnTrigger(const CStack *st) sendAndApply(&ssp); } } - //regeneration - if (st->hasBonusOfType(Bonus::HP_REGENERATION)) - { - bte.effect = Bonus::HP_REGENERATION; - bte.val = std::min((int)(st->MaxHealth() - st->getFirstHPleft()), st->valOfBonuses(Bonus::HP_REGENERATION)); - } - if (st->hasBonusOfType(Bonus::FULL_HP_REGENERATION)) - { - bte.effect = Bonus::HP_REGENERATION; - bte.val = st->MaxHealth() - st->getFirstHPleft(); - } - if (bte.val) //anything to heal - sendAndApply(&bte); if (st->hasBonusOfType(Bonus::POISON)) { @@ -6549,8 +6536,28 @@ void CGameHandler::runBattle() if(!q.front().empty()) { auto next = q.front().front(); + const auto stack = dynamic_cast(next); + + // regeneration takes place before everything else but only during first turn attempt in each round + // also works under blind and similar effects + if(stack && stack->alive() && !stack->waiting) + { + BattleTriggerEffect bte; + bte.stackID = stack->ID; + bte.effect = Bonus::HP_REGENERATION; + + const int32_t lostHealth = stack->MaxHealth() - stack->getFirstHPleft(); + if(stack->hasBonusOfType(Bonus::FULL_HP_REGENERATION)) + bte.val = lostHealth; + else if(stack->hasBonusOfType(Bonus::HP_REGENERATION)) + bte.val = std::min(lostHealth, stack->valOfBonuses(Bonus::HP_REGENERATION)); + + if(bte.val) // anything to heal + sendAndApply(&bte); + } + if(next->willMove()) - return dynamic_cast(next); + return stack; } } From eeea01d77885d5186a82921fb85cb006b0a180b5 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Mon, 26 Sep 2022 21:01:07 +0300 Subject: [PATCH 74/74] NKAI: namespace --- AI/Nullkiller/AIGateway.cpp | 5 +- AI/Nullkiller/AIGateway.h | 9 +- AI/Nullkiller/AIUtility.cpp | 5 + AI/Nullkiller/AIUtility.h | 49 +---- AI/Nullkiller/Analyzers/ArmyManager.cpp | 4 + AI/Nullkiller/Analyzers/ArmyManager.h | 5 + AI/Nullkiller/Analyzers/BuildAnalyzer.cpp | 5 + AI/Nullkiller/Analyzers/BuildAnalyzer.h | 5 + .../Analyzers/DangerHitMapAnalyzer.cpp | 5 + .../Analyzers/DangerHitMapAnalyzer.h | 5 + AI/Nullkiller/Analyzers/HeroManager.cpp | 5 + AI/Nullkiller/Analyzers/HeroManager.h | 5 + AI/Nullkiller/Analyzers/ObjectClusterizer.cpp | 23 ++- AI/Nullkiller/Analyzers/ObjectClusterizer.h | 5 + AI/Nullkiller/Behaviors/Behavior.cpp | 0 AI/Nullkiller/Behaviors/Behavior.h | 19 -- AI/Nullkiller/Behaviors/BuildingBehavior.cpp | 5 + AI/Nullkiller/Behaviors/BuildingBehavior.h | 3 + AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp | 5 + AI/Nullkiller/Behaviors/BuyArmyBehavior.h | 4 + .../Behaviors/CaptureObjectsBehavior.cpp | 18 +- .../Behaviors/CaptureObjectsBehavior.h | 4 + AI/Nullkiller/Behaviors/ClusterBehavior.cpp | 13 +- AI/Nullkiller/Behaviors/ClusterBehavior.h | 7 +- AI/Nullkiller/Behaviors/DefenceBehavior.cpp | 23 ++- AI/Nullkiller/Behaviors/DefenceBehavior.h | 4 + .../Behaviors/GatherArmyBehavior.cpp | 41 ++-- AI/Nullkiller/Behaviors/GatherArmyBehavior.h | 4 + .../Behaviors/RecruitHeroBehavior.cpp | 5 + AI/Nullkiller/Behaviors/RecruitHeroBehavior.h | 6 +- AI/Nullkiller/Behaviors/StartupBehavior.cpp | 5 + AI/Nullkiller/Behaviors/StartupBehavior.h | 4 + AI/Nullkiller/Engine/AIMemory.cpp | 7 +- AI/Nullkiller/Engine/AIMemory.h | 5 + AI/Nullkiller/Engine/DeepDecomposer.cpp | 21 +- AI/Nullkiller/Engine/DeepDecomposer.h | 7 +- AI/Nullkiller/Engine/FuzzyEngines.cpp | 5 + AI/Nullkiller/Engine/FuzzyEngines.h | 5 + AI/Nullkiller/Engine/FuzzyHelper.cpp | 9 +- AI/Nullkiller/Engine/FuzzyHelper.h | 7 +- AI/Nullkiller/Engine/Nullkiller.cpp | 11 +- AI/Nullkiller/Engine/Nullkiller.h | 5 + AI/Nullkiller/Engine/PriorityEvaluator.cpp | 7 +- AI/Nullkiller/Engine/PriorityEvaluator.h | 5 + AI/Nullkiller/Goals/AbstractGoal.cpp | 7 +- AI/Nullkiller/Goals/AbstractGoal.h | 9 +- AI/Nullkiller/Goals/AdventureSpellCast.cpp | 5 + AI/Nullkiller/Goals/AdventureSpellCast.h | 5 + AI/Nullkiller/Goals/Build.cpp | 5 + AI/Nullkiller/Goals/Build.h | 5 + AI/Nullkiller/Goals/BuildBoat.cpp | 5 + AI/Nullkiller/Goals/BuildBoat.h | 5 + AI/Nullkiller/Goals/BuildThis.cpp | 7 +- AI/Nullkiller/Goals/BuildThis.h | 5 + AI/Nullkiller/Goals/BuyArmy.cpp | 7 +- AI/Nullkiller/Goals/BuyArmy.h | 5 + AI/Nullkiller/Goals/CGoal.h | 34 +--- AI/Nullkiller/Goals/CaptureObject.cpp | 7 +- AI/Nullkiller/Goals/CaptureObject.h | 5 + AI/Nullkiller/Goals/CompleteQuest.cpp | 7 +- AI/Nullkiller/Goals/CompleteQuest.h | 4 + AI/Nullkiller/Goals/Composition.cpp | 7 +- AI/Nullkiller/Goals/Composition.h | 4 + AI/Nullkiller/Goals/DigAtTile.cpp | 5 + AI/Nullkiller/Goals/DigAtTile.h | 5 + AI/Nullkiller/Goals/DismissHero.cpp | 5 + AI/Nullkiller/Goals/DismissHero.h | 4 + .../Goals/ExchangeSwapTownHeroes.cpp | 7 +- AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h | 4 + AI/Nullkiller/Goals/ExecuteHeroChain.cpp | 7 +- AI/Nullkiller/Goals/ExecuteHeroChain.h | 4 + AI/Nullkiller/Goals/GatherArmy.cpp | 5 + AI/Nullkiller/Goals/GatherArmy.h | 5 + AI/Nullkiller/Goals/Goals.h | 2 +- AI/Nullkiller/Goals/Invalid.h | 33 +++ AI/Nullkiller/Goals/RecruitHero.cpp | 7 +- AI/Nullkiller/Goals/RecruitHero.h | 5 + AI/Nullkiller/Goals/SaveResources.cpp | 5 + AI/Nullkiller/Goals/SaveResources.h | 4 + AI/Nullkiller/Goals/Trade.cpp | 6 +- AI/Nullkiller/Goals/Trade.h | 5 + AI/Nullkiller/Goals/Win.cpp | 189 ------------------ AI/Nullkiller/Goals/Win.h | 39 ---- AI/Nullkiller/Markers/ArmyUpgrade.cpp | 7 +- AI/Nullkiller/Markers/ArmyUpgrade.h | 6 +- AI/Nullkiller/Markers/DefendTown.cpp | 7 +- AI/Nullkiller/Markers/DefendTown.h | 6 +- AI/Nullkiller/Markers/HeroExchange.cpp | 7 +- AI/Nullkiller/Markers/HeroExchange.h | 6 +- AI/Nullkiller/Markers/UnlockCluster.cpp | 7 +- AI/Nullkiller/Markers/UnlockCluster.h | 7 +- AI/Nullkiller/Pathfinding/AINodeStorage.cpp | 33 +-- AI/Nullkiller/Pathfinding/AINodeStorage.h | 13 +- AI/Nullkiller/Pathfinding/AIPathfinder.cpp | 5 + AI/Nullkiller/Pathfinding/AIPathfinder.h | 5 + .../Pathfinding/AIPathfinderConfig.cpp | 4 + .../Pathfinding/AIPathfinderConfig.h | 5 + .../Pathfinding/Actions/BattleAction.cpp | 7 +- .../Pathfinding/Actions/BattleAction.h | 7 +- .../Pathfinding/Actions/BoatActions.cpp | 14 +- .../Pathfinding/Actions/BoatActions.h | 5 + .../Pathfinding/Actions/BuyArmyAction.cpp | 7 +- .../Pathfinding/Actions/BuyArmyAction.h | 6 +- .../Pathfinding/Actions/QuestAction.cpp | 7 +- .../Pathfinding/Actions/QuestAction.h | 6 +- .../Pathfinding/Actions/SpecialAction.cpp | 8 +- .../Pathfinding/Actions/SpecialAction.h | 5 + .../Pathfinding/Actions/TownPortalAction.cpp | 7 +- .../Pathfinding/Actions/TownPortalAction.h | 6 +- AI/Nullkiller/Pathfinding/Actors.cpp | 27 +-- AI/Nullkiller/Pathfinding/Actors.h | 5 + .../Rules/AILayerTransitionRule.cpp | 8 +- .../Pathfinding/Rules/AILayerTransitionRule.h | 4 + .../Rules/AIMovementAfterDestinationRule.cpp | 14 +- .../Rules/AIMovementAfterDestinationRule.h | 4 + .../Rules/AIMovementToDestinationRule.cpp | 6 +- .../Rules/AIMovementToDestinationRule.h | 4 + .../Pathfinding/Rules/AIPreviousNodeRule.cpp | 6 +- .../Pathfinding/Rules/AIPreviousNodeRule.h | 4 + AI/Nullkiller/main.cpp | 2 +- Global.h | 14 ++ 121 files changed, 713 insertions(+), 471 deletions(-) delete mode 100644 AI/Nullkiller/Behaviors/Behavior.cpp delete mode 100644 AI/Nullkiller/Behaviors/Behavior.h delete mode 100644 AI/Nullkiller/Goals/Win.cpp delete mode 100644 AI/Nullkiller/Goals/Win.h diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index f657d3ecf..1b7313d4e 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -23,7 +23,8 @@ #include "AIGateway.h" #include "Goals/Goals.h" -class CGVisitableOPW; +namespace NKAI +{ const float SAFE_ATTACK_CONSTANT = 1.2; @@ -1668,3 +1669,5 @@ bool AIStatus::channelProbing() { return ongoingChannelProbing; } + +} diff --git a/AI/Nullkiller/AIGateway.h b/AI/Nullkiller/AIGateway.h index 29066be81..f3a4d8454 100644 --- a/AI/Nullkiller/AIGateway.h +++ b/AI/Nullkiller/AIGateway.h @@ -25,11 +25,8 @@ #include "Pathfinding/AIPathfinder.h" #include "Engine/Nullkiller.h" -VCMI_LIB_NAMESPACE_BEGIN - -struct QuestInfo; - -VCMI_LIB_NAMESPACE_END +namespace NKAI +{ class AIStatus { @@ -222,3 +219,5 @@ public: h & battlename; } }; + +} diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 2f2a29fde..52c127c75 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -20,6 +20,9 @@ #include "../../lib/CModHandler.h" +namespace NKAI +{ + extern boost::thread_specific_ptr ai; //extern static const int3 dirs[8]; @@ -446,3 +449,5 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject return true; } + +} diff --git a/AI/Nullkiller/AIUtility.h b/AI/Nullkiller/AIUtility.h index cdc19c1b5..68fa115f6 100644 --- a/AI/Nullkiller/AIUtility.h +++ b/AI/Nullkiller/AIUtility.h @@ -48,19 +48,19 @@ #include "../../lib/mapObjects/CObjectHandler.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/CPathfinder.h" +#include "../../CCallback.h" #include using namespace tbb; -class CCallback; -class Nullkiller; -struct creInfo; - -typedef const int3 & crint3; -typedef const std::string & crstring; typedef std::pair> dwellingContent; +namespace NKAI +{ +struct creInfo; +class Nullkiller; + const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1; const int ACTUAL_RESOURCE_COUNT = 7; const int ALLOWED_ROAMING_HEROES = 8; @@ -151,39 +151,6 @@ struct ObjectIdRef } }; -struct TimeCheck -{ - CStopWatch time; - std::string txt; - TimeCheck(crstring TXT) - : txt(TXT) - { - } - - ~TimeCheck() - { - logAi->trace("Time of %s was %d ms.", txt, time.getDiff()); - } -}; - -//TODO: replace with vstd:: -struct AtScopeExit -{ - std::function foo; - AtScopeExit(const std::function & FOO) - : foo(FOO) - {} - ~AtScopeExit() - { - foo(); - } -}; - - -class ObjsVector : public std::vector -{ -}; - template bool objWithID(const CGObjectInstance * obj) { @@ -278,7 +245,7 @@ uint64_t timeElapsed(std::chrono::time_point bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObjectInstance * obj); template -void pforeachTilePos(crint3 mapSize, TFunc fn) +void pforeachTilePos(const int3 & mapSize, TFunc fn) { for(int z = 0; z < mapSize.z; ++z) { @@ -380,3 +347,5 @@ private: std::shared_ptr *> instance_tracker; boost::mutex sync; }; + +} diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 48e2f3169..e5356d368 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -14,6 +14,8 @@ #include "../../../CCallback.h" #include "../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ class StackUpgradeInfo { public: @@ -497,3 +499,5 @@ ArmyUpgradeInfo ArmyManager::calculateCreaturesUpgrade( return result; } + +} diff --git a/AI/Nullkiller/Analyzers/ArmyManager.h b/AI/Nullkiller/Analyzers/ArmyManager.h index fddad9fcb..5b71bda48 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.h +++ b/AI/Nullkiller/Analyzers/ArmyManager.h @@ -17,6 +17,9 @@ #include "../../../lib/CTownHandler.h" #include "../../../lib/CBuildingHandler.h" +namespace NKAI +{ + class Nullkiller; struct SlotInfo @@ -102,3 +105,5 @@ private: std::vector getHillFortUpgrades(const CCreatureSet * army) const; std::vector getDwellingUpgrades(const CCreatureSet * army, const CGDwelling * dwelling) const; }; + +} diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp index 378598d5e..314b4174f 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.cpp @@ -12,6 +12,9 @@ #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../Engine/Nullkiller.h" +namespace NKAI +{ + void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo) { auto townInfo = developmentInfo.town->town; @@ -394,3 +397,5 @@ std::string BuildingInfo::toString() const + " x " + creatureCost.toString() + ", daily: " + dailyIncome.toString(); } + +} diff --git a/AI/Nullkiller/Analyzers/BuildAnalyzer.h b/AI/Nullkiller/Analyzers/BuildAnalyzer.h index 9fa58f97c..820442a72 100644 --- a/AI/Nullkiller/Analyzers/BuildAnalyzer.h +++ b/AI/Nullkiller/Analyzers/BuildAnalyzer.h @@ -12,6 +12,9 @@ #include "../AIUtility.h" #include "../../../lib/ResourceSet.h" +namespace NKAI +{ + class Nullkiller; class DLL_EXPORT BuildingInfo @@ -104,3 +107,5 @@ private: void updateDailyIncome(); void reset(); }; + +} diff --git a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp index 8192fd1a4..c3cdcbb71 100644 --- a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp @@ -11,6 +11,9 @@ #include "lib/mapping/CMap.h" //for victory conditions #include "../Engine/Nullkiller.h" +namespace NKAI +{ + void DangerHitMapAnalyzer::updateHitMap() { if(upToDate) @@ -137,3 +140,5 @@ void DangerHitMapAnalyzer::reset() { upToDate = false; } + +} diff --git a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.h b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.h index 7d2e70661..b74b52a4e 100644 --- a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.h +++ b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.h @@ -11,6 +11,9 @@ #include "../AIUtility.h" +namespace NKAI +{ + struct HitMapInfo { uint64_t danger; @@ -55,3 +58,5 @@ public: const std::set & getOneTurnAccessibleObjects(const CGHeroInstance * enemy) const; void reset(); }; + +} diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index 7b546f70c..76abf65b9 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -13,6 +13,9 @@ #include "../../../lib/mapObjects/MapObjects.h" #include "../../../lib/CHeroHandler.h" +namespace NKAI +{ + SecondarySkillEvaluator HeroManager::wariorSkillsScores = SecondarySkillEvaluator( { std::make_shared( @@ -305,3 +308,5 @@ float SecondarySkillEvaluator::evaluateSecSkill(const CGHeroInstance * hero, Sec return score; } + +} diff --git a/AI/Nullkiller/Analyzers/HeroManager.h b/AI/Nullkiller/Analyzers/HeroManager.h index 8248a2b0b..459604bef 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.h +++ b/AI/Nullkiller/Analyzers/HeroManager.h @@ -17,6 +17,9 @@ #include "../../../lib/CTownHandler.h" #include "../../../lib/CBuildingHandler.h" +namespace NKAI +{ + class DLL_EXPORT IHeroManager //: public: IAbstractManager { public: @@ -104,3 +107,5 @@ private: public: void evaluateScore(const CGHeroInstance * hero, SecondarySkill skill, float & score) const override; }; + +} diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index 65301992b..2acdef5e9 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -14,6 +14,9 @@ #include "../Engine/Nullkiller.h" #include "lib/mapping/CMap.h" //for victory conditions +namespace NKAI +{ + void ObjectCluster::addObject(const CGObjectInstance * obj, const AIPath & path, float priority) { ClusterObjects::accessor info; @@ -228,7 +231,7 @@ void ObjectClusterizer::clusterize() if(!shouldVisitObject(obj)) return; -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Check object %s%s.", obj->getObjectName(), obj->visitablePos().toString()); #endif @@ -236,7 +239,7 @@ void ObjectClusterizer::clusterize() if(paths.empty()) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("No paths found."); #endif continue; @@ -251,7 +254,7 @@ void ObjectClusterizer::clusterize() { farObjects.addObject(obj, paths.front(), 0); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Object ignored. Moved to far objects with path %s", paths.front().toString()); #endif @@ -262,13 +265,13 @@ void ObjectClusterizer::clusterize() for(auto & path : paths) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Checking path %s", path.toString()); #endif if(!shouldVisit(ai, path.targetHero, obj)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Hero %s does not need to visit %s", path.targetHero->name, obj->getObjectName()); #endif continue; @@ -282,7 +285,7 @@ void ObjectClusterizer::clusterize() { if(vstd::contains(heroesProcessed, path.targetHero)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Hero %s is already processed.", path.targetHero->name); #endif continue; @@ -302,7 +305,7 @@ void ObjectClusterizer::clusterize() cluster->second->addObject(obj, path, priority); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Path added to cluster %s%s", blocker->getObjectName(), blocker->visitablePos().toString()); #endif continue; @@ -327,7 +330,7 @@ void ObjectClusterizer::clusterize() farObjects.addObject(obj, path, priority); } -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Path %s added to %s objects. Turn: %d, priority: %f", path.toString(), interestingObject ? "near" : "far", @@ -345,7 +348,7 @@ void ObjectClusterizer::clusterize() { logAi->trace("Cluster %s %s count: %i", pair.first->getObjectName(), pair.first->visitablePos().toString(), pair.second->objects.size()); -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 for(auto obj : pair.second->getObjects()) { logAi->trace("Object %s %s", obj->getObjectName(), obj->visitablePos().toString()); @@ -355,3 +358,5 @@ void ObjectClusterizer::clusterize() logAi->trace("Clusterization complete in %ld", timeElapsed(start)); } + +} diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.h b/AI/Nullkiller/Analyzers/ObjectClusterizer.h index 3972e3084..c8137bba9 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.h +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.h @@ -11,6 +11,9 @@ #include "../Pathfinding/AINodeStorage.h" +namespace NKAI +{ + struct ClusterObjectInfo { float priority; @@ -72,3 +75,5 @@ public: private: bool shouldVisitObject(const CGObjectInstance * obj) const; }; + +} diff --git a/AI/Nullkiller/Behaviors/Behavior.cpp b/AI/Nullkiller/Behaviors/Behavior.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/AI/Nullkiller/Behaviors/Behavior.h b/AI/Nullkiller/Behaviors/Behavior.h deleted file mode 100644 index e9e36197e..000000000 --- a/AI/Nullkiller/Behaviors/Behavior.h +++ /dev/null @@ -1,19 +0,0 @@ -/* -* Behavior.h, part of VCMI engine -* -* Authors: listed in file AUTHORS in main folder -* -* License: GNU General Public License v2.0 or later -* Full text of license available in license.txt file, in main folder -* -*/ -#pragma once - -#include "../AIGateway.h" -#error REMOVE THIS FILE - -class Behavior : public Goals::AbstractGoal -{ -public: - virtual std::string toString() const = 0; -}; diff --git a/AI/Nullkiller/Behaviors/BuildingBehavior.cpp b/AI/Nullkiller/Behaviors/BuildingBehavior.cpp index 5fc50c213..e41840662 100644 --- a/AI/Nullkiller/Behaviors/BuildingBehavior.cpp +++ b/AI/Nullkiller/Behaviors/BuildingBehavior.cpp @@ -19,6 +19,9 @@ #include "lib/CPathfinder.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -77,3 +80,5 @@ Goals::TGoalVec BuildingBehavior::decompose() const return tasks; } + +} diff --git a/AI/Nullkiller/Behaviors/BuildingBehavior.h b/AI/Nullkiller/Behaviors/BuildingBehavior.h index 914b2d241..813a37619 100644 --- a/AI/Nullkiller/Behaviors/BuildingBehavior.h +++ b/AI/Nullkiller/Behaviors/BuildingBehavior.h @@ -13,6 +13,8 @@ #include "../AIUtility.h" #include "../Goals/CGoal.h" +namespace NKAI +{ namespace Goals { class BuildingBehavior : public CGoal @@ -32,3 +34,4 @@ namespace Goals }; } +} diff --git a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp index d7fbea89b..c4e96bb54 100644 --- a/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/BuyArmyBehavior.cpp @@ -16,6 +16,9 @@ #include "lib/mapping/CMap.h" //for victory conditions #include "lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -75,3 +78,5 @@ Goals::TGoalVec BuyArmyBehavior::decompose() const return tasks; } + +} diff --git a/AI/Nullkiller/Behaviors/BuyArmyBehavior.h b/AI/Nullkiller/Behaviors/BuyArmyBehavior.h index 4c0aa8f3d..a6bf681c7 100644 --- a/AI/Nullkiller/Behaviors/BuyArmyBehavior.h +++ b/AI/Nullkiller/Behaviors/BuyArmyBehavior.h @@ -13,6 +13,8 @@ #include "../AIUtility.h" #include "../Goals/CGoal.h" +namespace NKAI +{ namespace Goals { class BuyArmyBehavior : public CGoal @@ -30,3 +32,5 @@ namespace Goals } }; } + +} diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp index 0b65c4eac..d6b7eee41 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp @@ -12,9 +12,13 @@ #include "../Engine/Nullkiller.h" #include "../Goals/Composition.h" #include "../Goals/ExecuteHeroChain.h" +#include "../Goals/Invalid.h" #include "CaptureObjectsBehavior.h" #include "../AIUtility.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -59,13 +63,13 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector { tasks.push_back(sptr(Goals::Invalid())); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Path found %s", path.toString()); #endif if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength()); #endif continue; @@ -85,7 +89,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector { auto subGoal = firstBlockedAction->decompose(path.targetHero); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Decomposing special action %s returns %s", firstBlockedAction->toString(), subGoal->toString()); #endif @@ -104,7 +108,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getVisitGoals(const std::vector auto isSafe = isSafeToVisit(hero, path.heroArmy, danger); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace( "It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld", isSafe ? "safe" : "not safe", @@ -161,7 +165,7 @@ Goals::TGoalVec CaptureObjectsBehavior::decompose() const if(!objectMatchesFilter(objToVisit)) continue; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Checking object %s, %s", objToVisit->getObjectName(), objToVisit->visitablePos().toString()); #endif @@ -171,7 +175,7 @@ Goals::TGoalVec CaptureObjectsBehavior::decompose() const std::vector> waysToVisitObj; std::shared_ptr closestWay; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Found %d paths", paths.size()); #endif vstd::concatenate(tasks, getVisitGoals(paths, objToVisit)); @@ -219,3 +223,5 @@ bool CaptureObjectsBehavior::objectMatchesFilter(const CGObjectInstance * obj) c return true; } + +} diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.h b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.h index 45a4a907c..ce075c858 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.h +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.h @@ -14,6 +14,8 @@ #include "../Goals/CGoal.h" #include "../Pathfinding/AINodeStorage.h" +namespace NKAI +{ namespace Goals { class CaptureObjectsBehavior : public CGoal @@ -72,3 +74,5 @@ namespace Goals }; } + +} diff --git a/AI/Nullkiller/Behaviors/ClusterBehavior.cpp b/AI/Nullkiller/Behaviors/ClusterBehavior.cpp index 79ed91def..ff0679564 100644 --- a/AI/Nullkiller/Behaviors/ClusterBehavior.cpp +++ b/AI/Nullkiller/Behaviors/ClusterBehavior.cpp @@ -16,6 +16,9 @@ #include "../Goals/Composition.h" #include "../Behaviors/CaptureObjectsBehavior.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -50,7 +53,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr TGoalVec goals; -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace( "Checking cluster %s %s, found %d paths", cluster->blocker->getObjectName(), @@ -60,7 +63,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr for(auto path = paths.begin(); path != paths.end();) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Checking path %s", path->toString()); #endif @@ -89,13 +92,13 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr for(auto & node : clonedPath.nodes) node.parentIndex -= path->nodes.size() - clonedPath.nodes.size(); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Unlock path found %s", blockerPaths.back().toString()); #endif path++; } -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Decompose unlock paths"); #endif @@ -114,3 +117,5 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr return goals; } + +} diff --git a/AI/Nullkiller/Behaviors/ClusterBehavior.h b/AI/Nullkiller/Behaviors/ClusterBehavior.h index a05a4d05e..e5a52f73c 100644 --- a/AI/Nullkiller/Behaviors/ClusterBehavior.h +++ b/AI/Nullkiller/Behaviors/ClusterBehavior.h @@ -13,6 +13,9 @@ #include "../Goals/CGoal.h" #include "../AIUtility.h" +namespace NKAI +{ + struct ObjectCluster; namespace Goals @@ -36,4 +39,6 @@ namespace Goals private: Goals::TGoalVec decomposeCluster(std::shared_ptr cluster) const; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp index 41422b0b9..5ca3f1f4e 100644 --- a/AI/Nullkiller/Behaviors/DefenceBehavior.cpp +++ b/AI/Nullkiller/Behaviors/DefenceBehavior.cpp @@ -23,6 +23,9 @@ #include "lib/mapping/CMap.h" //for victory conditions #include "lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -117,7 +120,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta || path.turn() < treat.turn - 1 || (path.turn() < treat.turn && treat.turn >= 2)) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace( "Hero %s can eliminate danger for town %s using path %s.", path.targetHero->name, @@ -148,7 +151,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta if(cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Hero %s can be recruited to defend %s", hero->name, town->name); #endif tasks.push_back(Goals::sptr(Goals::RecruitHero(town, hero).setpriority(1))); @@ -196,7 +199,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta { auto & path = paths[i]; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace( "Hero %s can defend town with force %lld in %s turns, cost: %f, path: %s", path.targetHero->name, @@ -207,7 +210,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta #endif if(path.turn() <= treat.turn - 2) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Deffer defence of %s by %s because he has enough time to rich the town next trun", town->name, path.targetHero->name); @@ -220,7 +223,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta if(path.targetHero == town->visitingHero && path.exchangeCount == 1) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Put %s to garrison of town %s", path.targetHero->name, town->name); @@ -244,7 +247,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta { if(ai->nullkiller->arePathHeroesLocked(path)) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Can not move %s to defend town %s. Path is locked.", path.targetHero->name, town->name); @@ -272,7 +275,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta } } -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Move %s to defend town %s", path.targetHero->name, town->name); @@ -286,13 +289,13 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta { auto subGoal = firstBlockedAction->decompose(path.targetHero); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Decomposing special action %s returns %s", firstBlockedAction->toString(), subGoal->toString()); #endif if(subGoal->invalid()) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Path is invalid. Skipping"); #endif continue; @@ -307,3 +310,5 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta logAi->debug("Found %d tasks", tasks.size()); } + +} diff --git a/AI/Nullkiller/Behaviors/DefenceBehavior.h b/AI/Nullkiller/Behaviors/DefenceBehavior.h index a0e182ab6..bd606cd36 100644 --- a/AI/Nullkiller/Behaviors/DefenceBehavior.h +++ b/AI/Nullkiller/Behaviors/DefenceBehavior.h @@ -13,6 +13,8 @@ #include "../Goals/CGoal.h" #include "../AIUtility.h" +namespace NKAI +{ namespace Goals { class DefenceBehavior : public CGoal @@ -36,3 +38,5 @@ namespace Goals }; } + +} diff --git a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp index f16f93d8d..9673cfd82 100644 --- a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp @@ -19,6 +19,9 @@ #include "lib/mapping/CMap.h" //for victory conditions #include "lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -64,12 +67,12 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her Goals::TGoalVec tasks; const int3 pos = hero->visitablePos(); -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Checking ways to gaher army for hero %s, %s", hero->getObjectName(), pos.toString()); #endif if(ai->nullkiller->isHeroLocked(hero)) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Skipping locked hero %s, %s", hero->getObjectName(), pos.toString()); #endif return tasks; @@ -77,13 +80,13 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her auto paths = ai->nullkiller->pathfinder->getPathInfo(pos); -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Gather army found %d paths", paths.size()); #endif for(const AIPath & path : paths) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Path found %s", path.toString()); #endif @@ -91,7 +94,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength()); #endif continue; @@ -99,7 +102,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her if(ai->nullkiller->arePathHeroesLocked(path)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path because of locked hero"); #endif continue; @@ -112,7 +115,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her // avoid transferring very small amount of army if(armyValue < 0.1f) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Army value is too small."); #endif continue; @@ -121,7 +124,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her // avoid trying to move bigger army to the weaker one. if(armyValue > 1) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Army value is too large."); #endif continue; @@ -131,7 +134,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her auto isSafe = isSafeToVisit(hero, path.heroArmy, danger); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace( "It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld", isSafe ? "safe" : "not safe", @@ -156,7 +159,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her if(blockedAction) { - #if AI_TRACE_LEVEL >= 2 + #if NKAI_TRACE_LEVEL >= 2 logAi->trace("Action is blocked. Considering decomposition."); #endif composition.addNext(blockedAction->decompose(path.targetHero)); @@ -175,25 +178,25 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) const int3 pos = upgrader->visitablePos(); TResources availableResources = ai->nullkiller->getFreeResources(); -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Checking ways to upgrade army in town %s, %s", upgrader->getObjectName(), pos.toString()); #endif auto paths = ai->nullkiller->pathfinder->getPathInfo(pos); std::vector> waysToVisitObj; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Found %d paths", paths.size()); #endif for(const AIPath & path : paths) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Path found %s", path.toString()); #endif if(upgrader->visitingHero != path.targetHero) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path. Town has visiting hero."); #endif continue; @@ -201,7 +204,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) if(ai->nullkiller->arePathHeroesLocked(path)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path because of locked hero"); #endif continue; @@ -209,7 +212,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) if(path.getFirstBlockedAction()) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 // TODO: decomposition? logAi->trace("Ignore path. Action is blocked."); #endif @@ -218,7 +221,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path)) { -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength()); #endif continue; @@ -234,7 +237,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) auto isSafe = isSafeToVisit(path.targetHero, path.heroArmy, danger); -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace( "It is %s to visit %s by %s with army %lld, danger %lld and army loss %lld", isSafe ? "safe" : "not safe", @@ -257,3 +260,5 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) return tasks; } + +} diff --git a/AI/Nullkiller/Behaviors/GatherArmyBehavior.h b/AI/Nullkiller/Behaviors/GatherArmyBehavior.h index cf900bb7f..b933575ba 100644 --- a/AI/Nullkiller/Behaviors/GatherArmyBehavior.h +++ b/AI/Nullkiller/Behaviors/GatherArmyBehavior.h @@ -13,6 +13,8 @@ #include "../Goals/CGoal.h" #include "../AIUtility.h" +namespace NKAI +{ namespace Goals { class GatherArmyBehavior : public CGoal @@ -37,3 +39,5 @@ namespace Goals }; } + +} diff --git a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp index f90323bfa..e6ddae756 100644 --- a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp +++ b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp @@ -16,6 +16,9 @@ #include "lib/mapping/CMap.h" //for victory conditions #include "lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -46,3 +49,5 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const return tasks; } + +} diff --git a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.h b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.h index 018d62e63..4d1102b4d 100644 --- a/AI/Nullkiller/Behaviors/RecruitHeroBehavior.h +++ b/AI/Nullkiller/Behaviors/RecruitHeroBehavior.h @@ -13,6 +13,8 @@ #include "../Goals/CGoal.h" #include "../AIUtility.h" +namespace NKAI +{ namespace Goals { class RecruitHeroBehavior : public CGoal @@ -31,4 +33,6 @@ namespace Goals return true; } }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.cpp b/AI/Nullkiller/Behaviors/StartupBehavior.cpp index f5f84187f..462529005 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.cpp +++ b/AI/Nullkiller/Behaviors/StartupBehavior.cpp @@ -20,6 +20,9 @@ #include "lib/CPathfinder.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -221,3 +224,5 @@ Goals::TGoalVec StartupBehavior::decompose() const return tasks; } + +} diff --git a/AI/Nullkiller/Behaviors/StartupBehavior.h b/AI/Nullkiller/Behaviors/StartupBehavior.h index 1022339b4..12cfb33c2 100644 --- a/AI/Nullkiller/Behaviors/StartupBehavior.h +++ b/AI/Nullkiller/Behaviors/StartupBehavior.h @@ -13,6 +13,8 @@ #include "../Goals/CGoal.h" #include "../AIUtility.h" +namespace NKAI +{ namespace Goals { class StartupBehavior : public CGoal @@ -33,3 +35,5 @@ namespace Goals }; } + +} diff --git a/AI/Nullkiller/Engine/AIMemory.cpp b/AI/Nullkiller/Engine/AIMemory.cpp index 9f67f9d37..09535893c 100644 --- a/AI/Nullkiller/Engine/AIMemory.cpp +++ b/AI/Nullkiller/Engine/AIMemory.cpp @@ -11,6 +11,9 @@ #include "AIMemory.h" #include "../../../CCallback.h" +namespace NKAI +{ + void AIMemory::removeFromMemory(const CGObjectInstance * obj) { vstd::erase_if_present(visitableObjs, obj); @@ -101,4 +104,6 @@ void AIMemory::removeInvisibleObjects(CCallback * cb) vstd::erase_if(visitableObjs, shouldBeErased); vstd::erase_if(alreadyVisited, shouldBeErased); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Engine/AIMemory.h b/AI/Nullkiller/Engine/AIMemory.h index 7c0bf60b2..c3596726c 100644 --- a/AI/Nullkiller/Engine/AIMemory.h +++ b/AI/Nullkiller/Engine/AIMemory.h @@ -12,6 +12,9 @@ #include "../AIUtility.h" #include "../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ + class AIMemory { public: @@ -29,3 +32,5 @@ public: bool wasVisited(const CGObjectInstance * obj) const; void removeInvisibleObjects(CCallback * cb); }; + +} diff --git a/AI/Nullkiller/Engine/DeepDecomposer.cpp b/AI/Nullkiller/Engine/DeepDecomposer.cpp index 565aa7dfc..8e649634f 100644 --- a/AI/Nullkiller/Engine/DeepDecomposer.cpp +++ b/AI/Nullkiller/Engine/DeepDecomposer.cpp @@ -21,6 +21,9 @@ #include "../Goals/Invalid.h" #include "../Goals/Composition.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -49,7 +52,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit) TSubgoal current = goals[depth].back(); TGoalVec subgoals = decomposeCached(unwrapComposition(current), fromCache); -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Decomposition level %d returned %d goals", depth, subgoals.size()); #endif @@ -69,7 +72,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit) // 0 - goals directly from behavior Goals::TSubgoal task = depth >= 1 ? aggregateGoals(0, subgoal) : subgoal; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Found task %s", task->toString()); #endif if(!isCompositionLoop(subgoal)) @@ -84,7 +87,7 @@ Goals::TGoalVec DeepDecomposer::decompose(TSubgoal behavior, int depthLimit) } else if(depth < depthLimit - 1) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Found abstract goal %s", subgoal->toString()); #endif if(!isCompositionLoop(subgoal)) @@ -176,7 +179,7 @@ bool DeepDecomposer::isCompositionLoop(TSubgoal goal) TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Decomposing %s, level %s", goal->toString(), depth); #endif @@ -188,7 +191,7 @@ TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache) if(cached != decompositionCache[i].end()) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Use decomposition cache for %s, level: %d", goal->toString(), depth); #endif fromCache = true; @@ -200,7 +203,7 @@ TGoalVec DeepDecomposer::decomposeCached(TSubgoal goal, bool & fromCache) decompositionCache[depth][goal] = {}; // if goal decomposition yields no goals we still need it in cache to not decompose again } -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Calling decompose on %s, level %s", goal->toString(), depth); #endif @@ -221,7 +224,7 @@ void DeepDecomposer::addToCache(TSubgoal goal) { auto solution = parentDepth < depth ? aggregateGoals(parentDepth + 1, goal) : goal; -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Adding %s to decomosition cache of %s at level %d", solution->toString(), parent->toString(), parentDepth); #endif @@ -234,4 +237,6 @@ void DeepDecomposer::addToCache(TSubgoal goal) } } } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Engine/DeepDecomposer.h b/AI/Nullkiller/Engine/DeepDecomposer.h index bf10dbe3e..7d11764e8 100644 --- a/AI/Nullkiller/Engine/DeepDecomposer.h +++ b/AI/Nullkiller/Engine/DeepDecomposer.h @@ -11,6 +11,9 @@ #include "../Goals/AbstractGoal.h" +namespace NKAI +{ + struct GoalHash { uint64_t operator()(const Goals::TSubgoal & goal) const @@ -38,4 +41,6 @@ private: bool isCompositionLoop(Goals::TSubgoal goal); Goals::TGoalVec decomposeCached(Goals::TSubgoal goal, bool & fromCache); void addToCache(Goals::TSubgoal goal); -}; \ No newline at end of file +}; + +} diff --git a/AI/Nullkiller/Engine/FuzzyEngines.cpp b/AI/Nullkiller/Engine/FuzzyEngines.cpp index ab449e666..04f1fe758 100644 --- a/AI/Nullkiller/Engine/FuzzyEngines.cpp +++ b/AI/Nullkiller/Engine/FuzzyEngines.cpp @@ -14,6 +14,9 @@ #include "../../../lib/mapObjects/MapObjects.h" #include "../AIGateway.h" +namespace NKAI +{ + #define MIN_AI_STRENGTH (0.5f) //lower when combat AI gets smarter #define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us @@ -239,3 +242,5 @@ float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, c return output; } + +} diff --git a/AI/Nullkiller/Engine/FuzzyEngines.h b/AI/Nullkiller/Engine/FuzzyEngines.h index 0e0c533da..1694d175c 100644 --- a/AI/Nullkiller/Engine/FuzzyEngines.h +++ b/AI/Nullkiller/Engine/FuzzyEngines.h @@ -17,6 +17,9 @@ class CArmedInstance; VCMI_LIB_NAMESPACE_END +namespace NKAI +{ + class engineBase //subclasses create fuzzylite variables with "new" that are not freed - this is desired as fl::Engine wants to destroy these... { protected: @@ -40,3 +43,5 @@ private: fl::InputVariable * castleWalls; fl::OutputVariable * threat; }; + +} diff --git a/AI/Nullkiller/Engine/FuzzyHelper.cpp b/AI/Nullkiller/Engine/FuzzyHelper.cpp index 132b6ad15..95076b274 100644 --- a/AI/Nullkiller/Engine/FuzzyHelper.cpp +++ b/AI/Nullkiller/Engine/FuzzyHelper.cpp @@ -14,6 +14,9 @@ #include "../Goals/Goals.h" #include "Nullkiller.h" +namespace NKAI +{ + ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) { //this one is not fuzzy anymore, just calculate weighted average @@ -33,7 +36,7 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank) } -ui64 FuzzyHelper::evaluateDanger(crint3 tile, const CGHeroInstance * visitor, bool checkGuards) +ui64 FuzzyHelper::evaluateDanger(const int3 & tile, const CGHeroInstance * visitor, bool checkGuards) { auto cb = ai->cb.get(); const TerrainTile * t = cb->getTile(tile, false); @@ -153,4 +156,6 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj) default: return 0; } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Engine/FuzzyHelper.h b/AI/Nullkiller/Engine/FuzzyHelper.h index 760b34279..a3a2f2955 100644 --- a/AI/Nullkiller/Engine/FuzzyHelper.h +++ b/AI/Nullkiller/Engine/FuzzyHelper.h @@ -16,6 +16,9 @@ class CBank; VCMI_LIB_NAMESPACE_END +namespace NKAI +{ + class Nullkiller; class DLL_EXPORT FuzzyHelper @@ -30,5 +33,7 @@ public: ui64 estimateBankDanger(const CBank * bank); //TODO: move to another class? ui64 evaluateDanger(const CGObjectInstance * obj); - ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor, bool checkGuards = true); + ui64 evaluateDanger(const int3 & tile, const CGHeroInstance * visitor, bool checkGuards = true); }; + +} diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index add63e4bd..8b3e56f21 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -21,12 +21,15 @@ #include "../Goals/Invalid.h" #include "../Goals/Composition.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; using namespace Goals; -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 #define MAXPASS 1000000 #else #define MAXPASS 30 @@ -178,7 +181,7 @@ bool Nullkiller::arePathHeroesLocked(const AIPath & path) const { if(getHeroLockedReason(path.targetHero) == HeroLockedReason::STARTUP) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString()); #endif return true; @@ -190,7 +193,7 @@ bool Nullkiller::arePathHeroesLocked(const AIPath & path) const if(lockReason != HeroLockedReason::NOT_LOCKED) { -#if AI_TRACE_LEVEL >= 1 +#if NKAI_TRACE_LEVEL >= 1 logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString()); #endif return true; @@ -326,3 +329,5 @@ void Nullkiller::lockResources(const TResources & res) { lockedResources += res; } + +} diff --git a/AI/Nullkiller/Engine/Nullkiller.h b/AI/Nullkiller/Engine/Nullkiller.h index 9bb3304c0..e462040ff 100644 --- a/AI/Nullkiller/Engine/Nullkiller.h +++ b/AI/Nullkiller/Engine/Nullkiller.h @@ -19,6 +19,9 @@ #include "../Analyzers/HeroManager.h" #include "../Analyzers/ObjectClusterizer.h" +namespace NKAI +{ + const float MAX_GOLD_PEASURE = 0.3f; const float MIN_PRIORITY = 0.01f; const float NEXT_SCAN_MIN_PRIORITY = 0.4f; @@ -92,3 +95,5 @@ private: Goals::TTask choseBestTask(Goals::TTaskVec & tasks) const; void executeTask(Goals::TTask task); }; + +} diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.cpp b/AI/Nullkiller/Engine/PriorityEvaluator.cpp index 58f97b837..b0abfffac 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.cpp +++ b/AI/Nullkiller/Engine/PriorityEvaluator.cpp @@ -26,6 +26,9 @@ #include "../Markers/ArmyUpgrade.h" #include "../Markers/DefendTown.h" +namespace NKAI +{ + #define MIN_AI_STRENGHT (0.5f) //lower when combat AI gets smarter #define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us @@ -847,7 +850,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task) logAi->error("evaluate VisitTile: %s", fe.getWhat()); } -#if AI_TRACE_LEVEL >= 2 +#if NKAI_TRACE_LEVEL >= 2 logAi->trace("Evaluated %s, loss: %f, turn: %d, turns main: %f, scout: %f, gold: %d, cost: %d, army gain: %d, danger: %d, role: %s, strategical value: %f, cwr: %f, fear: %f, result %f", task->toString(), evaluationContext.armyLossPersentage, @@ -867,3 +870,5 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task) return result; } + +} diff --git a/AI/Nullkiller/Engine/PriorityEvaluator.h b/AI/Nullkiller/Engine/PriorityEvaluator.h index 6156c08c2..e026f2259 100644 --- a/AI/Nullkiller/Engine/PriorityEvaluator.h +++ b/AI/Nullkiller/Engine/PriorityEvaluator.h @@ -18,6 +18,9 @@ class CGWitchHut; VCMI_LIB_NAMESPACE_END +namespace NKAI +{ + class BuildingInfo; class Nullkiller; @@ -105,3 +108,5 @@ private: EvaluationContext buildEvaluationContext(Goals::TSubgoal goal) const; }; + +} diff --git a/AI/Nullkiller/Goals/AbstractGoal.cpp b/AI/Nullkiller/Goals/AbstractGoal.cpp index 52d6056fc..9433dfad2 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.cpp +++ b/AI/Nullkiller/Goals/AbstractGoal.cpp @@ -14,6 +14,9 @@ #include "../../../lib/CPathfinder.h" #include "../../../lib/StringConstants.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -84,4 +87,6 @@ bool TSubgoal::operator==(const TSubgoal & rhs) const bool AbstractGoal::invalid() const { return goalType == EGoals::INVALID; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/AbstractGoal.h b/AI/Nullkiller/Goals/AbstractGoal.h index 7407a5fc4..7c4788e72 100644 --- a/AI/Nullkiller/Goals/AbstractGoal.h +++ b/AI/Nullkiller/Goals/AbstractGoal.h @@ -15,6 +15,9 @@ #include "../../../lib/CTownHandler.h" #include "../AIUtility.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -171,8 +174,8 @@ class cannotFulfillGoalException : public std::exception std::string msg; public: - explicit cannotFulfillGoalException(crstring _Message) - : msg(_Message) + explicit cannotFulfillGoalException(const std::string & message) + : msg(message) { } @@ -208,3 +211,5 @@ public: return msg.c_str(); } }; + +} diff --git a/AI/Nullkiller/Goals/AdventureSpellCast.cpp b/AI/Nullkiller/Goals/AdventureSpellCast.cpp index ea8afd5b8..bffab6a13 100644 --- a/AI/Nullkiller/Goals/AdventureSpellCast.cpp +++ b/AI/Nullkiller/Goals/AdventureSpellCast.cpp @@ -13,6 +13,9 @@ #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -69,3 +72,5 @@ std::string AdventureSpellCast::toString() const { return "AdventureSpellCast " + spellID.toSpell()->name; } + +} diff --git a/AI/Nullkiller/Goals/AdventureSpellCast.h b/AI/Nullkiller/Goals/AdventureSpellCast.h index 063848521..23cfc4a97 100644 --- a/AI/Nullkiller/Goals/AdventureSpellCast.h +++ b/AI/Nullkiller/Goals/AdventureSpellCast.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + namespace Goals { class DLL_EXPORT AdventureSpellCast : public ElementarGoal @@ -35,3 +38,5 @@ namespace Goals virtual bool operator==(const AdventureSpellCast & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/Build.cpp b/AI/Nullkiller/Goals/Build.cpp index 3497706ba..e59c877eb 100644 --- a/AI/Nullkiller/Goals/Build.cpp +++ b/AI/Nullkiller/Goals/Build.cpp @@ -1,3 +1,6 @@ +namespace Nullkiller +{ + /* * Build.cpp, part of VCMI engine * @@ -91,3 +94,5 @@ bool Build::fulfillsMe(TSubgoal goal) else return false; } + +} diff --git a/AI/Nullkiller/Goals/Build.h b/AI/Nullkiller/Goals/Build.h index df2311e2e..8ff8d3228 100644 --- a/AI/Nullkiller/Goals/Build.h +++ b/AI/Nullkiller/Goals/Build.h @@ -1,3 +1,6 @@ +namespace Nullkiller +{ + /* * Build.h, part of VCMI engine * @@ -35,3 +38,5 @@ namespace Goals } }; } + +} diff --git a/AI/Nullkiller/Goals/BuildBoat.cpp b/AI/Nullkiller/Goals/BuildBoat.cpp index 0b934ffbf..8c28b43f9 100644 --- a/AI/Nullkiller/Goals/BuildBoat.cpp +++ b/AI/Nullkiller/Goals/BuildBoat.cpp @@ -14,6 +14,9 @@ #include "../../../lib/CPathfinder.h" #include "../Behaviors/CaptureObjectsBehavior.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -77,3 +80,5 @@ std::string BuildBoat::toString() const { return "BuildBoat"; } + +} diff --git a/AI/Nullkiller/Goals/BuildBoat.h b/AI/Nullkiller/Goals/BuildBoat.h index 858e6810f..31383d256 100644 --- a/AI/Nullkiller/Goals/BuildBoat.h +++ b/AI/Nullkiller/Goals/BuildBoat.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + namespace Goals { class DLL_EXPORT BuildBoat : public ElementarGoal @@ -29,3 +32,5 @@ namespace Goals virtual bool operator==(const BuildBoat & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/BuildThis.cpp b/AI/Nullkiller/Goals/BuildThis.cpp index c43a26796..06a06b25b 100644 --- a/AI/Nullkiller/Goals/BuildThis.cpp +++ b/AI/Nullkiller/Goals/BuildThis.cpp @@ -16,6 +16,9 @@ #include "../../../lib/StringConstants.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -63,4 +66,6 @@ void BuildThis::accept(AIGateway * ai) } throw cannotFulfillGoalException("Cannot build a given structure!"); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/BuildThis.h b/AI/Nullkiller/Goals/BuildThis.h index a8a273ac9..f4bacbc5e 100644 --- a/AI/Nullkiller/Goals/BuildThis.h +++ b/AI/Nullkiller/Goals/BuildThis.h @@ -12,6 +12,9 @@ #include "CGoal.h" #include "../Analyzers/BuildAnalyzer.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -41,3 +44,5 @@ namespace Goals void accept(AIGateway * ai) override; }; } + +} diff --git a/AI/Nullkiller/Goals/BuyArmy.cpp b/AI/Nullkiller/Goals/BuyArmy.cpp index c4d6f7151..dc35c16ba 100644 --- a/AI/Nullkiller/Goals/BuyArmy.cpp +++ b/AI/Nullkiller/Goals/BuyArmy.cpp @@ -14,6 +14,9 @@ #include "../Engine/Nullkiller.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -72,4 +75,6 @@ void BuyArmy::accept(AIGateway * ai) { ai->moveHeroToTile(town->visitablePos(), town->visitingHero.get()); } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/BuyArmy.h b/AI/Nullkiller/Goals/BuyArmy.h index 79b6ef99d..d4fdc6166 100644 --- a/AI/Nullkiller/Goals/BuyArmy.h +++ b/AI/Nullkiller/Goals/BuyArmy.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -40,3 +43,5 @@ namespace Goals virtual void accept(AIGateway * ai) override; }; } + +} diff --git a/AI/Nullkiller/Goals/CGoal.h b/AI/Nullkiller/Goals/CGoal.h index e5f9679c8..722c7ebd2 100644 --- a/AI/Nullkiller/Goals/CGoal.h +++ b/AI/Nullkiller/Goals/CGoal.h @@ -11,6 +11,9 @@ #include "AbstractGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; @@ -93,33 +96,6 @@ namespace Goals virtual int getHeroExchangeCount() const override { return 0; } }; - - class DLL_EXPORT Invalid : public ElementarGoal - { - public: - Invalid() - : ElementarGoal(Goals::INVALID) - { - priority = -1; - } - TGoalVec decompose() const override - { - return TGoalVec(); - } - - virtual bool operator==(const Invalid & other) const override - { - return true; - } - - virtual std::string toString() const override - { - return "Invalid"; - } - - virtual void accept(AIGateway * ai) override - { - throw cannotFulfillGoalException("Can not fulfill Invalid goal!"); - } - }; +} + } diff --git a/AI/Nullkiller/Goals/CaptureObject.cpp b/AI/Nullkiller/Goals/CaptureObject.cpp index 1950e249f..0dd71dc93 100644 --- a/AI/Nullkiller/Goals/CaptureObject.cpp +++ b/AI/Nullkiller/Goals/CaptureObject.cpp @@ -15,6 +15,9 @@ #include "../Behaviors/CaptureObjectsBehavior.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; using namespace Goals; @@ -37,4 +40,6 @@ std::string CaptureObject::toString() const TGoalVec CaptureObject::decompose() const { return CaptureObjectsBehavior(cb->getObj(ObjectInstanceID(objid))).decompose(); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/CaptureObject.h b/AI/Nullkiller/Goals/CaptureObject.h index a53a78ff0..e78993638 100644 --- a/AI/Nullkiller/Goals/CaptureObject.h +++ b/AI/Nullkiller/Goals/CaptureObject.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -38,3 +41,5 @@ namespace Goals virtual uint64_t getHash() const override; }; } + +} diff --git a/AI/Nullkiller/Goals/CompleteQuest.cpp b/AI/Nullkiller/Goals/CompleteQuest.cpp index 65d08f8b0..25dd9eb7f 100644 --- a/AI/Nullkiller/Goals/CompleteQuest.cpp +++ b/AI/Nullkiller/Goals/CompleteQuest.cpp @@ -16,6 +16,9 @@ #include "../../../lib/VCMI_Lib.h" #include "../../../lib/CGeneralTextHandler.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -245,4 +248,6 @@ TGoalVec CompleteQuest::missionDestroyObj() const } return TGoalVec(); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/CompleteQuest.h b/AI/Nullkiller/Goals/CompleteQuest.h index b2895917c..007b8d212 100644 --- a/AI/Nullkiller/Goals/CompleteQuest.h +++ b/AI/Nullkiller/Goals/CompleteQuest.h @@ -14,6 +14,8 @@ #include "../Goals/CGoal.h" #include "../../../lib/CGameState.h" +namespace NKAI +{ namespace Goals { class CompleteQuest : public CGoal @@ -47,3 +49,5 @@ namespace Goals std::string questToString() const; }; } + +} diff --git a/AI/Nullkiller/Goals/Composition.cpp b/AI/Nullkiller/Goals/Composition.cpp index 4adafdfe0..caaef64b7 100644 --- a/AI/Nullkiller/Goals/Composition.cpp +++ b/AI/Nullkiller/Goals/Composition.cpp @@ -16,6 +16,9 @@ #include "../../../lib/StringConstants.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -77,4 +80,6 @@ bool Composition::isElementar() const int Composition::getHeroExchangeCount() const { return isElementar() ? taskptr(*subtasks.back())->getHeroExchangeCount() : 0; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/Composition.h b/AI/Nullkiller/Goals/Composition.h index ce8b66313..f7de02bb0 100644 --- a/AI/Nullkiller/Goals/Composition.h +++ b/AI/Nullkiller/Goals/Composition.h @@ -11,6 +11,8 @@ #include "CGoal.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT Composition : public ElementarGoal @@ -39,3 +41,5 @@ namespace Goals virtual int getHeroExchangeCount() const override; }; } + +} diff --git a/AI/Nullkiller/Goals/DigAtTile.cpp b/AI/Nullkiller/Goals/DigAtTile.cpp index 9236a3788..a573bfbd0 100644 --- a/AI/Nullkiller/Goals/DigAtTile.cpp +++ b/AI/Nullkiller/Goals/DigAtTile.cpp @@ -13,6 +13,9 @@ #include "../AIUtility.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -35,3 +38,5 @@ bool DigAtTile::operator==(const DigAtTile & other) const // // return sptr(VisitTile(tile)); //} + +} diff --git a/AI/Nullkiller/Goals/DigAtTile.h b/AI/Nullkiller/Goals/DigAtTile.h index 21af09404..b50708c9b 100644 --- a/AI/Nullkiller/Goals/DigAtTile.h +++ b/AI/Nullkiller/Goals/DigAtTile.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -36,3 +39,5 @@ namespace Goals //TSubgoal decomposeSingle() const override; }; } + +} diff --git a/AI/Nullkiller/Goals/DismissHero.cpp b/AI/Nullkiller/Goals/DismissHero.cpp index d84e79ca5..09d5ceab5 100644 --- a/AI/Nullkiller/Goals/DismissHero.cpp +++ b/AI/Nullkiller/Goals/DismissHero.cpp @@ -13,6 +13,9 @@ #include "../../../lib/mapping/CMap.h" //for victory conditions #include "../../../lib/CPathfinder.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -37,3 +40,5 @@ std::string DismissHero::toString() const { return "DismissHero " + hero.name; } + +} diff --git a/AI/Nullkiller/Goals/DismissHero.h b/AI/Nullkiller/Goals/DismissHero.h index 7437875e8..a6d180300 100644 --- a/AI/Nullkiller/Goals/DismissHero.h +++ b/AI/Nullkiller/Goals/DismissHero.h @@ -11,6 +11,8 @@ #include "CGoal.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT DismissHero : public ElementarGoal @@ -27,3 +29,5 @@ namespace Goals virtual bool operator==(const DismissHero & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp index 0b570d975..ff7ac5245 100644 --- a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp +++ b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.cpp @@ -15,6 +15,9 @@ #include "../../../lib/CPathfinder.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -89,4 +92,6 @@ void ExchangeSwapTownHeroes::accept(AIGateway * ai) } logAi->debug("Put hero %s to garrison of %s", garrisonHero->name, town->name); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h index 00e4e1f83..aad61d77e 100644 --- a/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h +++ b/AI/Nullkiller/Goals/ExchangeSwapTownHeroes.h @@ -12,6 +12,8 @@ #include "CGoal.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT ExchangeSwapTownHeroes : public ElementarGoal @@ -32,3 +34,5 @@ namespace Goals virtual bool operator==(const ExchangeSwapTownHeroes & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp index 3d19bdc49..18fc224ee 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp @@ -14,6 +14,9 @@ #include "../../../lib/CPathfinder.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -197,4 +200,6 @@ bool ExecuteHeroChain::moveHeroToTile(const CGHeroInstance * hero, const int3 & } return ai->moveHeroToTile(tile, hero); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.h b/AI/Nullkiller/Goals/ExecuteHeroChain.h index 7aaf20ad3..b22e18499 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.h +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.h @@ -12,6 +12,8 @@ #include "CGoal.h" #include "../Pathfinding/AIPathfinder.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT ExecuteHeroChain : public ElementarGoal @@ -37,3 +39,5 @@ namespace Goals bool moveHeroToTile(const CGHeroInstance * hero, const int3 & tile); }; } + +} diff --git a/AI/Nullkiller/Goals/GatherArmy.cpp b/AI/Nullkiller/Goals/GatherArmy.cpp index 82e9f361a..ce4d146ca 100644 --- a/AI/Nullkiller/Goals/GatherArmy.cpp +++ b/AI/Nullkiller/Goals/GatherArmy.cpp @@ -1,3 +1,6 @@ +namespace Nullkiller +{ + /* * GatherArmy.cpp, part of VCMI engine * @@ -208,3 +211,5 @@ TGoalVec GatherArmy::getAllPossibleSubgoals() return ret; } + +} diff --git a/AI/Nullkiller/Goals/GatherArmy.h b/AI/Nullkiller/Goals/GatherArmy.h index d48e03e87..9dbb81ec3 100644 --- a/AI/Nullkiller/Goals/GatherArmy.h +++ b/AI/Nullkiller/Goals/GatherArmy.h @@ -1,3 +1,6 @@ +namespace Nullkiller +{ + /* * GatherArmy.h, part of VCMI engine * @@ -36,3 +39,5 @@ namespace Goals virtual bool operator==(const GatherArmy & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/Goals.h b/AI/Nullkiller/Goals/Goals.h index 02e4b733b..e7b857ccf 100644 --- a/AI/Nullkiller/Goals/Goals.h +++ b/AI/Nullkiller/Goals/Goals.h @@ -17,4 +17,4 @@ #include "Trade.h" #include "RecruitHero.h" #include "DigAtTile.h" -#include "AdventureSpellCast.h" \ No newline at end of file +#include "AdventureSpellCast.h" diff --git a/AI/Nullkiller/Goals/Invalid.h b/AI/Nullkiller/Goals/Invalid.h index 62326d387..6c2d7afa4 100644 --- a/AI/Nullkiller/Goals/Invalid.h +++ b/AI/Nullkiller/Goals/Invalid.h @@ -11,9 +11,42 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; namespace Goals { + class DLL_EXPORT Invalid : public ElementarGoal + { + public: + Invalid() + : ElementarGoal(Goals::INVALID) + { + priority = -1; + } + TGoalVec decompose() const override + { + return TGoalVec(); + } + + virtual bool operator==(const Invalid & other) const override + { + return true; + } + + virtual std::string toString() const override + { + return "Invalid"; + } + + virtual void accept(AIGateway * ai) override + { + throw cannotFulfillGoalException("Can not fulfill Invalid goal!"); + } + }; +} + } diff --git a/AI/Nullkiller/Goals/RecruitHero.cpp b/AI/Nullkiller/Goals/RecruitHero.cpp index d6b2450aa..361daedc4 100644 --- a/AI/Nullkiller/Goals/RecruitHero.cpp +++ b/AI/Nullkiller/Goals/RecruitHero.cpp @@ -16,6 +16,9 @@ #include "../../../lib/StringConstants.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -42,4 +45,6 @@ void RecruitHero::accept(AIGateway * ai) { throw cannotFulfillGoalException("No town to recruit hero!"); } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/RecruitHero.h b/AI/Nullkiller/Goals/RecruitHero.h index 5f8b98fd7..34a968f33 100644 --- a/AI/Nullkiller/Goals/RecruitHero.h +++ b/AI/Nullkiller/Goals/RecruitHero.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -42,3 +45,5 @@ namespace Goals void accept(AIGateway * ai) override; }; } + +} diff --git a/AI/Nullkiller/Goals/SaveResources.cpp b/AI/Nullkiller/Goals/SaveResources.cpp index d3f216898..42ed04c52 100644 --- a/AI/Nullkiller/Goals/SaveResources.cpp +++ b/AI/Nullkiller/Goals/SaveResources.cpp @@ -14,6 +14,9 @@ #include "../../../lib/CPathfinder.h" #include "../Behaviors/CaptureObjectsBehavior.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -37,3 +40,5 @@ std::string SaveResources::toString() const { return "SaveResources " + resources.toString(); } + +} diff --git a/AI/Nullkiller/Goals/SaveResources.h b/AI/Nullkiller/Goals/SaveResources.h index 26bb9a005..eb0fe3b5b 100644 --- a/AI/Nullkiller/Goals/SaveResources.h +++ b/AI/Nullkiller/Goals/SaveResources.h @@ -11,6 +11,8 @@ #include "CGoal.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT SaveResources : public ElementarGoal @@ -29,3 +31,5 @@ namespace Goals virtual bool operator==(const SaveResources & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/Trade.cpp b/AI/Nullkiller/Goals/Trade.cpp index e97e7c363..cc7175efa 100644 --- a/AI/Nullkiller/Goals/Trade.cpp +++ b/AI/Nullkiller/Goals/Trade.cpp @@ -10,9 +10,13 @@ #include "StdInc.h" #include "Trade.h" +namespace NKAI +{ using namespace Goals; bool Trade::operator==(const Trade & other) const { return resID == other.resID; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Goals/Trade.h b/AI/Nullkiller/Goals/Trade.h index 6109e517f..30c459be3 100644 --- a/AI/Nullkiller/Goals/Trade.h +++ b/AI/Nullkiller/Goals/Trade.h @@ -11,6 +11,9 @@ #include "CGoal.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -34,3 +37,5 @@ namespace Goals virtual bool operator==(const Trade & other) const override; }; } + +} diff --git a/AI/Nullkiller/Goals/Win.cpp b/AI/Nullkiller/Goals/Win.cpp deleted file mode 100644 index 82fc11776..000000000 --- a/AI/Nullkiller/Goals/Win.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* -* Win.cpp, part of VCMI engine -* -* Authors: listed in file AUTHORS in main folder -* -* License: GNU General Public License v2.0 or later -* Full text of license available in license.txt file, in main folder -* -*/ -#include "StdInc.h" -#include "Goals.h" -#include "../AIGateway.h" -#include "../AIUtility.h" -#include "../AIhelper.h" -#include "../FuzzyHelper.h" -#include "../../../lib/mapping/CMap.h" //for victory conditions -#include "../../../lib/CPathfinder.h" -#include "../../../lib/StringConstants.h" - - -extern boost::thread_specific_ptr cb; -extern boost::thread_specific_ptr ai; -extern FuzzyHelper * fh; - -using namespace Goals; - -TSubgoal Win::whatToDoToAchieve() -{ - auto toBool = [=](const EventCondition &) - { - // TODO: proper implementation - // Right now even already fulfilled goals will be included into generated list - // Proper check should test if event condition is already fulfilled - // Easiest way to do this is to call CGameState::checkForVictory but this function should not be - // used on client side or in AI code - return false; - }; - - std::vector goals; - - for(const TriggeredEvent & event : cb->getMapHeader()->triggeredEvents) - { - //TODO: try to eliminate human player(s) using loss conditions that have isHuman element - - if(event.effect.type == EventEffect::VICTORY) - { - boost::range::copy(event.trigger.getFulfillmentCandidates(toBool), std::back_inserter(goals)); - } - } - - //TODO: instead of returning first encountered goal AI should generate list of possible subgoals - for(const EventCondition & goal : goals) - { - switch(goal.condition) - { - case EventCondition::HAVE_ARTIFACT: - return sptr(GetArtOfType(goal.objectType)); - case EventCondition::DESTROY: - { - if(goal.object) - { - auto obj = cb->getObj(goal.object->id); - /*if(obj) - if(obj->getOwner() == ai->playerID) //we can't capture our own object - return sptr(Conquer());*/ - - - return sptr(VisitObj(goal.object->id.getNum())); - } - else - { - // TODO: destroy all objects of type goal.objectType - // This situation represents "kill all creatures" condition from H3 - break; - } - } - case EventCondition::HAVE_BUILDING: - { - // TODO build other buildings apart from Grail - // goal.objectType = buidingID to build - // goal.object = optional, town in which building should be built - // Represents "Improve town" condition from H3 (but unlike H3 it consists from 2 separate conditions) - - if(goal.objectType == BuildingID::GRAIL) - { - if(auto h = ai->getHeroWithGrail()) - { - //hero is in a town that can host Grail - if(h->visitedTown && !vstd::contains(h->visitedTown->forbiddenBuildings, BuildingID::GRAIL)) - { - const CGTownInstance * t = h->visitedTown; - return sptr(BuildThis(BuildingID::GRAIL, t).setpriority(10)); - } - else - { - auto towns = cb->getTownsInfo(); - towns.erase(boost::remove_if(towns, - [](const CGTownInstance * t) -> bool - { - return vstd::contains(t->forbiddenBuildings, BuildingID::GRAIL); - }), - towns.end()); - boost::sort(towns, CDistanceSorter(h.get())); - if(towns.size()) - { - return sptr(VisitTile(towns.front()->visitablePos()).sethero(h)); - } - } - } - double ratio = 0; - // maybe make this check a bit more complex? For example: - // 0.75 -> dig randomly within 3 tiles radius - // 0.85 -> radius now 2 tiles - // 0.95 -> 1 tile radius, position is fully known - // AFAIK H3 AI does something like this - int3 grailPos = cb->getGrailPos(&ratio); - if(ratio > 0.99) - { - return sptr(DigAtTile(grailPos)); - } //TODO: use FIND_OBJ - else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID)) //there are unvisited Obelisks - return sptr(VisitObj(obj->id.getNum())); - /*else - return sptr(Explore());*/ - } - break; - } - case EventCondition::CONTROL: - { - if(goal.object) - { - auto objRelations = cb->getPlayerRelations(ai->playerID, goal.object->tempOwner); - - if(objRelations == PlayerRelations::ENEMIES) - { - return sptr(VisitObj(goal.object->id.getNum())); - } - else - { - // TODO: Defance - break; - } - } - else - { - //TODO: control all objects of type "goal.objectType" - // Represents H3 condition "Flag all mines" - break; - } - } - - case EventCondition::HAVE_RESOURCES: - //TODO mines? piles? marketplace? - //save? - return sptr(CollectRes(static_cast(goal.objectType), goal.value)); - case EventCondition::HAVE_CREATURES: - return sptr(GatherTroops(goal.objectType, goal.value)); - case EventCondition::TRANSPORT: - { - //TODO. merge with bring Grail to town? So AI will first dig grail, then transport it using this goal and builds it - // Represents "transport artifact" condition: - // goal.objectType = type of artifact - // goal.object = destination-town where artifact should be transported - break; - } - case EventCondition::STANDARD_WIN: - return sptr(Invalid()); - - // Conditions that likely don't need any implementation - case EventCondition::DAYS_PASSED: - break; // goal.value = number of days for condition to trigger - case EventCondition::DAYS_WITHOUT_TOWN: - break; // goal.value = number of days to trigger this - case EventCondition::IS_HUMAN: - break; // Should be only used in calculation of candidates (see toBool lambda) - case EventCondition::CONST_VALUE: - break; - - case EventCondition::HAVE_0: - case EventCondition::HAVE_BUILDING_0: - case EventCondition::DESTROY_0: - //TODO: support new condition format - return sptr(Invalid()); - default: - assert(0); - } - } - return sptr(Invalid()); -} diff --git a/AI/Nullkiller/Goals/Win.h b/AI/Nullkiller/Goals/Win.h deleted file mode 100644 index df24b7fd4..000000000 --- a/AI/Nullkiller/Goals/Win.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Win.h, part of VCMI engine -* -* Authors: listed in file AUTHORS in main folder -* -* License: GNU General Public License v2.0 or later -* Full text of license available in license.txt file, in main folder -* -*/ -#pragma once - -#include "CGoal.h" - -struct HeroPtr; -class AIGateway; -class FuzzyHelper; - -namespace Goals -{ - class DLL_EXPORT Win : public CGoal - { - public: - Win() - : CGoal(Goals::WIN) - { - priority = 100; - } - TGoalVec getAllPossibleSubgoals() override - { - return TGoalVec(); - } - TSubgoal whatToDoToAchieve() override; - - virtual bool operator==(const Win & other) const override - { - return true; - } - }; -} diff --git a/AI/Nullkiller/Markers/ArmyUpgrade.cpp b/AI/Nullkiller/Markers/ArmyUpgrade.cpp index 8720139e9..7b8165544 100644 --- a/AI/Nullkiller/Markers/ArmyUpgrade.cpp +++ b/AI/Nullkiller/Markers/ArmyUpgrade.cpp @@ -13,6 +13,9 @@ #include "../Engine/Nullkiller.h" #include "../AIUtility.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -33,4 +36,6 @@ bool ArmyUpgrade::operator==(const ArmyUpgrade & other) const std::string ArmyUpgrade::toString() const { return "Army upgrade at " + upgrader->getObjectName() + upgrader->visitablePos().toString(); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/ArmyUpgrade.h b/AI/Nullkiller/Markers/ArmyUpgrade.h index 475abf519..df30c3588 100644 --- a/AI/Nullkiller/Markers/ArmyUpgrade.h +++ b/AI/Nullkiller/Markers/ArmyUpgrade.h @@ -13,6 +13,8 @@ #include "../Pathfinding/AINodeStorage.h" #include "../Analyzers/ArmyManager.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT ArmyUpgrade : public CGoal @@ -32,4 +34,6 @@ namespace Goals uint64_t getUpgradeValue() const { return upgradeValue; } uint64_t getInitialArmyValue() const { return initialValue; } }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/DefendTown.cpp b/AI/Nullkiller/Markers/DefendTown.cpp index 62e50585e..b09952f22 100644 --- a/AI/Nullkiller/Markers/DefendTown.cpp +++ b/AI/Nullkiller/Markers/DefendTown.cpp @@ -13,6 +13,9 @@ #include "../Engine/Nullkiller.h" #include "../AIUtility.h" +namespace NKAI +{ + using namespace Goals; DefendTown::DefendTown(const CGTownInstance * town, const HitMapInfo & treat, const AIPath & defencePath) @@ -37,4 +40,6 @@ bool DefendTown::operator==(const DefendTown & other) const std::string DefendTown::toString() const { return "Defend town " + town->getObjectName(); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/DefendTown.h b/AI/Nullkiller/Markers/DefendTown.h index dac1c9cf2..083f9b07f 100644 --- a/AI/Nullkiller/Markers/DefendTown.h +++ b/AI/Nullkiller/Markers/DefendTown.h @@ -14,6 +14,8 @@ #include "../Analyzers/ArmyManager.h" #include "../Analyzers/DangerHitMapAnalyzer.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT DefendTown : public CGoal @@ -36,4 +38,6 @@ namespace Goals uint8_t getTurn() const { return turn; } }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/HeroExchange.cpp b/AI/Nullkiller/Markers/HeroExchange.cpp index e673ce0b4..562215bb3 100644 --- a/AI/Nullkiller/Markers/HeroExchange.cpp +++ b/AI/Nullkiller/Markers/HeroExchange.cpp @@ -14,6 +14,9 @@ #include "../AIUtility.h" #include "../Analyzers/ArmyManager.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -34,4 +37,6 @@ uint64_t HeroExchange::getReinforcementArmyStrength() const uint64_t armyValue = ai->nullkiller->armyManager->howManyReinforcementsCanGet(hero.get(), exchangePath.heroArmy); return armyValue; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/HeroExchange.h b/AI/Nullkiller/Markers/HeroExchange.h index 20942d6a0..532d62666 100644 --- a/AI/Nullkiller/Markers/HeroExchange.h +++ b/AI/Nullkiller/Markers/HeroExchange.h @@ -12,6 +12,8 @@ #include "../Goals/CGoal.h" #include "../Pathfinding/AINodeStorage.h" +namespace NKAI +{ namespace Goals { class DLL_EXPORT HeroExchange : public CGoal @@ -31,4 +33,6 @@ namespace Goals uint64_t getReinforcementArmyStrength() const; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/UnlockCluster.cpp b/AI/Nullkiller/Markers/UnlockCluster.cpp index ef24095f3..bbf7c99c7 100644 --- a/AI/Nullkiller/Markers/UnlockCluster.cpp +++ b/AI/Nullkiller/Markers/UnlockCluster.cpp @@ -13,6 +13,9 @@ #include "../Engine/Nullkiller.h" #include "../AIUtility.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -26,4 +29,6 @@ bool UnlockCluster::operator==(const UnlockCluster & other) const std::string UnlockCluster::toString() const { return "Unlock Cluster " + cluster->blocker->getObjectName() + tile.toString(); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Markers/UnlockCluster.h b/AI/Nullkiller/Markers/UnlockCluster.h index 3e40ab850..3318fc7bc 100644 --- a/AI/Nullkiller/Markers/UnlockCluster.h +++ b/AI/Nullkiller/Markers/UnlockCluster.h @@ -13,6 +13,9 @@ #include "../Analyzers/ObjectClusterizer.h" +namespace NKAI +{ + struct HeroPtr; class AIGateway; class FuzzyHelper; @@ -38,4 +41,6 @@ namespace Goals std::shared_ptr getCluster() const { return cluster; } const AIPath & getPathToCenter() { return pathToCenter; } }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index b62e047cb..763ec2894 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -19,6 +19,9 @@ #include "../../../lib/PathfinderUtil.h" #include "../../../lib/CPlayerState.h" +namespace NKAI +{ + std::shared_ptr> AISharedStorage::shared; std::set commitedTiles; std::set commitedTilesInitial; @@ -261,7 +264,7 @@ void AINodeStorage::commit( destination->theNodeBefore = source->theNodeBefore; destination->chainOther = nullptr; -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Commited %s -> %s, cost: %f, turn: %s, mp: %d, hero: %s, mask: %x, army: %lld", source->coord.toString(), @@ -589,7 +592,7 @@ void HeroChainCalculationTask::cleanupInefectiveChains(std::vector= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 if(isNotEffective) { logAi->trace( @@ -634,7 +637,7 @@ void HeroChainCalculationTask::calculateHeroChain( || (node->action == CGPathNode::ENodeAction::UNKNOWN && node->actor->hero) || (node->actor->chainMask & srcNode->actor->chainMask) != 0) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Skip exchange %s[%x] -> %s[%x] at %s because of %s", node->actor->toString(), @@ -651,7 +654,7 @@ void HeroChainCalculationTask::calculateHeroChain( continue; } -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Thy exchange %s[%x] -> %s[%x] at %s", node->actor->toString(), @@ -675,7 +678,7 @@ void HeroChainCalculationTask::calculateHeroChain( && carrier->action != CGPathNode::BLOCKING_VISIT && (other->armyLoss == 0 || other->armyLoss < other->actor->armyValue)) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Exchange allowed %s[%x] -> %s[%x] at %s", other->actor->toString(), @@ -692,7 +695,7 @@ void HeroChainCalculationTask::calculateHeroChain( if(hasLessMp && hasLessExperience) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace("Exchange at %s is ineficient. Blocked.", carrier->coord.toString()); #endif return; @@ -717,7 +720,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector if(!chainNodeOptional) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace("Exchange at %s can not allocate node. Blocked.", carrier->coord.toString()); #endif continue; @@ -727,7 +730,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector if(exchangeNode->action != CGPathNode::ENodeAction::UNKNOWN) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Skip exchange %s[%x] -> %s[%x] at %s because node is in use", other->actor->toString(), @@ -741,7 +744,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector if(exchangeNode->turns != 0xFF && exchangeNode->getCost() < chainInfo.getCost()) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Skip exchange %s[%x] -> %s[%x] at %s because not effective enough. %f < %f", other->actor->toString(), @@ -772,7 +775,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector exchangeNode->chainOther = other; exchangeNode->armyLoss = chainInfo.armyLoss; -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Chain accepted at %s %s -> %s, mask %x, cost %f, turn: %s, mp: %d, army %i", exchangeNode->coord.toString(), @@ -1096,7 +1099,7 @@ void AINodeStorage::calculateTownPortal( if(nodeOptional) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace("Adding town portal node at %s", targetTown->name); #endif output.push_back(nodeOptional.get()); @@ -1180,7 +1183,7 @@ bool AINodeStorage::hasBetterChain( { if(node.getCost() < candidateNode->getCost()) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Block ineficient battle move %s->%s, hero: %s[%X], army %lld, mp diff: %i", source->coord.toString(), @@ -1204,7 +1207,7 @@ bool AINodeStorage::hasBetterChain( if(nodeArmyValue > candidateArmyValue && node.getCost() <= candidateNode->getCost()) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Block ineficient move because of stronger army %s->%s, hero: %s[%X], army %lld, mp diff: %i", source->coord.toString(), @@ -1230,7 +1233,7 @@ bool AINodeStorage::hasBetterChain( continue; } -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Block ineficient move because of stronger hero %s->%s, hero: %s[%X], army %lld, mp diff: %i", source->coord.toString(), @@ -1452,3 +1455,5 @@ std::string AIPath::toString() const return str.str(); } + +} diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.h b/AI/Nullkiller/Pathfinding/AINodeStorage.h index 075a90d32..008bff677 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.h +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.h @@ -10,10 +10,8 @@ #pragma once -#define PATHFINDER_TRACE_LEVEL 0 -#define AI_TRACE_LEVEL 0 -#define SCOUT_TURN_DISTANCE_LIMIT 3 -#define MAIN_TURN_DISTANCE_LIMIT 5 +#define NKAI_PATHFINDER_TRACE_LEVEL 0 +#define NKAI_TRACE_LEVEL 0 #include "../../../lib/CPathfinder.h" #include "../../../lib/mapObjects/CGHeroInstance.h" @@ -23,6 +21,11 @@ #include "Actions/SpecialAction.h" #include "Actors.h" +namespace NKAI +{ + const int SCOUT_TURN_DISTANCE_LIMIT = 3; + const int MAIN_TURN_DISTANCE_LIMIT = 5; + namespace AIPathfinding { #ifdef ENVIRONMENT64 @@ -256,3 +259,5 @@ private: const std::vector & initialNodes, TVector & output); }; + +} diff --git a/AI/Nullkiller/Pathfinding/AIPathfinder.cpp b/AI/Nullkiller/Pathfinding/AIPathfinder.cpp index 4b51369e1..87eb5fb79 100644 --- a/AI/Nullkiller/Pathfinding/AIPathfinder.cpp +++ b/AI/Nullkiller/Pathfinding/AIPathfinder.cpp @@ -14,6 +14,9 @@ #include "../../../lib/mapping/CMap.h" #include "../Engine/Nullkiller.h" +namespace NKAI +{ + AIPathfinder::AIPathfinder(CPlayerSpecificInfoCallback * cb, Nullkiller * ai) :cb(cb), ai(ai) { @@ -99,3 +102,5 @@ void AIPathfinder::updatePaths(std::map heroes logAi->trace("Recalculated paths in %ld", timeElapsed(start)); } + +} diff --git a/AI/Nullkiller/Pathfinding/AIPathfinder.h b/AI/Nullkiller/Pathfinding/AIPathfinder.h index 8f9389403..eb7b92f44 100644 --- a/AI/Nullkiller/Pathfinding/AIPathfinder.h +++ b/AI/Nullkiller/Pathfinding/AIPathfinder.h @@ -13,6 +13,9 @@ #include "AINodeStorage.h" #include "../AIUtility.h" +namespace NKAI +{ + class Nullkiller; struct PathfinderSettings @@ -42,3 +45,5 @@ public: void updatePaths(std::map heroes, PathfinderSettings pathfinderSettings); void init(); }; + +} diff --git a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp index c34a05d05..0f1be5087 100644 --- a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp +++ b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp @@ -15,6 +15,8 @@ #include "Rules/AIPreviousNodeRule.h" #include "../Engine//Nullkiller.h" +namespace NKAI +{ namespace AIPathfinding { std::vector> makeRuleset( @@ -55,3 +57,5 @@ namespace AIPathfinding return helper.get(); } } + +} diff --git a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.h b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.h index 0b196e7a2..05e6f5558 100644 --- a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.h +++ b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.h @@ -12,6 +12,9 @@ #include "AINodeStorage.h" +namespace NKAI +{ + class Nullkiller; namespace AIPathfinding @@ -31,3 +34,5 @@ namespace AIPathfinding virtual CPathfinderHelper * getOrCreatePathfinderHelper(const PathNodeInfo & source, CGameState * gs) override; }; } + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp b/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp index fcfc0fac2..70a4b1063 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BattleAction.cpp @@ -14,6 +14,9 @@ #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -28,4 +31,6 @@ namespace AIPathfinding { return "Battle at " + targetTile.toString(); } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BattleAction.h b/AI/Nullkiller/Pathfinding/Actions/BattleAction.h index 0a6b608b2..918b5974e 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BattleAction.h +++ b/AI/Nullkiller/Pathfinding/Actions/BattleAction.h @@ -13,6 +13,9 @@ #include "SpecialAction.h" #include "../../../../lib/CGameState.h" +namespace NKAI +{ + namespace AIPathfinding { class BattleAction : public SpecialAction @@ -30,4 +33,6 @@ namespace AIPathfinding virtual std::string toString() const override; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp index 39aec27a2..214c0d366 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp @@ -12,11 +12,15 @@ #include "../../AIGateway.h" #include "../../Goals/AdventureSpellCast.h" #include "../../Goals/CaptureObject.h" +#include "../../Goals/Invalid.h" #include "../../Goals/BuildBoat.h" #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" #include "BoatActions.h" +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -34,7 +38,7 @@ namespace AIPathfinding return Goals::sptr(Goals::CaptureObject(shipyard->o)); } - return sptr(Goals::Invalid()); + return Goals::sptr(Goals::Invalid()); } bool BuildBoatAction::canAct(const AIPathNode * source) const @@ -43,7 +47,7 @@ namespace AIPathfinding if(cb->getPlayerRelations(hero->tempOwner, shipyard->o->tempOwner) == PlayerRelations::ENEMIES) { -#if AI_TRACE_LEVEL > 1 +#if NKAI_TRACE_LEVEL > 1 logAi->trace("Can not build a boat. Shipyard is enemy."); #endif return false; @@ -55,7 +59,7 @@ namespace AIPathfinding if(!cb->getResourceAmount().canAfford(source->actor->armyCost + boatCost)) { -#if AI_TRACE_LEVEL > 1 +#if NKAI_TRACE_LEVEL > 1 logAi->trace("Can not build a boat. Not enough resources."); #endif @@ -128,4 +132,6 @@ namespace AIPathfinding return hero->getSpellCost(summonBoat.toSpell()); } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BoatActions.h b/AI/Nullkiller/Pathfinding/Actions/BoatActions.h index 4b2812b21..a1634b09b 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BoatActions.h +++ b/AI/Nullkiller/Pathfinding/Actions/BoatActions.h @@ -14,6 +14,9 @@ #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ + namespace AIPathfinding { class VirtualBoatAction : public SpecialAction @@ -69,3 +72,5 @@ namespace AIPathfinding virtual const CGObjectInstance * targetObject() const override; }; } + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp index 338a8b918..3a15f7e4c 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp @@ -14,6 +14,9 @@ #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -34,4 +37,6 @@ namespace AIPathfinding { return "Buy Army"; } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h index d609b9db2..89294aecf 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h +++ b/AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h @@ -13,6 +13,8 @@ #include "SpecialAction.h" #include "../../../../lib/CGameState.h" +namespace NKAI +{ namespace AIPathfinding { class BuyArmyAction : public SpecialAction @@ -28,4 +30,6 @@ namespace AIPathfinding void execute(const CGHeroInstance * hero) const override; std::string toString() const override; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp index 5249d6396..5deb87e7b 100644 --- a/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp @@ -14,6 +14,9 @@ #include "../../Goals/CompleteQuest.h" #include "../../../../lib/mapping/CMap.h" //for victory conditions +namespace NKAI +{ + extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; @@ -44,4 +47,6 @@ namespace AIPathfinding { return "Complete Quest"; } -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/QuestAction.h b/AI/Nullkiller/Pathfinding/Actions/QuestAction.h index d0c13ee05..ae5ae0490 100644 --- a/AI/Nullkiller/Pathfinding/Actions/QuestAction.h +++ b/AI/Nullkiller/Pathfinding/Actions/QuestAction.h @@ -13,6 +13,8 @@ #include "SpecialAction.h" #include "../../../../lib/CGameState.h" +namespace NKAI +{ namespace AIPathfinding { class QuestAction : public SpecialAction @@ -34,4 +36,6 @@ namespace AIPathfinding virtual std::string toString() const override; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp index 75222ac9e..d85395a8b 100644 --- a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.cpp @@ -12,6 +12,10 @@ #include "SpecialAction.h" #include "../../AIGateway.h" #include "../../Goals/CGoal.h" +#include "../../Goals/Invalid.h" + +namespace NKAI +{ Goals::TSubgoal SpecialAction::decompose(const CGHeroInstance * hero) const { @@ -21,4 +25,6 @@ Goals::TSubgoal SpecialAction::decompose(const CGHeroInstance * hero) const void SpecialAction::execute(const CGHeroInstance * hero) const { throw cannotFulfillGoalException("Can not execute " + toString()); -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.h b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.h index 51977963b..b0d8799ad 100644 --- a/AI/Nullkiller/Pathfinding/Actions/SpecialAction.h +++ b/AI/Nullkiller/Pathfinding/Actions/SpecialAction.h @@ -13,6 +13,9 @@ #include "../../AIUtility.h" #include "../../Goals/AbstractGoal.h" +namespace NKAI +{ + struct AIPathNode; class SpecialAction @@ -42,3 +45,5 @@ public: virtual const CGObjectInstance * targetObject() const { return nullptr; } }; + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp index 889ec1245..30f1ffc6d 100644 --- a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.cpp @@ -14,6 +14,9 @@ #include "../../../../lib/mapObjects/MapObjects.h" #include "TownPortalAction.h" +namespace NKAI +{ + using namespace AIPathfinding; extern boost::thread_specific_ptr cb; @@ -53,4 +56,6 @@ uint32_t TownPortalAction::getManaCost(const CGHeroInstance * hero) const SpellID summonBoat = SpellID::TOWN_PORTAL; return hero->getSpellCost(summonBoat.toSpell()); -}*/ \ No newline at end of file +}*/ + +} diff --git a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.h b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.h index d9dbd3efb..1afc58cb6 100644 --- a/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.h +++ b/AI/Nullkiller/Pathfinding/Actions/TownPortalAction.h @@ -15,6 +15,8 @@ #include "../../../../lib/mapObjects/MapObjects.h" #include "../../Goals/AdventureSpellCast.h" +namespace NKAI +{ namespace AIPathfinding { class TownPortalAction : public SpecialAction @@ -32,4 +34,6 @@ namespace AIPathfinding virtual std::string toString() const override; }; -} \ No newline at end of file +} + +} diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index b5f730a12..dcea063e1 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -16,6 +16,8 @@ #include "../../../lib/mapObjects/MapObjects.h" #include "Actions/BuyArmyAction.h" +using namespace NKAI; + CCreatureSet emptyArmy; bool HeroExchangeArmy::needsLastStack() const @@ -68,7 +70,7 @@ ChainActor::ChainActor(const CGObjectInstance * obj, const CCreatureSet * creatu int ChainActor::maxMovePoints(CGPathNode::ELayer layer) { -#if AI_TRACE_LEVEL > 0 +#if NKAI_TRACE_LEVEL > 0 if(!hero) throw std::logic_error("Asking movement points for static actor"); #endif @@ -164,25 +166,6 @@ ExchangeResult ChainActor::tryExchangeNoLock(const ChainActor * specialActor, co return baseActor->tryExchangeNoLock(specialActor, other); } -VCMI_LIB_NAMESPACE_BEGIN -namespace vstd -{ - template - typename M::mapped_type & getOrCompute(M &m, Key const& k, F f) - { - typedef typename M::mapped_type V; - - std::pair r = m.insert(typename M::value_type(k, V())); - V &v = r.first->second; - - if(r.second) - f(v); - - return v; - } -} -VCMI_LIB_NAMESPACE_END - ExchangeResult HeroActor::tryExchangeNoLock(const ChainActor * specialActor, const ChainActor * other) const { const ChainActor * otherBase = other->baseActor; @@ -282,7 +265,7 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other) if(!resources.canAfford(actor->armyCost + other->armyCost)) { -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Can not afford exchange because of total cost %s but we have %s", (actor->armyCost + other->armyCost).toString(), @@ -322,7 +305,7 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other) auto reinforcement = newArmy->getArmyStrength() - actor->creatureSet->getArmyStrength(); -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Exchange %s->%s reinforcement: %d, %f%%", actor->toString(), diff --git a/AI/Nullkiller/Pathfinding/Actors.h b/AI/Nullkiller/Pathfinding/Actors.h index 2f18df369..cf450dfbc 100644 --- a/AI/Nullkiller/Pathfinding/Actors.h +++ b/AI/Nullkiller/Pathfinding/Actors.h @@ -15,6 +15,9 @@ #include "../AIUtility.h" #include "Actions/SpecialAction.h" +namespace NKAI +{ + extern const uint64_t MIN_ARMY_STRENGTH_FOR_CHAIN; class ChainActor; @@ -170,3 +173,5 @@ public: TownGarrisonActor(const CGTownInstance * town, uint64_t chainMask); virtual std::string toString() const override; }; + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.cpp index 7ce26bee3..f3143a239 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.cpp @@ -11,6 +11,8 @@ #include "AILayerTransitionRule.h" #include "../../Engine/Nullkiller.h" +namespace NKAI +{ namespace AIPathfinding { AILayerTransitionRule::AILayerTransitionRule(CPlayerSpecificInfoCallback * cb, Nullkiller * ai, std::shared_ptr nodeStorage) @@ -38,7 +40,7 @@ namespace AIPathfinding if(virtualBoat && tryEmbarkVirtualBoat(destination, source, virtualBoat)) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace("Embarking to virtual boat while moving %s -> %s!", source.coord.toString(), destination.coord.toString()); #endif } @@ -139,7 +141,7 @@ namespace AIPathfinding } else { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Special transition node already allocated. Blocked moving %s -> %s", source.coord.toString(), @@ -159,3 +161,5 @@ namespace AIPathfinding return result; } } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h index b18da7f7b..dd79f1b53 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AILayerTransitionRule.h @@ -17,6 +17,8 @@ #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ namespace AIPathfinding { class AILayerTransitionRule : public LayerTransitionRule @@ -50,3 +52,5 @@ namespace AIPathfinding std::shared_ptr virtualBoat) const; }; } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp index 225f139ca..45fd896bd 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.cpp @@ -14,6 +14,8 @@ #include "../../Goals/Invalid.h" #include "AIPreviousNodeRule.h" +namespace NKAI +{ namespace AIPathfinding { AIMovementAfterDestinationRule::AIMovementAfterDestinationRule( @@ -45,7 +47,7 @@ namespace AIPathfinding return; } -#if PATHFINDER_TRACE_LEVEL >= 2 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Movement from tile %s is blocked. Try to bypass. Action: %d, blocker: %d", destination.coord.toString(), @@ -220,7 +222,7 @@ namespace AIPathfinding if(guardsAlreadyBypassed && srcNode->actor->allowBattle) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Bypass guard at destination while moving %s -> %s", source.coord.toString(), @@ -248,7 +250,7 @@ namespace AIPathfinding if(!battleNodeOptional) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Can not allocate battle node while moving %s -> %s", source.coord.toString(), @@ -261,7 +263,7 @@ namespace AIPathfinding if(battleNode->locked) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Block bypass guard at destination while moving %s -> %s", source.coord.toString(), @@ -288,7 +290,7 @@ namespace AIPathfinding battleNode->specialAction = std::make_shared(destination.coord); -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Begin bypass guard at destination with danger %s while moving %s -> %s", std::to_string(danger), @@ -301,3 +303,5 @@ namespace AIPathfinding return false; } } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h index c118bdc40..31c0b1449 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementAfterDestinationRule.h @@ -16,6 +16,8 @@ #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ namespace AIPathfinding { class AIMovementAfterDestinationRule : public MovementAfterDestinationRule @@ -66,3 +68,5 @@ namespace AIPathfinding CPathfinderHelper * pathfinderHelper) const; }; } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.cpp index 4e1d10681..5cd4f9376 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.cpp @@ -10,6 +10,8 @@ #include "StdInc.h" #include "AIMovementToDestinationRule.h" +namespace NKAI +{ namespace AIPathfinding { AIMovementToDestinationRule::AIMovementToDestinationRule(std::shared_ptr nodeStorage) @@ -37,7 +39,7 @@ namespace AIPathfinding if(blocker == BlockingReason::SOURCE_GUARDED && nodeStorage->getAINode(source.node)->actor->allowBattle) { -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Bypass src guard while moving from %s to %s", source.coord.toString(), @@ -49,3 +51,5 @@ namespace AIPathfinding destination.blocked = true; } } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h index 4d0da1b49..1ae5ff862 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIMovementToDestinationRule.h @@ -16,6 +16,8 @@ #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ namespace AIPathfinding { class AIMovementToDestinationRule : public MovementToDestinationRule @@ -33,3 +35,5 @@ namespace AIPathfinding CPathfinderHelper * pathfinderHelper) const override; }; } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.cpp b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.cpp index a46b6558e..975f37c2d 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.cpp +++ b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.cpp @@ -10,6 +10,8 @@ #include "StdInc.h" #include "AIPreviousNodeRule.h" +namespace NKAI +{ namespace AIPathfinding { AIPreviousNodeRule::AIPreviousNodeRule(std::shared_ptr nodeStorage) @@ -35,7 +37,7 @@ namespace AIPathfinding // we can not directly bypass objects, we need to interact with them first destination.node->theNodeBefore = source.node; -#if PATHFINDER_TRACE_LEVEL >= 1 +#if NKAI_PATHFINDER_TRACE_LEVEL >= 1 logAi->trace( "Link src node %s to destination node %s while bypassing visitable obj", source.coord.toString(), @@ -45,3 +47,5 @@ namespace AIPathfinding } } } + +} diff --git a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h index d3847c862..c337827e7 100644 --- a/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h +++ b/AI/Nullkiller/Pathfinding/Rules/AIPreviousNodeRule.h @@ -16,6 +16,8 @@ #include "../../../../lib/mapping/CMap.h" #include "../../../../lib/mapObjects/MapObjects.h" +namespace NKAI +{ namespace AIPathfinding { class AIPreviousNodeRule : public MovementToDestinationRule @@ -33,3 +35,5 @@ namespace AIPathfinding CPathfinderHelper * pathfinderHelper) const override; }; } + +} diff --git a/AI/Nullkiller/main.cpp b/AI/Nullkiller/main.cpp index a6a95ef24..fff944c8d 100644 --- a/AI/Nullkiller/main.cpp +++ b/AI/Nullkiller/main.cpp @@ -28,5 +28,5 @@ extern "C" DLL_EXPORT void GetAiName(char * name) extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr & out) { - out = std::make_shared(); + out = std::make_shared(); } diff --git a/Global.h b/Global.h index 80776b24f..0270d6942 100644 --- a/Global.h +++ b/Global.h @@ -746,6 +746,20 @@ namespace vstd return false; } + template + typename M::mapped_type & getOrCompute(M & m, Key const & k, F f) + { + typedef typename M::mapped_type V; + + std::pair r = m.insert(typename M::value_type(k, V())); + V & v = r.first->second; + + if(r.second) + f(v); + + return v; + } + using boost::math::round; } using vstd::operator-=;