ObstaclePlacer.cpp 3.3 KB

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