Kaynağa Gözat

Place quest artifacts after all the treasures are already created.

Tomasz Zieliński 2 yıl önce
ebeveyn
işleme
80b5c53815

+ 2 - 0
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

+ 11 - 28
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<RmgMap>(mapGenOptions);
+	placer = std::make_shared<CZonePlacer>(*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<TreasurePlacer>())
-				m->setQuestArtZone(zoneA.get());
-		}
-		else if (zoneA->getId() < zoneB->getId())
-		{
-			if(auto * m = zoneA->getModificator<TreasurePlacer>())
-				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<CZonePlacer> CMapGenerator::getZonePlacer() const
+{
+	return placer;
+}
+
 void CMapGenerator::decreasePrisonsRemaining()
 {
 	prisonsRemaining = std::max (0, prisonsRemaining - 1);

+ 5 - 4
lib/rmg/CMapGenerator.h

@@ -25,6 +25,7 @@ class JsonNode;
 class RmgMap;
 class CMap;
 class Zone;
+class CZonePlacer;
 
 typedef std::vector<JsonNode> JsonVector;
 
@@ -59,16 +60,15 @@ public:
 	
 	std::unique_ptr<CMap> generate();
 
-	void findZonesForQuestArts();
-
 	int getNextMonlithIndex();
 	int getPrisonsRemaning() const;
+	std::shared_ptr<CZonePlacer> getZonePlacer() const;
 	void decreasePrisonsRemaining();
 	const std::vector<ArtifactID> & 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<RmgMap> map;
+	std::shared_ptr<CZonePlacer> placer;
 	
 	std::vector<rmg::ZoneConnection> connectionsLeft;
 	
@@ -85,7 +86,7 @@ private:
 	int prisonsRemaining;
 	//int questArtsRemaining;
 	int monolithIndex;
-	std::vector<ArtifactID> questArtifacts;
+	std::vector<ArtifactID> questArtifacts; //TODO: Protect with mutex
 
 	/// Generation methods
 	void loadConfig();

+ 5 - 0
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

+ 4 - 1
lib/rmg/CZonePlacer.h

@@ -26,6 +26,7 @@ typedef std::vector<std::pair<TRmgTemplateZoneId, std::shared_ptr<Zone>>> TZoneV
 typedef std::map<TRmgTemplateZoneId, std::shared_ptr<Zone>> TZoneMap;
 typedef std::map<std::shared_ptr<Zone>, float3> TForceVector;
 typedef std::map<std::shared_ptr<Zone>, float> TDistanceVector;
+typedef std::map<int, std::map<int, size_t>> 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<int, std::map<int, size_t>> distancesBetweenZones;
+	TDistanceMap distancesBetweenZones;
 	std::set<TRmgTemplateZoneId> lastSwappedZones;
 	RmgMap & map;
 };

+ 17 - 0
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<QuestArtifactPlacer>())
+				{
+					qap->rememberPotentialArtifactToReplace(&instance->object());
+				}
+				break;
+			}
+			default:
+				break;
+		}
 	}
 	
 	switch(object.instances().front()->object().ID)

+ 2 - 0
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<TownPlacer>();
 			zone->addModificator<MinePlacer>();
+			zone->addModificator<QuestArtifactPlacer>();
 			zone->addModificator<ConnectionsPlacer>();
 			zone->addModificator<RoadPlacer>();
 			zone->addModificator<RiverPlacer>();

+ 7 - 14
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<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
+				zone.getModificator<QuestArtifactPlacer>()->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<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
+				zone.getModificator<QuestArtifactPlacer>()->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<TreasurePlacer>()->addObjectToRandomPool(generateArtInfo(artid));
+				zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
 				
 				return obj;
 			};

+ 3 - 7
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<ObjectInfo*> prepareTreasurePile(const CTreasureInfo & treasureInfo);
 	rmg::Object constructTreasurePile(const std::vector<ObjectInfo*> & treasureInfos, bool densePlacement = false);
-	
-	
+
 protected:	
 	std::vector<ObjectInfo> 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

+ 5 - 0
lib/rmg/Zone.cpp

@@ -95,6 +95,11 @@ rmg::Area & Zone::areaUsed()
 	return dAreaUsed;
 }
 
+std::vector<int3> Zone::getPossibleQuestArtifactPos() const
+{
+	return possibleQuestArtifactPos;
+}
+
 void Zone::clearTiles()
 {
 	dArea.clear();

+ 3 - 0
lib/rmg/Zone.h

@@ -93,6 +93,8 @@ public:
 	rmg::Area & areaPossible();
 	rmg::Area & freePaths();
 	rmg::Area & areaUsed();
+
+	std::vector<int3> 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<int3> possibleQuestArtifactPos;
 	
 	//template info
 	si32 townType;