| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 | 
							- /*
 
- * ObjectDistributor.cpp, part of VCMI engine
 
- *
 
- * Authors: listed in file AUTHORS in main folder
 
- *
 
- * License: GNU General Public License v2.0 or later
 
- * Full text of license available in license.txt file, in main folder
 
- *
 
- */
 
- #include "StdInc.h"
 
- #include "ObjectDistributor.h"
 
- #include "../../VCMI_Lib.h"
 
- #include "../RmgMap.h"
 
- #include "../CMapGenerator.h"
 
- #include "TreasurePlacer.h"
 
- #include "PrisonHeroPlacer.h"
 
- #include "QuestArtifactPlacer.h"
 
- #include "TownPlacer.h"
 
- #include "TerrainPainter.h"
 
- #include "../../mapObjectConstructors/AObjectTypeHandler.h"
 
- #include "../../mapObjectConstructors/CObjectClassesHandler.h"
 
- #include "../../mapObjects/MapObjects.h"
 
- #include "../Functions.h"
 
- #include "../RmgObject.h"
 
- VCMI_LIB_NAMESPACE_BEGIN
 
- void ObjectDistributor::process()
 
- {
 
- 	distributeLimitedObjects();
 
- 	distributePrisons();
 
- 	distributeSeerHuts();
 
- }
 
- void ObjectDistributor::init()
 
- {
 
- 	//All of the terrain types need to be determined
 
- 	DEPENDENCY_ALL(TerrainPainter);
 
- 	POSTFUNCTION(TreasurePlacer);
 
- }
 
- void ObjectDistributor::distributeLimitedObjects()
 
- {
 
- 	ObjectInfo oi;
 
- 	auto zones = map.getZones();
 
- 	for (auto primaryID : VLC->objtypeh->knownObjects())
 
- 	{
 
- 		for (auto secondaryID : VLC->objtypeh->knownSubObjects(primaryID))
 
- 		{
 
- 			auto handler = VLC->objtypeh->getHandlerFor(primaryID, secondaryID);
 
- 			if (!handler->isStaticObject() && handler->getRMGInfo().value)
 
- 			{
 
- 				auto rmgInfo = handler->getRMGInfo();
 
- 				//Skip objects which don't have global per-map limit here 
 
- 				if (rmgInfo.mapLimit)
 
- 				{
 
- 					//Count all zones where this object can be placed
 
- 					std::vector<std::shared_ptr<Zone>> matchingZones;
 
- 					for (const auto& it : zones)
 
- 					{
 
- 						if (!handler->getTemplates(it.second->getTerrainType()).empty() &&
 
- 							rmgInfo.value <= it.second->getMaxTreasureValue())
 
- 						{
 
- 							matchingZones.push_back(it.second);
 
- 						}
 
- 					}
 
- 					size_t numZones = matchingZones.size();
 
- 					if (!numZones)
 
- 						continue;
 
- 					auto rmgInfo = handler->getRMGInfo();
 
- 					RandomGeneratorUtil::randomShuffle(matchingZones, zone.getRand());
 
- 					for (auto& zone : matchingZones)
 
- 					{
 
- 						oi.generateObject = [cb=map.mapInstance->cb, primaryID, secondaryID]() -> CGObjectInstance *
 
- 						{
 
- 							return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create(cb, nullptr);
 
- 						};
 
- 						
 
- 						oi.value = rmgInfo.value;
 
- 						oi.probability = rmgInfo.rarity;
 
- 						oi.setTemplates(primaryID, secondaryID, zone->getTerrainType());
 
- 						//Rounding up will make sure all possible objects are exhausted
 
- 						uint32_t mapLimit = rmgInfo.mapLimit.value();
 
- 						uint32_t maxPerZone = std::ceil(float(mapLimit) / numZones);
 
- 						//But not more than zone limit
 
- 						oi.maxPerZone = std::min(maxPerZone, rmgInfo.zoneLimit);
 
- 						numZones--;
 
- 						rmgInfo.setMapLimit(mapLimit - oi.maxPerZone);
 
- 						//Don't add objects with 0 count remaining
 
- 						if(oi.maxPerZone && !oi.templates.empty())
 
- 						{
 
- 							zone->getModificator<TreasurePlacer>()->addObjectToRandomPool(oi);
 
- 						}
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- void ObjectDistributor::distributeSeerHuts()
 
- {
 
- 	//TODO: Move typedef outside the class?
 
- 	//Copy by value to random shuffle
 
- 	const auto & zoneMap = map.getZones();
 
- 	RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
 
- 	RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
 
- 	const auto & possibleQuestArts = generator.getAllPossibleQuestArtifacts();
 
- 	size_t availableArts = possibleQuestArts.size();
 
- 	auto artIt = possibleQuestArts.begin();
 
- 	for (int i = zones.size() - 1; i >= 0 ; i--)
 
- 	{
 
- 		size_t localArts = std::ceil((float)availableArts / (i + 1));
 
- 		availableArts -= localArts;
 
- 		auto * qap = zones[i].second->getModificator<QuestArtifactPlacer>();
 
- 		if (qap)
 
- 		{
 
- 			for (;localArts > 0 && artIt != possibleQuestArts.end(); artIt++, localArts--)
 
- 			{
 
- 				qap->addRandomArtifact(*artIt);
 
- 			}
 
- 		}
 
- 	}
 
- }
 
- void ObjectDistributor::distributePrisons()
 
- {
 
- 	//Copy by value to random shuffle
 
- 	const auto & zoneMap = map.getZones();
 
- 	RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
 
- 	RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
 
- 	// TODO: Some shorthand for unique Modificator
 
- 	PrisonHeroPlacer * prisonHeroPlacer = nullptr;
 
- 	for(auto & z : map.getZones())
 
- 	{
 
- 		prisonHeroPlacer = z.second->getModificator<PrisonHeroPlacer>();
 
- 		if (prisonHeroPlacer)
 
- 		{
 
- 			break;
 
- 		}
 
- 	}
 
- 	size_t allowedPrisons = prisonHeroPlacer->getPrisonsRemaning();
 
- 	for (int i = zones.size() - 1; i >= 0; i--)
 
- 	{
 
- 		auto zone = zones[i].second;
 
- 		auto * tp = zone->getModificator<TreasurePlacer>();
 
- 		if (tp)
 
- 		{
 
- 			tp->setMaxPrisons(std::ceil(float(allowedPrisons) / (i + 1)));
 
- 			allowedPrisons -= tp->getMaxPrisons();
 
- 		}
 
- 	}
 
- }
 
- VCMI_LIB_NAMESPACE_END
 
 
  |