ObstaclePlacer.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * ObstaclePlacer.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 "ObstaclePlacer.h"
  12. #include "ObjectManager.h"
  13. #include "TreasurePlacer.h"
  14. #include "RockFiller.h"
  15. #include "WaterRoutes.h"
  16. #include "WaterProxy.h"
  17. #include "RoadPlacer.h"
  18. #include "RiverPlacer.h"
  19. #include "../RmgMap.h"
  20. #include "../CMapGenerator.h"
  21. #include "../../CRandomGenerator.h"
  22. #include "../Functions.h"
  23. #include "../../mapping/CMapEditManager.h"
  24. #include "../../mapping/CMap.h"
  25. #include "../../mapping/ObstacleProxy.h"
  26. #include "../../mapObjects/CGObjectInstance.h"
  27. VCMI_LIB_NAMESPACE_BEGIN
  28. void ObstaclePlacer::process()
  29. {
  30. manager = zone.getModificator<ObjectManager>();
  31. if(!manager)
  32. return;
  33. collectPossibleObstacles(zone.getTerrainType());
  34. {
  35. Zone::Lock lock(zone.areaMutex);
  36. blockedArea = zone.area().getSubarea([this](const int3& t)
  37. {
  38. return map.shouldBeBlocked(t);
  39. });
  40. blockedArea.subtract(zone.areaUsed());
  41. zone.areaPossible().subtract(blockedArea);
  42. prohibitedArea = zone.freePaths() + zone.areaUsed() + manager->getVisitableArea();
  43. //Progressively block tiles, but make sure they don't seal any gap between blocks
  44. rmg::Area toBlock;
  45. do
  46. {
  47. toBlock.clear();
  48. for (const auto& tile : zone.areaPossible().getTilesVector())
  49. {
  50. rmg::Area neighbors;
  51. rmg::Area t;
  52. t.add(tile);
  53. for (const auto& n : t.getBorderOutside())
  54. {
  55. //Area outside the map is also impassable
  56. if (!map.isOnMap(n) || map.shouldBeBlocked(n))
  57. {
  58. neighbors.add(n);
  59. }
  60. }
  61. if (neighbors.empty())
  62. {
  63. continue;
  64. }
  65. //Will only be added if it doesn't connect two disjointed blocks
  66. if (neighbors.connected(true)) //Do not block diagonal pass
  67. {
  68. toBlock.add(tile);
  69. }
  70. }
  71. zone.areaPossible().subtract(toBlock);
  72. for (const auto& tile : toBlock.getTilesVector())
  73. {
  74. map.setOccupied(tile, ETileType::BLOCKED);
  75. }
  76. } while (!toBlock.empty());
  77. prohibitedArea.unite(zone.areaPossible());
  78. }
  79. auto objs = createObstacles(zone.getRand());
  80. mapProxy->insertObjects(objs);
  81. }
  82. void ObstaclePlacer::init()
  83. {
  84. DEPENDENCY(ObjectManager);
  85. DEPENDENCY(TreasurePlacer);
  86. DEPENDENCY(RoadPlacer);
  87. if (zone.isUnderground())
  88. {
  89. DEPENDENCY(RockFiller);
  90. }
  91. else
  92. {
  93. DEPENDENCY(WaterRoutes);
  94. DEPENDENCY(WaterProxy);
  95. }
  96. }
  97. bool ObstaclePlacer::isInTheMap(const int3& tile)
  98. {
  99. return map.isOnMap(tile);
  100. }
  101. void ObstaclePlacer::placeObject(rmg::Object & object, std::set<CGObjectInstance*> &)
  102. {
  103. manager->placeObject(object, false, false);
  104. }
  105. std::pair<bool, bool> ObstaclePlacer::verifyCoverage(const int3 & t) const
  106. {
  107. return {map.shouldBeBlocked(t), zone.areaPossible().contains(t)};
  108. }
  109. void ObstaclePlacer::postProcess(const rmg::Object & object)
  110. {
  111. //river processing
  112. riverManager = zone.getModificator<RiverPlacer>();
  113. if(riverManager)
  114. {
  115. const auto objTypeName = object.instances().front()->object().typeName;
  116. if(objTypeName == "mountain")
  117. riverManager->riverSource().unite(object.getArea());
  118. else if(objTypeName == "lake")
  119. riverManager->riverSink().unite(object.getArea());
  120. }
  121. }
  122. bool ObstaclePlacer::isProhibited(const rmg::Area & objArea) const
  123. {
  124. if(prohibitedArea.overlap(objArea))
  125. return true;
  126. if(!zone.area().contains(objArea))
  127. return true;
  128. return false;
  129. }
  130. VCMI_LIB_NAMESPACE_END