浏览代码

Unban artifacts if RMG fails to place Seer Hut (unlikely)

Tomasz Zieliński 1 年之前
父节点
当前提交
71844d4d92

+ 5 - 0
lib/rmg/CMapGenerator.cpp

@@ -509,6 +509,11 @@ void CMapGenerator::banQuestArt(const ArtifactID & id)
 	map->getMap(this).allowedArtifact.erase(id);
 }
 
+void CMapGenerator::unbanQuestArt(const ArtifactID & id)
+{
+	map->getMap(this).allowedArtifact.insert(id);
+}
+
 Zone * CMapGenerator::getZoneWater() const
 {
 	for(auto & z : map->getZones())

+ 1 - 0
lib/rmg/CMapGenerator.h

@@ -65,6 +65,7 @@ public:
 	const std::vector<ArtifactID> & getAllPossibleQuestArtifacts() const;
 	const std::vector<HeroTypeID> getAllPossibleHeroes() const;
 	void banQuestArt(const ArtifactID & id);
+	void unbanQuestArt(const ArtifactID & id);
 	
 	Zone * getZoneWater() const;
 	void addWaterTreasuresInfo();

+ 10 - 2
lib/rmg/modificators/QuestArtifactPlacer.cpp

@@ -40,11 +40,18 @@ void QuestArtifactPlacer::addQuestArtZone(std::shared_ptr<Zone> otherZone)
 
 void QuestArtifactPlacer::addQuestArtifact(const ArtifactID& id)
 {
+	logGlobal->info("Need to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
 	RecursiveLock lock(externalAccessMutex);
-	logGlobal->info("Need to place quest artifact artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
 	questArtifactsToPlace.emplace_back(id);
 }
 
+void QuestArtifactPlacer::removeQuestArtifact(const ArtifactID& id)
+{
+	logGlobal->info("Will not try to place quest artifact %s", VLC->artifacts()->getById(id)->getNameTranslated());
+	RecursiveLock lock(externalAccessMutex);
+	vstd::erase_if_present(questArtifactsToPlace, id);
+}
+
 void QuestArtifactPlacer::rememberPotentialArtifactToReplace(CGObjectInstance* obj)
 {
 	RecursiveLock lock(externalAccessMutex);
@@ -143,10 +150,11 @@ ArtifactID QuestArtifactPlacer::drawRandomArtifact()
 	}
 }
 
-void QuestArtifactPlacer::addRandomArtifact(ArtifactID artid)
+void QuestArtifactPlacer::addRandomArtifact(const ArtifactID & artid)
 {
 	RecursiveLock lock(externalAccessMutex);
 	questArtifacts.push_back(artid);
+	generator.unbanQuestArt(artid);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 3 - 2
lib/rmg/modificators/QuestArtifactPlacer.h

@@ -29,14 +29,15 @@ public:
 	void findZonesForQuestArts();
 
 	void addQuestArtifact(const ArtifactID& id);
+	void removeQuestArtifact(const ArtifactID& id);
 	void rememberPotentialArtifactToReplace(CGObjectInstance* obj);
 	std::vector<CGObjectInstance*> getPossibleArtifactsToReplace() const;
 	void placeQuestArtifacts(CRandomGenerator & rand);
 	void dropReplacedArtifact(CGObjectInstance* obj);
 
 	size_t getMaxQuestArtifactCount() const;
-	ArtifactID drawRandomArtifact();
-	void addRandomArtifact(ArtifactID artid);
+	[[nodiscard]] ArtifactID drawRandomArtifact();
+	void addRandomArtifact(const ArtifactID & artid);
 
 protected:
 

+ 25 - 6
lib/rmg/modificators/TreasurePlacer.cpp

@@ -474,7 +474,8 @@ void TreasurePlacer::addAllPossibleObjects()
 			
 			int randomAppearance = chooseRandomAppearance(zone.getRand(), Obj::SEER_HUT, zone.getTerrainType());
 			
-			oi.generateObject = [creature, creaturesAmount, randomAppearance, this, qap]() -> CGObjectInstance *
+			// FIXME: Remove duplicated code for gold, exp and creaure reward
+			oi.generateObject = [creature, creaturesAmount, randomAppearance, this, qap, &oi]() -> CGObjectInstance *
 			{
 				auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
 				auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
@@ -485,9 +486,15 @@ void TreasurePlacer::addAllPossibleObjects()
 				obj->configuration.info.push_back(reward);
 								
 				ArtifactID artid = qap->drawRandomArtifact();
+				oi.destroyObject = [artid, qap]()
+				{
+					// Artifact can be used again
+					qap->addRandomArtifact(artid);
+					qap->removeQuestArtifact(artid);
+				};
 				obj->quest->mission.artifacts.push_back(artid);
 				
-				zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
+				qap->addQuestArtifact(artid);
 				
 				return obj;
 			};
@@ -521,7 +528,7 @@ void TreasurePlacer::addAllPossibleObjects()
 			oi.probability = 10;
 			oi.maxPerZone = 1;
 			
-			oi.generateObject = [i, randomAppearance, this, qap]() -> CGObjectInstance *
+			oi.generateObject = [i, randomAppearance, this, qap, &oi]() -> CGObjectInstance *
 			{
 				auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
 				auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
@@ -532,9 +539,15 @@ void TreasurePlacer::addAllPossibleObjects()
 				obj->configuration.info.push_back(reward);
 				
 				ArtifactID artid = qap->drawRandomArtifact();
+				oi.destroyObject = [artid, qap]()
+				{
+					// Artifact can be used again
+					qap->addRandomArtifact(artid);
+					qap->removeQuestArtifact(artid);
+				};
 				obj->quest->mission.artifacts.push_back(artid);
 				
-				zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
+				qap->addQuestArtifact(artid);
 				
 				return obj;
 			};
@@ -542,7 +555,7 @@ void TreasurePlacer::addAllPossibleObjects()
 			if(!oi.templates.empty())
 				possibleSeerHuts.push_back(oi);
 			
-			oi.generateObject = [i, randomAppearance, this, qap]() -> CGObjectInstance *
+			oi.generateObject = [i, randomAppearance, this, qap, &oi]() -> CGObjectInstance *
 			{
 				auto factory = VLC->objtypeh->getHandlerFor(Obj::SEER_HUT, randomAppearance);
 				auto * obj = dynamic_cast<CGSeerHut *>(factory->create());
@@ -553,9 +566,15 @@ void TreasurePlacer::addAllPossibleObjects()
 				obj->configuration.info.push_back(reward);
 				
 				ArtifactID artid = qap->drawRandomArtifact();
+				oi.destroyObject = [artid, qap]()
+				{
+					// Artifact can be used again
+					qap->addRandomArtifact(artid);
+					qap->removeQuestArtifact(artid);
+				};
 				obj->quest->mission.artifacts.push_back(artid);
 				
-				zone.getModificator<QuestArtifactPlacer>()->addQuestArtifact(artid);
+				qap->addQuestArtifact(artid);
 				
 				return obj;
 			};