Răsfoiți Sursa

Spawn quest arts in nearby zones.

DjWarmonger 10 ani în urmă
părinte
comite
9453250e0f
4 a modificat fișierele cu 147 adăugiri și 90 ștergeri
  1. 21 0
      lib/rmg/CMapGenerator.cpp
  2. 1 0
      lib/rmg/CMapGenerator.h
  3. 123 90
      lib/rmg/CRmgTemplateZone.cpp
  4. 2 0
      lib/rmg/CRmgTemplateZone.h

+ 21 - 0
lib/rmg/CMapGenerator.cpp

@@ -241,6 +241,7 @@ void CMapGenerator::fillZones()
 		it.second->initFreeTiles(this);
 	}
 
+	findZonesForQuestArts();
 	createConnections();
 	//make sure all connections are passable before creating borders
 	for (auto it : zones)
@@ -270,6 +271,26 @@ void CMapGenerator::fillZones()
 	logGlobal->infoStream() << "Zones filled successfully";
 }
 
+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 = connection.getZoneA();
+		auto zoneB = connection.getZoneB();
+
+		if (zoneA->getId() > zoneB->getId())
+		{
+			zoneB->setQuestArtZone(zoneA);
+		}
+		else if (zoneA->getId() < zoneB->getId())
+		{
+			zoneA->setQuestArtZone(zoneB);
+		}
+	}
+}
+
 void CMapGenerator::createConnections()
 {
 	for (auto connection : mapGenOptions->getMapTemplate()->getConnections())

+ 1 - 0
lib/rmg/CMapGenerator.h

@@ -64,6 +64,7 @@ public:
 
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> getZones() const;
 	void createConnections();
+	void findZonesForQuestArts();
 	void foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo);
 
 	bool isBlocked(const int3 &tile) const;

+ 123 - 90
lib/rmg/CRmgTemplateZone.cpp

@@ -144,7 +144,8 @@ CRmgTemplateZone::CRmgTemplateZone() :
 	townType(ETownType::NEUTRAL),
 	terrainType (ETerrainType::GRASS),
 	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
-	minGuardedValue(0)
+	minGuardedValue(0),
+	questArtZone(nullptr)
 {
 	terrainTypes = getDefaultTerrainTypes();
 }
@@ -297,6 +298,11 @@ void CRmgTemplateZone::addConnection(TRmgTemplateZoneId otherZone)
 	connections.push_back (otherZone);
 }
 
+void CRmgTemplateZone::setQuestArtZone(CRmgTemplateZone * otherZone)
+{
+	questArtZone = otherZone;
+}
+
 std::vector<TRmgTemplateZoneId> CRmgTemplateZone::getConnections() const
 {
 	return connections;
@@ -2259,120 +2265,147 @@ void CRmgTemplateZone::addAllPossibleObjects(CMapGenerator* gen)
 
 	//seer huts with creatures or generic rewards
 
-	static const int genericSeerHuts = 8;
-	int seerHutsPerType = 0;
-	const int questArtsRemaining = gen->getQuestArtsRemaning().size();
+	if (questArtZone) //we won't be placing seer huts if there is no zone left to place arties
+	{
+		static const int genericSeerHuts = 8;
+		int seerHutsPerType = 0;
+		const int questArtsRemaining = gen->getQuestArtsRemaning().size();
 
-	std::vector<CCreature *> creatures;
+		std::vector<CCreature *> creatures;
 
-	for (auto cre : VLC->creh->creatures)
-	{
-		if (cre->faction == townType)
+		for (auto cre : VLC->creh->creatures)
 		{
-			creatures.push_back(cre);
+			if (cre->faction == townType)
+			{
+				creatures.push_back(cre);
+			}
 		}
-	}
 
-	//general issue is that not many artifact types are available for quests
-
-	if (questArtsRemaining >= genericSeerHuts + creatures.size())
-	{
-		seerHutsPerType = questArtsRemaining / (genericSeerHuts + creatures.size());
-	}
-	else if (questArtsRemaining >= genericSeerHuts)
-	{
-		seerHutsPerType = 1;
-	}
-	oi.maxPerZone = seerHutsPerType;
+		//general issue is that not many artifact types are available for quests
 
-	RandomGeneratorUtil::randomShuffle(creatures, gen->rand);
+		if (questArtsRemaining >= genericSeerHuts + creatures.size())
+		{
+			seerHutsPerType = questArtsRemaining / (genericSeerHuts + creatures.size());
+		}
+		else if (questArtsRemaining >= genericSeerHuts)
+		{
+			seerHutsPerType = 1;
+		}
+		oi.maxPerZone = seerHutsPerType;
 
-	for (int i = 0; i < std::min<int>(creatures.size(), questArtsRemaining - genericSeerHuts); i++)
-	{
-		auto creature = creatures[i];
-		int creaturesAmount = creatureToCount(creature);
+		RandomGeneratorUtil::randomShuffle(creatures, gen->rand);
 
-		if (!creaturesAmount)
-			continue;
+		auto generateArtInfo = [](ArtifactID id) -> ObjectInfo
+		{
+			ObjectInfo artInfo;
+			artInfo.probability = 1e6; //99,9% to spawn that art in first treasure pile
+			artInfo.maxPerZone = 1;
+			artInfo.value = 2000; //treasure art
+			artInfo.generateObject = [id]() -> CGObjectInstance *
+			{
+				auto obj = new CGArtifact;
+				obj->ID = Obj::ARTIFACT;
+				obj->subID = id;
 
-		int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
+				return obj;
+				//TODO: place required artifact in next zone
+			};
+			return artInfo;
+		};
 
-		oi.generateObject = [creature, creaturesAmount, randomAppearance, gen]() -> CGObjectInstance *
+		for (int i = 0; i < std::min<int>(creatures.size(), questArtsRemaining - genericSeerHuts); i++)
 		{
-			auto obj = new CGSeerHut();
-			obj->ID = Obj::SEER_HUT;
-			obj->subID = randomAppearance;
-			obj->rewardType = CGSeerHut::CREATURE;
-			obj->rID = creature->idNumber;
-			obj->rVal = creaturesAmount;
+			auto creature = creatures[i];
+			int creaturesAmount = creatureToCount(creature);
 
-			obj->quest->missionType = CQuest::MISSION_ART;
-			ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
-			obj->quest->m5arts.push_back(artid);
-			gen->banQuestArt(artid);
-			gen->map->addQuest(obj);
+			if (!creaturesAmount)
+				continue;
 
-			return obj;
-			//TODO: place required artifact in next zone
-		};
-		oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
-		oi.value = ((2 * (creature->AIValue) * creaturesAmount * (1 + (float)(gen->getZoneCount(creature->faction)) / gen->getTotalZoneCount())) - 4000) / 3;
-		oi.probability = 3;
-		possibleObjects.push_back(oi);
-	}
+			int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
 
-	static int seerExpGold[] = { 5000, 10000, 15000, 20000 };
-	static int seerValues[] = { 2000, 5333, 8666, 12000};
+			oi.generateObject = [creature, creaturesAmount, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
+			{
+				auto obj = new CGSeerHut();
+				obj->ID = Obj::SEER_HUT;
+				obj->subID = randomAppearance;
+				obj->rewardType = CGSeerHut::CREATURE;
+				obj->rID = creature->idNumber;
+				obj->rVal = creaturesAmount;
 
-	for (int i = 0; i < 4; i++) //seems that code for exp and gold reward is similiar
-	{
-		int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
+				obj->quest->missionType = CQuest::MISSION_ART;
+				ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
+				obj->quest->m5arts.push_back(artid);
+				gen->banQuestArt(artid);
+				gen->map->addQuest(obj);
+
+				this->questArtZone->possibleObjects.push_back (generateArtInfo(artid));
+
+				return obj;
+				//TODO: place required artifact in next zone
+			};
+			oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
+			oi.value = ((2 * (creature->AIValue) * creaturesAmount * (1 + (float)(gen->getZoneCount(creature->faction)) / gen->getTotalZoneCount())) - 4000) / 3;
+			oi.probability = 3;
+			possibleObjects.push_back(oi);
+		}
 
-		oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
-		oi.value = seerValues[i];
-		oi.probability = 10;
+		static int seerExpGold[] = { 5000, 10000, 15000, 20000 };
+		static int seerValues[] = { 2000, 5333, 8666, 12000 };
 
-		oi.generateObject = [i, randomAppearance, gen]() -> CGObjectInstance *
+		for (int i = 0; i < 4; i++) //seems that code for exp and gold reward is similiar
 		{
-			auto obj = new CGSeerHut();
-			obj->ID = Obj::SEER_HUT;
-			obj->subID = randomAppearance;
-			obj->rewardType = CGSeerHut::EXPERIENCE;
-			obj->rID = 0; //unitialized?
-			obj->rVal = seerExpGold[i];
+			int randomAppearance = *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::SEER_HUT), gen->rand);
 
-			obj->quest->missionType = CQuest::MISSION_ART;
-			ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
-			obj->quest->m5arts.push_back(artid);
-			gen->banQuestArt(artid);
-			gen->map->addQuest(obj);
+			oi.setTemplate(Obj::SEER_HUT, randomAppearance, terrainType);
+			oi.value = seerValues[i];
+			oi.probability = 10;
 
-			return obj;
-			//TODO: place required artifact in next zone
-		};
+			oi.generateObject = [i, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
+			{
+				auto obj = new CGSeerHut();
+				obj->ID = Obj::SEER_HUT;
+				obj->subID = randomAppearance;
+				obj->rewardType = CGSeerHut::EXPERIENCE;
+				obj->rID = 0; //unitialized?
+				obj->rVal = seerExpGold[i];
 
-		possibleObjects.push_back(oi);
+				obj->quest->missionType = CQuest::MISSION_ART;
+				ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
+				obj->quest->m5arts.push_back(artid);
+				gen->banQuestArt(artid);
+				gen->map->addQuest(obj);
 
-		oi.generateObject = [i, randomAppearance, gen]() -> CGObjectInstance *
-		{
-			auto obj = new CGSeerHut();
-			obj->ID = Obj::SEER_HUT;
-			obj->subID = randomAppearance;
-			obj->rewardType = CGSeerHut::RESOURCES;
-			obj->rID = Res::GOLD;
-			obj->rVal = seerExpGold[i];
+				this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
 
-			obj->quest->missionType = CQuest::MISSION_ART;
-			ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
-			obj->quest->m5arts.push_back(artid);
-			gen->banQuestArt(artid);
-			gen->map->addQuest(obj);
+				return obj;
+				//TODO: place required artifact in next zone
+			};
 
-			return obj;
-			//TODO: place required artifact in next zone
-		};
+			possibleObjects.push_back(oi);
 
-		possibleObjects.push_back(oi);
+			oi.generateObject = [i, randomAppearance, gen, this, generateArtInfo]() -> CGObjectInstance *
+			{
+				auto obj = new CGSeerHut();
+				obj->ID = Obj::SEER_HUT;
+				obj->subID = randomAppearance;
+				obj->rewardType = CGSeerHut::RESOURCES;
+				obj->rID = Res::GOLD;
+				obj->rVal = seerExpGold[i];
+
+				obj->quest->missionType = CQuest::MISSION_ART;
+				ArtifactID artid = *RandomGeneratorUtil::nextItem(gen->getQuestArtsRemaning(), gen->rand);
+				obj->quest->m5arts.push_back(artid);
+				gen->banQuestArt(artid);
+				gen->map->addQuest(obj);
+
+				this->questArtZone->possibleObjects.push_back(generateArtInfo(artid));
+
+				return obj;
+				//TODO: place required artifact in next zone
+			};
+
+			possibleObjects.push_back(oi);
+		}
 	}
 }
 

+ 2 - 0
lib/rmg/CRmgTemplateZone.h

@@ -169,6 +169,7 @@ public:
 	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
 
 	void addConnection(TRmgTemplateZoneId otherZone);
+	void setQuestArtZone(CRmgTemplateZone * otherZone);
 	std::vector<TRmgTemplateZoneId> getConnections() const;
 	void addTreasureInfo(CTreasureInfo & info);
 	std::vector<CTreasureInfo> getTreasureInfo();
@@ -194,6 +195,7 @@ private:
 
 	si32 townType;
 	ETerrainType terrainType;
+	CRmgTemplateZone * questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
 
 	EMonsterStrength::EMonsterStrength zoneMonsterStrength;
 	std::vector<CTreasureInfo> treasureInfo;