ObjectDistributor.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 "TownPlacer.h"
  17. #include "TerrainPainter.h"
  18. #include "../mapObjects/CObjectClassesHandler.h"
  19. #include "../mapObjects/MapObjects.h"
  20. #include "Functions.h"
  21. #include "RmgObject.h"
  22. VCMI_LIB_NAMESPACE_BEGIN
  23. void ObjectDistributor::process()
  24. {
  25. //Firts call will add objects to ALL zones, once they were added skip it
  26. if (zone.getModificator<TreasurePlacer>()->getPossibleObjectsSize() == 0)
  27. {
  28. ObjectDistributor::distributeLimitedObjects();
  29. }
  30. }
  31. void ObjectDistributor::init()
  32. {
  33. DEPENDENCY(TownPlacer);
  34. DEPENDENCY(TerrainPainter);
  35. POSTFUNCTION(TreasurePlacer);
  36. }
  37. void ObjectDistributor::distributeLimitedObjects()
  38. {
  39. //FIXME: Must be called after TerrainPainter::process()
  40. ObjectInfo oi;
  41. auto zones = map.getZones();
  42. for (auto primaryID : VLC->objtypeh->knownObjects())
  43. {
  44. for (auto secondaryID : VLC->objtypeh->knownSubObjects(primaryID))
  45. {
  46. auto handler = VLC->objtypeh->getHandlerFor(primaryID, secondaryID);
  47. if (!handler->isStaticObject() && handler->getRMGInfo().value)
  48. {
  49. auto rmgInfo = handler->getRMGInfo();
  50. //Skip objects which don't have global per-map limit here
  51. if (rmgInfo.mapLimit)
  52. {
  53. //Count all zones where this object can be placed
  54. std::vector<std::shared_ptr<Zone>> matchingZones;
  55. for (const auto& it : zones)
  56. {
  57. if (!handler->getTemplates(it.second->getTerrainType()).empty() &&
  58. rmgInfo.value <= it.second->getMaxTreasureValue())
  59. {
  60. matchingZones.push_back(it.second);
  61. }
  62. }
  63. size_t numZones = matchingZones.size();
  64. if (!numZones)
  65. continue;
  66. auto rmgInfo = handler->getRMGInfo();
  67. for (auto& zone : matchingZones)
  68. {
  69. //We already know there are some templates
  70. auto templates = handler->getTemplates(zone->getTerrainType());
  71. //Assume the template with fewest terrains is the most suitable
  72. auto temp = *boost::min_element(templates, [](std::shared_ptr<const ObjectTemplate> lhs, std::shared_ptr<const ObjectTemplate> rhs) -> bool
  73. {
  74. return lhs->getAllowedTerrains().size() < rhs->getAllowedTerrains().size();
  75. });
  76. oi.generateObject = [temp]() -> CGObjectInstance *
  77. {
  78. return VLC->objtypeh->getHandlerFor(temp->id, temp->subid)->create(temp);
  79. };
  80. oi.value = rmgInfo.value;
  81. oi.probability = rmgInfo.rarity;
  82. oi.templ = temp;
  83. //Rounding up will make sure all possible objects are exhausted
  84. uint32_t mapLimit = rmgInfo.mapLimit.value();
  85. uint32_t maxPerZone = std::ceil(float(mapLimit) / numZones);
  86. //But not more than zone limit
  87. oi.maxPerZone = std::min(maxPerZone, rmgInfo.zoneLimit);
  88. numZones--;
  89. rmgInfo.setMapLimit(mapLimit - oi.maxPerZone);
  90. //Don't add objects with 0 count remaining
  91. if (oi.maxPerZone)
  92. {
  93. zone->getModificator<TreasurePlacer>()->addObjectToRandomPool(oi);
  94. }
  95. }
  96. }
  97. }
  98. }
  99. }
  100. }
  101. VCMI_LIB_NAMESPACE_END