From 0e388826946aa320f5a510379c13811677382878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 2 Jan 2025 17:18:06 +0100 Subject: [PATCH 1/4] Fix blocked paths to objects at the bottom of the zone --- lib/rmg/RmgObject.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/rmg/RmgObject.cpp b/lib/rmg/RmgObject.cpp index 4d81b8c2e..fd97f2821 100644 --- a/lib/rmg/RmgObject.cpp +++ b/lib/rmg/RmgObject.cpp @@ -271,6 +271,11 @@ const int3 & Object::getPosition() const int3 Object::getVisitablePosition() const { assert(!dInstances.empty()); + + // FIXME: This doesn't take into account Hota monster offset + if (guarded) + return getGuardPos(); + for(const auto & instance : dInstances) if(!getArea().contains(instance.getVisitablePosition())) return instance.getVisitablePosition(); From ce003af4b98228e03dbaac04006cebf3b9017248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 2 Jan 2025 17:41:01 +0100 Subject: [PATCH 2/4] Heavier penalty for routing roads behind monoliths --- lib/rmg/modificators/RoadPlacer.cpp | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/rmg/modificators/RoadPlacer.cpp b/lib/rmg/modificators/RoadPlacer.cpp index a2a404766..c58401358 100644 --- a/lib/rmg/modificators/RoadPlacer.cpp +++ b/lib/rmg/modificators/RoadPlacer.cpp @@ -76,25 +76,35 @@ bool RoadPlacer::createRoad(const int3 & destination) auto simpleRoutig = [this, &border](const int3& src, const int3& dst) { - if(areaIsolated().contains(dst)) + if(std::abs((src - dst).y) == 1) { - return 1000.0f; //Do not route road behind objects that are not visitable from top, such as Monoliths + //Do not allow connections straight up through object not visitable from top + if(areaIsolated().contains(dst) || areaIsolated().contains(src)) + { + return 1e12f; + } } else { - float ret = dst.dist2d(src); - - if (visitableTiles.contains(src) || visitableTiles.contains(dst)) + if(areaIsolated().contains(dst)) { - ret *= VISITABLE_PENALTY; + //Simply do not route road behind objects that are not visitable from top, such as Monoliths + return 1e6f; } - float dist = border.distanceSqr(dst); - if(dist > 1.0f) - { - ret /= dist; - } - return ret; } + + float ret = dst.dist2d(src); + + if (visitableTiles.contains(src) || visitableTiles.contains(dst)) + { + ret *= VISITABLE_PENALTY; + } + float dist = border.distanceSqr(dst); + if(dist > 1.0f) + { + ret /= dist; + } + return ret; }; auto res = path.search(destination, true, simpleRoutig); From a88a994d7592172a864ce84f2d3cf9e700591600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 2 Jan 2025 18:12:40 +0100 Subject: [PATCH 3/4] Proper fix for the issue --- lib/rmg/modificators/ObjectManager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/rmg/modificators/ObjectManager.cpp b/lib/rmg/modificators/ObjectManager.cpp index b6dd55e02..678016732 100644 --- a/lib/rmg/modificators/ObjectManager.cpp +++ b/lib/rmg/modificators/ObjectManager.cpp @@ -418,12 +418,14 @@ bool ObjectManager::createMonoliths() logGlobal->error("Failed to fill zone %d due to lack of space", zone.getId()); return false; } + + // Object must be placed first so that curved path won't go through occupied tiles + placeObject(rmgObject, guarded, true, objInfo.createRoad); - // Once it can be created, replace with curved path + // Once it can be created, replace with curved path. replaceWithCurvedPath(path, zone, rmgObject.getVisitablePosition()); zone.connectPath(path); - placeObject(rmgObject, guarded, true, objInfo.createRoad); } vstd::erase_if(requiredObjects, [](const auto & objInfo) @@ -452,6 +454,8 @@ bool ObjectManager::createRequiredObjects() logGlobal->error("Failed to fill zone %d due to lack of space", zone.getId()); return false; } + + placeObject(rmgObject, guarded, true, objInfo.createRoad); if (objInfo.createRoad) { // Once valid path can be created, replace with curved path @@ -459,7 +463,6 @@ bool ObjectManager::createRequiredObjects() } zone.connectPath(path); - placeObject(rmgObject, guarded, true, objInfo.createRoad); for(const auto & nearby : nearbyObjects) { From 685403c588bd6f2211131f4f0678baa0d68cd407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 2 Jan 2025 18:12:59 +0100 Subject: [PATCH 4/4] Cleanup --- lib/rmg/Functions.cpp | 2 +- lib/rmg/modificators/ObjectManager.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/rmg/Functions.cpp b/lib/rmg/Functions.cpp index 2d76d2f49..4728b1e3c 100644 --- a/lib/rmg/Functions.cpp +++ b/lib/rmg/Functions.cpp @@ -24,7 +24,7 @@ VCMI_LIB_NAMESPACE_BEGIN -void replaceWithCurvedPath(rmg::Path & path, const Zone & zone, const int3 & src, bool onlyStraight) +void replaceWithCurvedPath(rmg::Path & path, const Zone & zone, const int3 & src, bool onlyStraight /* = true */) { auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder()); auto pathArea = zone.areaForRoads(); diff --git a/lib/rmg/modificators/ObjectManager.cpp b/lib/rmg/modificators/ObjectManager.cpp index 678016732..4071da681 100644 --- a/lib/rmg/modificators/ObjectManager.cpp +++ b/lib/rmg/modificators/ObjectManager.cpp @@ -634,7 +634,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD for (auto id : adjacentZones) { auto otherZone = map.getZones().at(id); - if ((otherZone->getType() == ETemplateZoneType::WATER) == (zone.getType() == ETemplateZoneType::WATER)) + if ((otherZone->getType() == ETemplateZoneType::WATER) == (zone.getType() == ETemplateZoneType::WATER)) { // Do not update other zone if only one is water auto manager = otherZone->getModificator(); @@ -675,6 +675,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD if (object.isGuarded()) { + // Do not route roads through guarded objects rp->areaVisitable().add(instance->getVisitablePosition()); } }