ObjectDistributor.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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 "../../VCMI_Lib.h"
  13. #include "../RmgMap.h"
  14. #include "../CMapGenerator.h"
  15. #include "TreasurePlacer.h"
  16. #include "QuestArtifactPlacer.h"
  17. #include "TownPlacer.h"
  18. #include "TerrainPainter.h"
  19. #include "../../mapObjectConstructors/AObjectTypeHandler.h"
  20. #include "../../mapObjectConstructors/CObjectClassesHandler.h"
  21. #include "../../mapObjects/MapObjects.h"
  22. #include "../Functions.h"
  23. #include "../RmgObject.h"
  24. VCMI_LIB_NAMESPACE_BEGIN
  25. void ObjectDistributor::process()
  26. {
  27. distributeLimitedObjects();
  28. distributePrisons();
  29. distributeSeerHuts();
  30. }
  31. void ObjectDistributor::init()
  32. {
  33. //All of the terrain types need to be determined
  34. DEPENDENCY_ALL(TerrainPainter);
  35. POSTFUNCTION(TreasurePlacer);
  36. }
  37. void ObjectDistributor::distributeLimitedObjects()
  38. {
  39. ObjectInfo oi;
  40. auto zones = map.getZones();
  41. for (auto primaryID : VLC->objtypeh->knownObjects())
  42. {
  43. for (auto secondaryID : VLC->objtypeh->knownSubObjects(primaryID))
  44. {
  45. auto handler = VLC->objtypeh->getHandlerFor(primaryID, secondaryID);
  46. if (!handler->isStaticObject() && handler->getRMGInfo().value)
  47. {
  48. auto rmgInfo = handler->getRMGInfo();
  49. //Skip objects which don't have global per-map limit here
  50. if (rmgInfo.mapLimit)
  51. {
  52. //Count all zones where this object can be placed
  53. std::vector<std::shared_ptr<Zone>> matchingZones;
  54. for (const auto& it : zones)
  55. {
  56. if (!handler->getTemplates(it.second->getTerrainType()).empty() &&
  57. rmgInfo.value <= it.second->getMaxTreasureValue())
  58. {
  59. matchingZones.push_back(it.second);
  60. }
  61. }
  62. size_t numZones = matchingZones.size();
  63. if (!numZones)
  64. continue;
  65. auto rmgInfo = handler->getRMGInfo();
  66. // FIXME: Random order of distribution
  67. RandomGeneratorUtil::randomShuffle(matchingZones, zone.getRand());
  68. for (auto& zone : matchingZones)
  69. {
  70. oi.generateObject = [primaryID, secondaryID]() -> CGObjectInstance *
  71. {
  72. return VLC->objtypeh->getHandlerFor(primaryID, secondaryID)->create();
  73. };
  74. oi.value = rmgInfo.value;
  75. oi.probability = rmgInfo.rarity;
  76. oi.setTemplates(primaryID, secondaryID, zone->getTerrainType());
  77. //Rounding up will make sure all possible objects are exhausted
  78. uint32_t mapLimit = rmgInfo.mapLimit.value();
  79. uint32_t maxPerZone = std::ceil(float(mapLimit) / numZones);
  80. //But not more than zone limit
  81. oi.maxPerZone = std::min(maxPerZone, rmgInfo.zoneLimit);
  82. numZones--;
  83. rmgInfo.setMapLimit(mapLimit - oi.maxPerZone);
  84. //Don't add objects with 0 count remaining
  85. if(oi.maxPerZone && !oi.templates.empty())
  86. {
  87. zone->getModificator<TreasurePlacer>()->addObjectToRandomPool(oi);
  88. }
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }
  95. void ObjectDistributor::distributeSeerHuts()
  96. {
  97. //TODO: Move typedef outside the class?
  98. //Copy by value to random shuffle
  99. const auto & zoneMap = map.getZones();
  100. RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
  101. RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
  102. const auto & possibleQuestArts = generator.getAllPossibleQuestArtifacts();
  103. size_t availableArts = possibleQuestArts.size();
  104. auto artIt = possibleQuestArts.begin();
  105. for (int i = zones.size() - 1; i >= 0 ; i--)
  106. {
  107. size_t localArts = std::ceil((float)availableArts / (i + 1));
  108. availableArts -= localArts;
  109. auto * qap = zones[i].second->getModificator<QuestArtifactPlacer>();
  110. if (qap)
  111. {
  112. for (;localArts > 0 && artIt != possibleQuestArts.end(); artIt++, localArts--)
  113. {
  114. qap->addRandomArtifact(*artIt);
  115. }
  116. }
  117. }
  118. }
  119. void ObjectDistributor::distributePrisons()
  120. {
  121. //Copy by value to random shuffle
  122. const auto & zoneMap = map.getZones();
  123. RmgMap::ZoneVector zones(zoneMap.begin(), zoneMap.end());
  124. RandomGeneratorUtil::randomShuffle(zones, zone.getRand());
  125. size_t allowedPrisons = generator.getPrisonsRemaning();
  126. for (int i = zones.size() - 1; i >= 0; i--)
  127. {
  128. auto zone = zones[i].second;
  129. auto * tp = zone->getModificator<TreasurePlacer>();
  130. if (tp)
  131. {
  132. tp->setMaxPrisons(std::ceil(float(allowedPrisons) / (i + 1)));
  133. allowedPrisons -= tp->getMaxPrisons();
  134. }
  135. }
  136. }
  137. VCMI_LIB_NAMESPACE_END