Selaa lähdekoodia

First implementation that works

Tomasz Zieliński 1 vuosi sitten
vanhempi
sitoutus
67447acd0e

+ 5 - 1
lib/rmg/modificators/ObstaclePlacer.cpp

@@ -64,6 +64,10 @@ void ObstaclePlacer::process()
 		areaPossible->subtract(blockedArea);
 
 		prohibitedArea = zone.freePaths() + areaUsed + manager->getVisitableArea();
+		if (auto * rp = zone.getModificator<RoadPlacer>())
+		{
+			prohibitedArea.unite(rp->getRoads());
+		}
 
 		//Progressively block tiles, but make sure they don't seal any gap between blocks
 		rmg::Area toBlock;
@@ -116,7 +120,7 @@ void ObstaclePlacer::init()
 	DEPENDENCY(RoadPlacer);
 	if (zone.isUnderground())
 	{
-		DEPENDENCY(RockFiller);
+		DEPENDENCY_ALL(RockFiller);
 	}
 	else
 	{

+ 16 - 7
lib/rmg/modificators/RoadPlacer.cpp

@@ -34,6 +34,12 @@ void RoadPlacer::process()
 	connectRoads();
 }
 
+void RoadPlacer::postProcess()
+{
+	//Draw dirt roads if there are only mines
+	drawRoads(noRoadNodes);
+}
+
 void RoadPlacer::init()
 {
 }
@@ -140,8 +146,9 @@ void RoadPlacer::drawRoads(bool secondary)
 			return !terrain->isPassable() || !terrain->isLand();
 		});
 
-		zone.areaPossible()->subtract(roads);
-		zone.freePaths()->unite(roads);
+		// FIXME: This area should still be available after road is created
+		//zone.areaPossible()->subtract(roads);
+		//zone.freePaths()->unite(roads);
 	}
 
 	if(!generator.getMapGenOptions().isRoadEnabled())
@@ -175,12 +182,11 @@ void RoadPlacer::drawRoads(bool secondary)
 void RoadPlacer::addRoadNode(const int3& node)
 {
 	RecursiveLock lock(externalAccessMutex);
-	roadNodes.insert(node);
+	roadNodes.push_back(node);
 }
 
 void RoadPlacer::connectRoads()
 {
-	bool noRoadNodes = false;
 	//Assumes objects are already placed
 	if(roadNodes.size() < 2)
 	{
@@ -220,13 +226,16 @@ void RoadPlacer::connectRoads()
 		}
 	}
 	
-	//Draw dirt roads if there are only mines
-	drawRoads(noRoadNodes);
+	if (!zone.isUnderground())
+	{
+		// Otherwise roads will be drawn only after rock is placed
+		postProcess();
+	}
 }
 
 char RoadPlacer::dump(const int3 & t)
 {
-	if(roadNodes.count(t))
+	if(vstd::contains(roadNodes, t))
 		return '@';
 	if(roads.contains(t))
 		return '+';

+ 4 - 1
lib/rmg/modificators/RoadPlacer.h

@@ -19,6 +19,7 @@ public:
 	MODIFICATOR(RoadPlacer);
 	
 	void process() override;
+	void postProcess();
 	void init() override;
 	char dump(const int3 &) override;
 	
@@ -36,11 +37,13 @@ protected:
 	void drawRoads(bool secondary = false); //actually updates tiles
 
 protected:
-	rmg::Tileset roadNodes; //tiles to be connected with roads
+	std::vector<int3> roadNodes; //tiles to be connected with roads
 	rmg::Area roads; //all tiles with roads
 	rmg::Area areaRoads;
 	rmg::Area isolated;
 	rmg::Area visitableTiles; // Tiles occupied by removable or passable objects
+
+	bool noRoadNodes = false;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 9 - 2
lib/rmg/modificators/RockFiller.cpp

@@ -14,6 +14,7 @@
 #include "TreasurePlacer.h"
 #include "ObjectManager.h"
 #include "RiverPlacer.h"
+#include "RoadPlacer.h"
 #include "../RmgMap.h"
 #include "../CMapGenerator.h"
 #include "../Functions.h"
@@ -35,7 +36,7 @@ void RockFiller::process()
 void RockFiller::processMap()
 {
 	//Merge all areas
-	for(auto & z : map.getZones())
+	for(auto & z : map.getZonesOnLevel(1))
 	{
 		auto zone = z.second;
 		if(auto * m = zone->getModificator<RockPlacer>())
@@ -45,7 +46,7 @@ void RockFiller::processMap()
 		}
 	}
 	
-	for(auto & z : map.getZones())
+	for(auto & z : map.getZonesOnLevel(1))
 	{
 		auto zone = z.second;
 		if(auto * m = zone->getModificator<RockPlacer>())
@@ -56,6 +57,12 @@ void RockFiller::processMap()
 
 			m->postProcess();
 		}
+
+		// Draw roads after rock is placed
+		if(auto * rp = zone->getModificator<RoadPlacer>())
+		{
+			rp->postProcess();
+		}
 	}
 }
 

+ 18 - 7
lib/rmg/modificators/RockPlacer.cpp

@@ -30,14 +30,21 @@ void RockPlacer::process()
 {
 	blockRock();
 }
+
 void RockPlacer::blockRock()
 {
 	rockTerrain = VLC->terrainTypeHandler->getById(zone.getTerrainType())->rockTerrain;
 	assert(!VLC->terrainTypeHandler->getById(rockTerrain)->isPassable());
 
 	accessibleArea = zone.freePaths() + zone.areaUsed();
+	if(auto * rp = zone.getModificator<RoadPlacer>())
+	{
+		accessibleArea.unite(rp->getRoads());
+	}
 	if(auto * m = zone.getModificator<ObjectManager>())
+	{
 		accessibleArea.unite(m->getVisitableArea());
+	}
 
 	//negative approach - create rock tiles first, then make sure all accessible tiles have no rock
 	rockArea = zone.area()->getSubarea([this](const int3 & t)
@@ -55,6 +62,12 @@ void RockPlacer::postProcess()
 		{
 			return !map.getTile(t).terType->isPassable();
 		});
+
+		// Do not place rock on roads
+		if(auto * rp = zone.getModificator<RoadPlacer>())
+		{
+			rockArea.subtract(rp->getRoads());
+		}
 		
 		zone.areaUsed()->unite(rockArea);
 		zone.areaPossible()->subtract(rockArea);
@@ -70,15 +83,13 @@ void RockPlacer::postProcess()
 
 void RockPlacer::init()
 {
-	for (const auto& zone : map.getZones())
+	DEPENDENCY(RoadPlacer);
+	for (const auto& zone : map.getZonesOnLevel(1))
 	{
-		if (zone.second->isUnderground())
+		auto * tp = zone.second->getModificator<TreasurePlacer>();
+		if (tp)
 		{
-			auto * tp = zone.second->getModificator<TreasurePlacer>();
-			if (tp)
-			{
-				dependency(tp);
-			}
+			dependency(tp);
 		}
 	}
 }

+ 7 - 1
lib/rmg/modificators/TreasurePlacer.cpp

@@ -937,7 +937,7 @@ void TreasurePlacer::createTreasures(ObjectManager& manager)
 
 				if (guarded)
 				{
-					// TODO: Guard cannot be adjacent to road, but blocked side of an object could be
+					// Guard cannot be adjacent to road, but blocked side of an object could be
 					searchArea.subtract(roads);
 
 					path = manager.placeAndConnectObject(searchArea, rmgObject, [this, &rmgObject, &minDistance, &manager, &nextToRoad](const int3& tile)
@@ -967,6 +967,12 @@ void TreasurePlacer::createTreasures(ObjectManager& manager)
 				}
 				else
 				{
+					// Do not place non-removable objects on roads
+					if (!rmgObject.getRemovableArea().contains(rmgObject.getArea()))
+					{
+						searchArea.subtract(roads);
+					}
+
 					path = manager.placeAndConnectObject(searchArea, rmgObject, minDistance, guarded, false, ObjectManager::OptimizeType::DISTANCE);
 				}
 			}