diff --git a/lib/rmg/CRmgTemplate.cpp b/lib/rmg/CRmgTemplate.cpp index 47cf5c38b..eaf4c5060 100644 --- a/lib/rmg/CRmgTemplate.cpp +++ b/lib/rmg/CRmgTemplate.cpp @@ -672,28 +672,64 @@ void CRmgTemplate::serializeJson(JsonSerializeFormat & handler) afterLoad(); } +std::set CRmgTemplate::inheritTerrainType(std::shared_ptr zone, uint32_t iteration /* = 0 */) +{ + if (iteration >= 50) + { + logGlobal->error("Infinite recursion for terrain types detected in template %s", name); + return std::set(); + } + if (zone->getTerrainTypeLikeZone() != ZoneOptions::NO_ZONE) + { + iteration++; + const auto otherZone = zones.at(zone->getTerrainTypeLikeZone()); + zone->setTerrainTypes(inheritTerrainType(otherZone, iteration)); + } + return zone->getTerrainTypes(); +} + +std::map CRmgTemplate::inheritMineTypes(std::shared_ptr zone, uint32_t iteration /* = 0 */) +{ + if (iteration >= 50) + { + logGlobal->error("Infinite recursion for mine types detected in template %s", name); + return std::map(); + } + if (zone->getMinesLikeZone() != ZoneOptions::NO_ZONE) + { + iteration++; + const auto otherZone = zones.at(zone->getMinesLikeZone()); + zone->setMinesInfo(inheritMineTypes(otherZone, iteration)); + } + return zone->getMinesInfo(); +} + +std::vector CRmgTemplate::inheritTreasureInfo(std::shared_ptr zone, uint32_t iteration /* = 0 */) +{ + if (iteration >= 50) + { + logGlobal->error("Infinite recursion for treasures detected in template %s", name); + return std::vector(); + } + if (zone->getTreasureLikeZone() != ZoneOptions::NO_ZONE) + { + iteration++; + const auto otherZone = zones.at(zone->getTreasureLikeZone()); + zone->setTreasureInfo(inheritTreasureInfo(otherZone, iteration)); + } + return zone->getTreasureInfo(); +} + void CRmgTemplate::afterLoad() { for(auto & idAndZone : zones) { auto zone = idAndZone.second; - if(zone->getMinesLikeZone() != ZoneOptions::NO_ZONE) - { - const auto otherZone = zones.at(zone->getMinesLikeZone()); - zone->setMinesInfo(otherZone->getMinesInfo()); - } - if(zone->getTerrainTypeLikeZone() != ZoneOptions::NO_ZONE) - { - const auto otherZone = zones.at(zone->getTerrainTypeLikeZone()); - zone->setTerrainTypes(otherZone->getTerrainTypes()); - } - - if(zone->getTreasureLikeZone() != ZoneOptions::NO_ZONE) - { - const auto otherZone = zones.at(zone->getTreasureLikeZone()); - zone->setTreasureInfo(otherZone->getTreasureInfo()); - } + //Inherit properties recursively. + inheritTerrainType(zone); + inheritMineTypes(zone); + inheritTreasureInfo(zone); } for(const auto & connection : connections) diff --git a/lib/rmg/CRmgTemplate.h b/lib/rmg/CRmgTemplate.h index 0c087eb8d..67caf9ca7 100644 --- a/lib/rmg/CRmgTemplate.h +++ b/lib/rmg/CRmgTemplate.h @@ -238,6 +238,9 @@ private: std::set allowedWaterContent; void afterLoad(); + std::set inheritTerrainType(std::shared_ptr zone, size_t iteration = 0); + std::map inheritMineTypes(std::shared_ptr zone, size_t iteration = 0); + std::vector inheritTreasureInfo(std::shared_ptr zone, size_t iteration = 0); void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName); void serializePlayers(JsonSerializeFormat & handler, CPlayerCountRange & value, const std::string & fieldName); };