From 62490683ceafeafac65cf939f67264a6aff91447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 16 Mar 2023 16:20:11 +0100 Subject: [PATCH 1/3] Place objects away from zone guard in both zones, not only the where it is placed. --- lib/rmg/ConnectionsPlacer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rmg/ConnectionsPlacer.cpp b/lib/rmg/ConnectionsPlacer.cpp index f5131935c..bee600bbf 100644 --- a/lib/rmg/ConnectionsPlacer.cpp +++ b/lib/rmg/ConnectionsPlacer.cpp @@ -150,6 +150,8 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con rmg::Object monster(*monsterType); monster.setPosition(guardPos); manager.placeObject(monster, false, true); + //Place objects away from the monster in the other zone, too + otherZone->getModificator()->updateDistances(monster); } else { From f2dc9cb48eb13e7481006c27bba8b8962a2e6d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Thu, 16 Mar 2023 18:42:28 +0100 Subject: [PATCH 2/3] - Place Subterranean Gates as far from other objects as possible - Added minimum distance between zone guards --- lib/rmg/ConnectionsPlacer.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/rmg/ConnectionsPlacer.cpp b/lib/rmg/ConnectionsPlacer.cpp index bee600bbf..20ce47f14 100644 --- a/lib/rmg/ConnectionsPlacer.cpp +++ b/lib/rmg/ConnectionsPlacer.cpp @@ -100,15 +100,20 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con borderPos = *RandomGeneratorUtil::nextItem(directConnectionIterator->second, generator.rand); guardPos = zone.areaPossible().nearest(borderPos); assert(borderPos != guardPos); - - auto safetyGap = rmg::Area({guardPos}); - safetyGap.unite(safetyGap.getBorderOutside()); - safetyGap.intersect(zone.areaPossible()); - if(!safetyGap.empty()) + + float dist = map.getTile(guardPos).getNearestObjectDistance(); + if (dist >= 3) //Don't place guards at adjacent tiles { - safetyGap.intersect(otherZone->areaPossible()); - if(safetyGap.empty()) - break; //successfull position + + auto safetyGap = rmg::Area({ guardPos }); + safetyGap.unite(safetyGap.getBorderOutside()); + safetyGap.intersect(zone.areaPossible()); + if (!safetyGap.empty()) + { + safetyGap.intersect(otherZone->areaPossible()); + if (safetyGap.empty()) + break; //successfull position + } } //failed position @@ -227,8 +232,10 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c rmg::Path path1 = manager.placeAndConnectObject(commonArea, rmgGate1, [this, minDist, &path2, &rmgGate1, &zShift, guarded2, &managerOther, &rmgGate2 ](const int3 & tile) { auto ti = map.getTile(tile); + auto otherTi = map.getTile(tile - zShift); float dist = ti.getNearestObjectDistance(); - if(dist < minDist) + float otherDist = otherTi.getNearestObjectDistance(); + if(dist < minDist || otherDist < minDist) return -1.f; rmg::Area toPlace(rmgGate1.getArea() + rmgGate1.getAccessibleArea()); @@ -236,8 +243,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c path2 = managerOther.placeAndConnectObject(toPlace, rmgGate2, minDist, guarded2, true, ObjectManager::OptimizeType::NONE); - return path2.valid() ? 1.f : -1.f; - }, guarded1, true, ObjectManager::OptimizeType::NONE); + return path2.valid() ? (dist + otherDist) : -1.f; + }, guarded1, true, ObjectManager::OptimizeType::DISTANCE); if(path1.valid() && path2.valid()) { From e1ced317a1dec2c9633a09a007eef0d1dd48678a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Zieli=C5=84ski?= Date: Sat, 18 Mar 2023 21:56:09 +0100 Subject: [PATCH 3/3] Few tweaks for boat placement to keep distance between it and other objects, especially guards. --- lib/rmg/WaterProxy.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/lib/rmg/WaterProxy.cpp b/lib/rmg/WaterProxy.cpp index 6e9263cf1..02e916f3b 100644 --- a/lib/rmg/WaterProxy.cpp +++ b/lib/rmg/WaterProxy.cpp @@ -202,24 +202,28 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, RouteInfo & info) auto * manager = zone.getModificator(); if(!manager) return false; - + auto subObjects = VLC->objtypeh->knownSubObjects(Obj::BOAT); auto * boat = dynamic_cast(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(subObjects, generator.rand))->create()); rmg::Object rmgObject(*boat); rmgObject.setTemplate(zone.getTerrainType()); - + auto waterAvailable = zone.areaPossible() + zone.freePaths(); rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles coast.intersect(land.areaPossible() + land.freePaths()); //having only available land tiles - auto boardingPositions = coast.getSubarea([&waterAvailable](const int3 & tile) //tiles where boarding is possible - { - rmg::Area a({tile}); - a = a.getBorderOutside(); - a.intersect(waterAvailable); - return !a.empty(); - }); - + auto boardingPositions = coast.getSubarea([&waterAvailable, this](const int3 & tile) //tiles where boarding is possible + { + //We don't want place boat right to any land object, especiallly the zone guard + if (map.getTile(tile).getNearestObjectDistance() <= 3) + return false; + + rmg::Area a({tile}); + a = a.getBorderOutside(); + a.intersect(waterAvailable); + return !a.empty(); + }); + while(!boardingPositions.empty()) { auto boardingPosition = *boardingPositions.getTiles().begin(); @@ -232,27 +236,28 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, RouteInfo & info) boardingPositions.erase(boardingPosition); continue; } - + //try to place boat at water, create paths on water and land - auto path = manager->placeAndConnectObject(shipPositions, rmgObject, 2, false, true, ObjectManager::OptimizeType::NONE); + auto path = manager->placeAndConnectObject(shipPositions, rmgObject, 4, false, true, ObjectManager::OptimizeType::NONE); auto landPath = land.searchPath(boardingPosition, false); if(!path.valid() || !landPath.valid()) { boardingPositions.erase(boardingPosition); continue; } - + info.blocked = rmgObject.getArea(); info.visitable = rmgObject.getVisitablePosition(); info.boarding = boardingPosition; info.water = shipPositions; - + zone.connectPath(path); land.connectPath(landPath); manager->placeObject(rmgObject, false, true); + land.getModificator()->updateDistances(rmgObject); //Keep land objects away from the boat break; } - + return !boardingPositions.empty(); }