ObjectDistributor.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /*
  2. * ObjectDistributor.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "ObjectDistributor.h"
  12. #include "../../GameLibrary.h"
  13. #include "../RmgMap.h"
  14. #include "../CMapGenerator.h"
  15. #include "TreasurePlacer.h"
  16. #include "PrisonHeroPlacer.h"
  17. #include "QuestArtifactPlacer.h"
  18. #include "TownPlacer.h"
  19. #include "TerrainPainter.h"
  20. #include "../../mapObjectConstructors/AObjectTypeHandler.h"
  21. #include "../../mapObjectConstructors/CObjectClassesHandler.h"
  22. #include "../../mapObjects/MapObjects.h"
  23. #include "../Functions.h"
  24. #include "../RmgObject.h"
  25. #include <vstd/RNG.h>
  26. VCMI_LIB_NAMESPACE_BEGIN
  27. void ObjectDistributor::process()
  28. {
  29. distributeLimitedObjects();
  30. distributePrisons();
  31. distributeSeerHuts();
  32. }
  33. void ObjectDistributor::init()
  34. {
  35. //All of the terrain types need to be determined
  36. DEPENDENCY_ALL(TerrainPainter);
  37. POSTFUNCTION(TreasurePlacer);
  38. }
  39. void ObjectDistributor::distributeLimitedObjects()
  40. {
  41. // objects with these IDs need special placement / construction logic
  42. std::set<MapObjectID> excludedIDs = {
  43. Obj::CREATURE_GENERATOR1,
  44. Obj::CREATURE_GENERATOR4,
  45. };
  46. auto zones = map.getZones();
  47. for (auto primaryID : LIBRARY->objtypeh->knownObjects())
  48. {
  49. for (auto secondaryID : LIBRARY->objtypeh->knownSubObjects(primaryID))
  50. {
  51. auto handler = LIBRARY->objtypeh->getHandlerFor(primaryID, secondaryID);
  52. if (!handler->isStaticObject() && handler->getRMGInfo().value)
  53. {
  54. auto rmgInfo = handler->getRMGInfo();
  55. //Skip objects which don't have global per-map limit here
  56. if (rmgInfo.mapLimit)
  57. {
  58. if(excludedIDs.find(primaryID) != excludedIDs.end())
  59. {
  60. logGlobal->error("ObjectDistributor: Object %s does not support per-map limit", handler->getJsonKey());
  61. continue;
  62. }
  63. //Count all zones where this object can be placed
  64. std::vector<std::shared_ptr<Zone>> matchingZones;
  65. for (const auto& it : zones)
  66. {
  67. if (!handler->getTemplates(it.second->getTerrainType()).empty() &&
  68. rmgInfo.value <= it.second->getMaxTreasureValue())
  69. {
  70. matchingZones.push_back(it.second);
  71. }
  72. }
  73. size_t numZones = matchingZones.size();
  74. if (!numZones)
  75. continue;
  76. auto rmgInfo = handler->getRMGInfo();
  77. RandomGeneratorUtil::randomShuffle(matchingZones, zone.getRand());
  78. for (auto& zone : matchingZones)
  79. {
  80. ObjectInfo oi(primaryID, secondaryID);
  81. oi.generateObject = [cb=map.mapInstance->cb, primaryID, secondaryID]()
  82. {
  83. return LIBRARY->objtypeh->getHandlerFor(primaryID, secondaryID)->create(cb, nullptr);
  84. };
  85. oi.value = rmgInfo.value;
  86. oi.probability = rmgInfo.rarity;
  87. oi.setTemplates(primaryID, secondaryID, zone->getTerrainType());
  88. //Rounding up will make sure all possible objects are exhausted
  89. uint32_t mapLimit = rmgInfo.mapLimit.value();
  90. uint32_t maxPerZone = std::ceil(float(mapLimit) / numZones);
  91. //But not more than zone limit
  92. oi.maxPerZone = std::min(maxPerZone, rmgInfo.zoneLimit);
  93. numZones--;
  94. rmgInfo.setMapLimit(mapLimit - oi.maxPerZone);
  95. //Don't add objects with 0 count remaining
  96. if(oi.maxPerZone && !oi.templates.empty())
  97. {
  98. zone->getModificator<TreasurePlacer>()->addObjectToRandomPool(oi);
  99. }
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }
  106. void ObjectDistributor::distributeSeerHuts()
  107. {
  108. //TODO: Move typedef outside the class?
  109. //Copy by value to random shuffle
  110. const auto & zoneMap = map.getZones();
  111. RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
  112. RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
  113. const auto & possibleQuestArts = generator.getAllPossibleQuestArtifacts();
  114. size_t availableArts = possibleQuestArts.size();
  115. auto artIt = possibleQuestArts.begin();
  116. for (int i = zones.size() - 1; i >= 0 ; i--)
  117. {
  118. size_t localArts = std::ceil((float)availableArts / (i + 1));
  119. availableArts -= localArts;
  120. auto * qap = zones[i].second->getModificator<QuestArtifactPlacer>();
  121. if (qap)
  122. {
  123. for (;localArts > 0 && artIt != possibleQuestArts.end(); artIt++, localArts--)
  124. {
  125. qap->addRandomArtifact(*artIt);
  126. }
  127. }
  128. }
  129. }
  130. void ObjectDistributor::distributePrisons()
  131. {
  132. //Copy by value to random shuffle
  133. const auto & zoneMap = map.getZones();
  134. RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
  135. RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
  136. // TODO: Some shorthand for unique Modificator
  137. PrisonHeroPlacer * prisonHeroPlacer = nullptr;
  138. for(auto & z : map.getZones())
  139. {
  140. prisonHeroPlacer = z.second->getModificator<PrisonHeroPlacer>();
  141. if (prisonHeroPlacer)
  142. {
  143. break;
  144. }
  145. }
  146. size_t allowedPrisons = prisonHeroPlacer->getPrisonsRemaining();
  147. for (int i = zones.size() - 1; i >= 0; i--)
  148. {
  149. auto zone = zones[i].second;
  150. auto * tp = zone->getModificator<TreasurePlacer>();
  151. if (tp)
  152. {
  153. tp->setMaxPrisons(std::ceil(float(allowedPrisons) / (i + 1)));
  154. allowedPrisons -= tp->getMaxPrisons();
  155. }
  156. }
  157. }
  158. VCMI_LIB_NAMESPACE_END