mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
+ Maintain clear perimeter of a treasure pile.
+ Make sure that separate blocked areas remain unconnected so it's possible to pass between them.
This commit is contained in:
@@ -166,7 +166,6 @@ int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: Race condition for tiles? For Area?
|
||||
if(result.valid())
|
||||
obj.setPosition(result);
|
||||
return result;
|
||||
@@ -213,6 +212,55 @@ rmg::Path ObjectManager::placeAndConnectObject(const rmg::Area & searchArea, rmg
|
||||
return -1.f;
|
||||
}
|
||||
|
||||
rmg::Area perimeter;
|
||||
rmg::Area areaToBlock;
|
||||
if (obj.isGuarded())
|
||||
{
|
||||
auto guardedArea = obj.instances().back()->getAccessibleArea();
|
||||
guardedArea.add(obj.instances().back()->getVisitablePosition());
|
||||
areaToBlock = obj.getAccessibleArea(true);
|
||||
areaToBlock.subtract(guardedArea);
|
||||
|
||||
if (!areaToBlock.empty())
|
||||
{
|
||||
perimeter = areaToBlock;
|
||||
perimeter.unite(areaToBlock.getBorderOutside());
|
||||
//We could have added border around guard
|
||||
perimeter.subtract(guardedArea);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
perimeter = obj.getArea();
|
||||
perimeter.subtract(obj.getAccessibleArea());
|
||||
if (!perimeter.empty())
|
||||
{
|
||||
perimeter.unite(perimeter.getBorderOutside());
|
||||
perimeter.subtract(obj.getAccessibleArea());
|
||||
}
|
||||
}
|
||||
//Check if perimeter of the object intersects with more than one blocked areas
|
||||
|
||||
auto tiles = perimeter.getTiles();
|
||||
vstd::erase_if(tiles, [this](const int3& tile) -> bool
|
||||
{
|
||||
//Out-of-map area also is an obstacle
|
||||
if (!map.isOnMap(tile))
|
||||
return false;
|
||||
return !(map.isBlocked(tile) || map.isUsed(tile));
|
||||
});
|
||||
|
||||
if (!tiles.empty())
|
||||
{
|
||||
rmg::Area border(tiles);
|
||||
border.subtract(areaToBlock);
|
||||
if (!border.connected())
|
||||
{
|
||||
//We don't want to connect two blocked areas to create impassable obstacle
|
||||
return -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
return dist;
|
||||
}, isGuarded, onlyStraight, optimizer);
|
||||
}
|
||||
@@ -237,7 +285,7 @@ rmg::Path ObjectManager::placeAndConnectObject(const rmg::Area & searchArea, rmg
|
||||
accessibleArea.intersect(guardedArea);
|
||||
accessibleArea.add(obj.instances().back()->getPosition(true));
|
||||
}
|
||||
|
||||
|
||||
auto path = zone.searchPath(accessibleArea, onlyStraight, [&obj, isGuarded](const int3 & t)
|
||||
{
|
||||
if(isGuarded)
|
||||
|
||||
Reference in New Issue
Block a user