Переглянути джерело

Try to not route roads through passable objects

Tomasz Zieliński 1 рік тому
батько
коміт
8f1638f78a

+ 5 - 3
lib/rmg/modificators/ObjectManager.cpp

@@ -597,7 +597,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 	{
 		objectsVisitableArea.add(instance->getVisitablePosition());
 		objects.push_back(&instance->object());
-		if(auto * m = zone.getModificator<RoadPlacer>())
+		if(auto * rp = zone.getModificator<RoadPlacer>())
 		{
 			if (instance->object().blockVisit && !instance->object().removable)
 			{
@@ -607,7 +607,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 			else if(instance->object().appearance->isVisitableFromTop())
 			{
 				//Passable objects
-				m->areaForRoads().add(instance->getVisitablePosition());
+				rp->areaForRoads().add(instance->getVisitablePosition());
 			}
 			else if(!instance->object().appearance->isVisitableFromTop())
 			{
@@ -621,8 +621,10 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 					(!instance->object().blockingAt(tile + int3(0, 1, 0)) && 
 					instance->object().blockingAt(tile));
 				});				
-				m->areaIsolated().unite(borderAbove);
+				rp->areaIsolated().unite(borderAbove);
 			}
+
+			rp->areaVisitable().add(instance->getVisitablePosition());
 		}
 
 		switch (instance->object().ID.toEnum())

+ 22 - 4
lib/rmg/modificators/RoadPlacer.cpp

@@ -52,6 +52,11 @@ rmg::Area & RoadPlacer::areaIsolated()
 	return isolated;
 }
 
+rmg::Area & RoadPlacer::areaVisitable()
+{
+	return visitableTiles;
+}
+
 const rmg::Area & RoadPlacer::getRoads() const
 {
 	return roads;
@@ -64,7 +69,9 @@ bool RoadPlacer::createRoad(const int3 & dst)
 	rmg::Path path(searchArea);
 	path.connect(roads);
 
-	auto simpleRoutig = [this](const int3& src, const int3& dst)
+	const float VISITABLE_PENALTY = 1.33f;
+
+	auto simpleRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst)
 	{
 		if(areaIsolated().contains(dst))
 		{
@@ -72,14 +79,19 @@ bool RoadPlacer::createRoad(const int3 & dst)
 		}
 		else
 		{
-			return 1.0f;
+			auto ret = 1.0f;
+			if (visitableTiles.contains(src) || visitableTiles.contains(dst))
+			{
+				ret *= VISITABLE_PENALTY;
+			}
+			return ret;
 		}
 	};
 	
 	auto res = path.search(dst, true, simpleRoutig);
 	if(!res.valid())
 	{
-		auto desperateRoutig = [this](const int3& src, const int3& dst) -> float
+		auto desperateRoutig = [this, VISITABLE_PENALTY](const int3& src, const int3& dst) -> float
 		{
 			//Do not allow connections straight up through object not visitable from top
 			if(std::abs((src - dst).y) == 1)
@@ -98,7 +110,13 @@ bool RoadPlacer::createRoad(const int3 & dst)
 			}
 
 			float weight = dst.dist2dSQ(src);
-			return weight * weight;
+
+			auto ret =  weight * weight;
+			if (visitableTiles.contains(src) || visitableTiles.contains(dst))
+			{
+				ret *= VISITABLE_PENALTY;
+			}
+			return ret;
 		};
 		res = path.search(dst, false, desperateRoutig);
 

+ 3 - 0
lib/rmg/modificators/RoadPlacer.h

@@ -25,8 +25,10 @@ public:
 	void addRoadNode(const int3 & node);
 	void connectRoads(); //fills "roads" according to "roadNodes"
 	
+	// TODO: Use setters?
 	rmg::Area & areaForRoads();
 	rmg::Area & areaIsolated();
+	rmg::Area & areaVisitable();
 	const rmg::Area & getRoads() const;
 	
 protected:
@@ -38,6 +40,7 @@ protected:
 	rmg::Area roads; //all tiles with roads
 	rmg::Area areaRoads;
 	rmg::Area isolated;
+	rmg::Area visitableTiles; // Tiles occupied by removable or passable objects
 };
 
 VCMI_LIB_NAMESPACE_END