diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 32db2ec97..3f973f138 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -106,6 +106,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/rmg/ObjectDistributor.cpp ${MAIN_LIB_DIR}/rmg/RoadPlacer.cpp ${MAIN_LIB_DIR}/rmg/TreasurePlacer.cpp + ${MAIN_LIB_DIR}/rmg/QuestArtifactPlacer.cpp ${MAIN_LIB_DIR}/rmg/RmgMap.cpp ${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.cpp ${MAIN_LIB_DIR}/rmg/WaterAdopter.cpp @@ -371,6 +372,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/rmg/ObjectDistributor.h ${MAIN_LIB_DIR}/rmg/RoadPlacer.h ${MAIN_LIB_DIR}/rmg/TreasurePlacer.h + ${MAIN_LIB_DIR}/rmg/QuestArtifactPlacer.h ${MAIN_LIB_DIR}/rmg/RmgMap.h ${MAIN_LIB_DIR}/rmg/ConnectionsPlacer.h ${MAIN_LIB_DIR}/rmg/WaterAdopter.h diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index d71d2bb7c..729933bf7 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -37,6 +37,7 @@ CMapGenerator::CMapGenerator(CMapGenOptions& mapGenOptions, int RandomSeed) : rand.setSeed(this->randomSeed); mapGenOptions.finalize(rand); map = std::make_unique(mapGenOptions); + placer = std::make_shared(*map); } int CMapGenerator::getRandomSeed() const @@ -109,6 +110,7 @@ void CMapGenerator::initPrisonsRemaining() void CMapGenerator::initQuestArtsRemaining() { + //TODO: Move to QuestArtifactPlacer? for (auto art : VLC->arth->objects) { if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->constituentOf.empty()) //don't use parts of combined artifacts @@ -267,14 +269,13 @@ void CMapGenerator::addPlayerInfo() void CMapGenerator::genZones() { - CZonePlacer placer(*map); - placer.placeZones(&rand); - placer.assignZones(&rand); + placer->placeZones(&rand); + placer->assignZones(&rand); logGlobal->info("Zones generated successfully"); } -void CMapGenerator::createWaterTreasures() +void CMapGenerator::addWaterTreasuresInfo() { if (!getZoneWater()) return; @@ -288,8 +289,7 @@ void CMapGenerator::createWaterTreasures() void CMapGenerator::fillZones() { - findZonesForQuestArts(); - createWaterTreasures(); + addWaterTreasuresInfo(); logGlobal->info("Started filling zones"); @@ -331,28 +331,6 @@ void CMapGenerator::fillZones() Load::Progress::set(250); } -void CMapGenerator::findZonesForQuestArts() -{ - //we want to place arties in zones that were not yet filled (higher index) - - for (auto connection : mapGenOptions.getMapTemplate()->getConnections()) - { - auto zoneA = map->getZones()[connection.getZoneA()]; - auto zoneB = map->getZones()[connection.getZoneB()]; - - if (zoneA->getId() > zoneB->getId()) - { - if(auto * m = zoneB->getModificator()) - m->setQuestArtZone(zoneA.get()); - } - else if (zoneA->getId() < zoneB->getId()) - { - if(auto * m = zoneA->getModificator()) - m->setQuestArtZone(zoneB.get()); - } - } -} - void CMapGenerator::addHeaderInfo() { map->map().version = EMapFormat::VCMI; @@ -392,6 +370,11 @@ int CMapGenerator::getPrisonsRemaning() const return prisonsRemaining; } +std::shared_ptr CMapGenerator::getZonePlacer() const +{ + return placer; +} + void CMapGenerator::decreasePrisonsRemaining() { prisonsRemaining = std::max (0, prisonsRemaining - 1); diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index 162aeb406..c4e7d4145 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -25,6 +25,7 @@ class JsonNode; class RmgMap; class CMap; class Zone; +class CZonePlacer; typedef std::vector JsonVector; @@ -59,16 +60,15 @@ public: std::unique_ptr generate(); - void findZonesForQuestArts(); - int getNextMonlithIndex(); int getPrisonsRemaning() const; + std::shared_ptr getZonePlacer() const; void decreasePrisonsRemaining(); const std::vector & getQuestArtsRemaning() const; void banQuestArt(const ArtifactID & id); Zone * getZoneWater() const; - void createWaterTreasures(); + void addWaterTreasuresInfo(); int getRandomSeed() const; @@ -77,6 +77,7 @@ private: CMapGenOptions& mapGenOptions; Config config; std::unique_ptr map; + std::shared_ptr placer; std::vector connectionsLeft; @@ -85,7 +86,7 @@ private: int prisonsRemaining; //int questArtsRemaining; int monolithIndex; - std::vector questArtifacts; + std::vector questArtifacts; //TODO: Protect with mutex /// Generation methods void loadConfig(); diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index 3b60ca650..3705552d2 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -869,4 +869,9 @@ void CZonePlacer::assignZones(CRandomGenerator * rand) logGlobal->info("Finished zone colouring"); } +const TDistanceMap& CZonePlacer::getDistanceMap() +{ + return distancesBetweenZones; +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/CZonePlacer.h b/lib/rmg/CZonePlacer.h index 34e24f6f9..28c195509 100644 --- a/lib/rmg/CZonePlacer.h +++ b/lib/rmg/CZonePlacer.h @@ -26,6 +26,7 @@ typedef std::vector>> TZoneV typedef std::map> TZoneMap; typedef std::map, float3> TForceVector; typedef std::map, float> TDistanceVector; +typedef std::map> TDistanceMap; class CZonePlacer { @@ -40,6 +41,8 @@ public: void findPathsBetweenZones(); void placeOnGrid(CRandomGenerator* rand); void assignZones(CRandomGenerator * rand); + + const TDistanceMap & getDistanceMap(); private: void prepareZones(TZoneMap &zones, TZoneVector &zonesVector, const bool underground, CRandomGenerator * rand); @@ -65,7 +68,7 @@ private: float bestTotalOverlap; //distance [a][b] = number of zone connections required to travel between the zones - std::map> distancesBetweenZones; + TDistanceMap distancesBetweenZones; std::set lastSwappedZones; RmgMap & map; }; diff --git a/lib/rmg/ObjectManager.cpp b/lib/rmg/ObjectManager.cpp index 74841d9a9..18cda16be 100644 --- a/lib/rmg/ObjectManager.cpp +++ b/lib/rmg/ObjectManager.cpp @@ -16,6 +16,8 @@ #include "RoadPlacer.h" #include "RiverPlacer.h" #include "WaterAdopter.h" +#include "TreasurePlacer.h" +#include "QuestArtifactPlacer.h" #include "../CCreatureHandler.h" #include "../mapObjects/CommonConstructors.h" #include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h @@ -379,6 +381,21 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD m->areaIsolated().add(instance->getVisitablePosition() + int3(0, -1, 0)); } } + + switch (instance->object().ID) + { + case Obj::RANDOM_TREASURE_ART: + case Obj::RANDOM_MINOR_ART: //In OH3 quest artifacts have higher value than normal arts + { + if (auto * qap = zone.getModificator()) + { + qap->rememberPotentialArtifactToReplace(&instance->object()); + } + break; + } + default: + break; + } } switch(object.instances().front()->object().ID) diff --git a/lib/rmg/RmgMap.cpp b/lib/rmg/RmgMap.cpp index f488d2a8e..313b202dc 100644 --- a/lib/rmg/RmgMap.cpp +++ b/lib/rmg/RmgMap.cpp @@ -19,6 +19,7 @@ #include "ObjectManager.h" #include "RoadPlacer.h" #include "TreasurePlacer.h" +#include "QuestArtifactPlacer.h" #include "ConnectionsPlacer.h" #include "TownPlacer.h" #include "MinePlacer.h" @@ -139,6 +140,7 @@ void RmgMap::addModificators() { zone->addModificator(); zone->addModificator(); + zone->addModificator(); zone->addModificator(); zone->addModificator(); zone->addModificator(); diff --git a/lib/rmg/TreasurePlacer.cpp b/lib/rmg/TreasurePlacer.cpp index 87b767f33..5428f370a 100644 --- a/lib/rmg/TreasurePlacer.cpp +++ b/lib/rmg/TreasurePlacer.cpp @@ -17,6 +17,8 @@ #include "ConnectionsPlacer.h" #include "RmgMap.h" #include "TileInfo.h" +#include "CZonePlacer.h" +#include "QuestArtifactPlacer.h" #include "../mapObjects/CommonConstructors.h" #include "../mapObjects/MapObjects.h" //needed to resolve templates for CommonConstructors.h #include "../CCreatureHandler.h" @@ -41,11 +43,6 @@ void TreasurePlacer::init() POSTFUNCTION(RoadPlacer); } -void TreasurePlacer::setQuestArtZone(Zone * otherZone) -{ - questArtZone = otherZone; -} - void TreasurePlacer::addObjectToRandomPool(const ObjectInfo& oi) { possibleObjects.push_back(oi); @@ -389,8 +386,8 @@ void TreasurePlacer::addAllPossibleObjects() addObjectToRandomPool(oi); //seer huts with creatures or generic rewards - - if(questArtZone) //we won't be placing seer huts if there is no zone left to place arties + + if(zone.getConnections().size()) //Unlikely, but... { static const int genericSeerHuts = 8; int seerHutsPerType = 0; @@ -450,9 +447,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; generator.banQuestArt(artid); - - - this->questArtZone->getModificator()->addObjectToRandomPool(generateArtInfo(artid)); + zone.getModificator()->addQuestArtifact(artid); return obj; }; @@ -487,8 +482,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; generator.banQuestArt(artid); - - this->questArtZone->getModificator()->addObjectToRandomPool(generateArtInfo(artid)); + zone.getModificator()->addQuestArtifact(artid); return obj; }; @@ -510,8 +504,7 @@ void TreasurePlacer::addAllPossibleObjects() obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false; generator.banQuestArt(artid); - - this->questArtZone->getModificator()->addObjectToRandomPool(generateArtInfo(artid)); + zone.getModificator()->addQuestArtifact(artid); return obj; }; diff --git a/lib/rmg/TreasurePlacer.h b/lib/rmg/TreasurePlacer.h index 03968e308..859576412 100644 --- a/lib/rmg/TreasurePlacer.h +++ b/lib/rmg/TreasurePlacer.h @@ -1,5 +1,5 @@ /* - * TreasurePlacer.cpp, part of VCMI engine + * TreasurePlacer.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * @@ -18,6 +18,7 @@ class CGObjectInstance; class ObjectManager; class RmgMap; class CMapGenerator; +class CRandomGenerator; struct ObjectInfo { @@ -43,8 +44,6 @@ public: char dump(const int3 &) override; void createTreasures(ObjectManager & manager); - - void setQuestArtZone(Zone * otherZone); void addObjectToRandomPool(const ObjectInfo& oi); void addAllPossibleObjects(); //add objects, including zone-specific, to possibleObjects @@ -56,8 +55,7 @@ protected: ObjectInfo * getRandomObject(ui32 desiredValue, ui32 currentValue, ui32 maxValue, bool allowLargeObjects); std::vector prepareTreasurePile(const CTreasureInfo & treasureInfo); rmg::Object constructTreasurePile(const std::vector & treasureInfos, bool densePlacement = false); - - + protected: std::vector possibleObjects; int minGuardedValue = 0; @@ -65,8 +63,6 @@ protected: rmg::Area treasureArea; rmg::Area treasureBlockArea; rmg::Area guards; - - Zone * questArtZone = nullptr; //artifacts required for Seer Huts will be placed here - or not if null }; VCMI_LIB_NAMESPACE_END diff --git a/lib/rmg/Zone.cpp b/lib/rmg/Zone.cpp index 3e27363d0..91d0a9d15 100644 --- a/lib/rmg/Zone.cpp +++ b/lib/rmg/Zone.cpp @@ -95,6 +95,11 @@ rmg::Area & Zone::areaUsed() return dAreaUsed; } +std::vector Zone::getPossibleQuestArtifactPos() const +{ + return possibleQuestArtifactPos; +} + void Zone::clearTiles() { dArea.clear(); diff --git a/lib/rmg/Zone.h b/lib/rmg/Zone.h index 110ec881e..2c5f4a78e 100644 --- a/lib/rmg/Zone.h +++ b/lib/rmg/Zone.h @@ -93,6 +93,8 @@ public: rmg::Area & areaPossible(); rmg::Area & freePaths(); rmg::Area & areaUsed(); + + std::vector getPossibleQuestArtifactPos() const; void initFreeTiles(); void clearTiles(); @@ -137,6 +139,7 @@ protected: rmg::Area dAreaPossible; rmg::Area dAreaFree; //core paths of free tiles that all other objects will be linked to rmg::Area dAreaUsed; + std::vector possibleQuestArtifactPos; //template info si32 townType;