1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-06 09:09:40 +02:00

Do not hide roads behind objects

This commit is contained in:
Tomasz Zieliński
2024-05-01 12:15:07 +02:00
parent d5b6e31223
commit 186b6629c7
5 changed files with 38 additions and 11 deletions

View File

@@ -359,6 +359,7 @@ void Object::setPosition(const int3 & position)
dVisitableCache.translate(shift); dVisitableCache.translate(shift);
dRemovableAreaCache.translate(shift); dRemovableAreaCache.translate(shift);
dFullAreaCache.translate(shift); dFullAreaCache.translate(shift);
dBorderAboveCache.translate(shift);
dPosition = position; dPosition = position;
for(auto& i : dInstances) for(auto& i : dInstances)
@@ -386,6 +387,16 @@ const Area & Object::getArea() const
return dFullAreaCache; return dFullAreaCache;
} }
const Area & Object::getBorderAbove() const
{
if(dBorderAboveCache.empty())
{
for(const auto & instance : dInstances)
dBorderAboveCache.unite(instance.getBorderAbove());
}
return dBorderAboveCache;
}
const int3 Object::getVisibleTop() const const int3 Object::getVisibleTop() const
{ {
if (visibleTopOffset) if (visibleTopOffset)
@@ -445,6 +456,20 @@ uint32_t rmg::Object::getValue() const
return value; return value;
} }
rmg::Area Object::Instance::getBorderAbove() const
{
int3 visitablePos = getVisitablePosition();
auto areaVisitable = rmg::Area({visitablePos});
auto borderAbove = areaVisitable.getBorderOutside();
vstd::erase_if(borderAbove, [&](const int3 & tile)
{
return tile.y >= visitablePos.y ||
(!object().blockingAt(tile + int3(0, 1, 0)) &&
object().blockingAt(tile));
});
return borderAbove;
}
void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng) void Object::Instance::finalize(RmgMap & map, CRandomGenerator & rng)
{ {
if(!map.isOnMap(getPosition(true))) if(!map.isOnMap(getPosition(true)))
@@ -501,6 +526,7 @@ void Object::clearCachedArea() const
dBlockVisitableCache.clear(); dBlockVisitableCache.clear();
dVisitableCache.clear(); dVisitableCache.clear();
dRemovableAreaCache.clear(); dRemovableAreaCache.clear();
dBorderAboveCache.clear();
} }
void Object::clear() void Object::clear()

View File

@@ -38,6 +38,7 @@ public:
bool isBlockedVisitable() const; bool isBlockedVisitable() const;
bool isRemovable() const; bool isRemovable() const;
const Area & getAccessibleArea() const; const Area & getAccessibleArea() const;
Area getBorderAbove() const;
void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation
void setAnyTemplate(CRandomGenerator &); //cache invalidation void setAnyTemplate(CRandomGenerator &); //cache invalidation
@@ -78,6 +79,7 @@ public:
const Area & getVisitableArea() const; const Area & getVisitableArea() const;
const Area & getRemovableArea() const; const Area & getRemovableArea() const;
const Area getEntrableArea() const; const Area getEntrableArea() const;
const Area & getBorderAbove() const;
const int3 & getPosition() const; const int3 & getPosition() const;
void setPosition(const int3 & position); void setPosition(const int3 & position);
@@ -104,6 +106,7 @@ private:
mutable Area dBlockVisitableCache; mutable Area dBlockVisitableCache;
mutable Area dVisitableCache; mutable Area dVisitableCache;
mutable Area dRemovableAreaCache; mutable Area dRemovableAreaCache;
mutable Area dBorderAboveCache;
int3 dPosition; int3 dPosition;
mutable std::optional<int3> visibleTopOffset; mutable std::optional<int3> visibleTopOffset;
mutable std::list<Object::Instance*> cachedInstanceList; mutable std::list<Object::Instance*> cachedInstanceList;

View File

@@ -648,15 +648,7 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
else if(!instance->object().appearance->isVisitableFromTop()) else if(!instance->object().appearance->isVisitableFromTop())
{ {
// Do not route road behind visitable tile // Do not route road behind visitable tile
int3 visitablePos = instance->getVisitablePosition(); auto borderAbove = instance->getBorderAbove();
auto areaVisitable = rmg::Area({visitablePos});
auto borderAbove = areaVisitable.getBorderOutside();
vstd::erase_if(borderAbove, [&](const int3 & tile)
{
return tile.y >= visitablePos.y ||
(!instance->object().blockingAt(tile + int3(0, 1, 0)) &&
instance->object().blockingAt(tile));
});
rp->areaIsolated().unite(borderAbove); rp->areaIsolated().unite(borderAbove);
} }

View File

@@ -77,11 +77,13 @@ bool RoadPlacer::createRoad(const int3 & dst)
{ {
if(areaIsolated().contains(dst)) if(areaIsolated().contains(dst))
{ {
return 1000.0f; //Do not route road behind objects that are not visitable from top return 1000.0f; //Do not route road behind objects that are not visitable from top, such as Monoliths
} }
else else
{ {
auto ret = 1.0f; float weight = dst.dist2dSQ(src);
auto ret = weight * weight;
if (visitableTiles.contains(src) || visitableTiles.contains(dst)) if (visitableTiles.contains(src) || visitableTiles.contains(dst))
{ {
ret *= VISITABLE_PENALTY; ret *= VISITABLE_PENALTY;

View File

@@ -966,6 +966,10 @@ void TreasurePlacer::createTreasures(ObjectManager& manager)
if (zone.freePaths()->overlap(areaToBlock) || roads.overlap(areaToBlock) || manager.getVisitableArea().overlap(areaToBlock)) if (zone.freePaths()->overlap(areaToBlock) || roads.overlap(areaToBlock) || manager.getVisitableArea().overlap(areaToBlock))
return -1.f; return -1.f;
// Add huge penalty for objects hiding roads
if (rmgObject.getBorderAbove().overlap(roads))
bestDistance /= 10.0f;
return bestDistance; return bestDistance;
}, guarded, false, ObjectManager::OptimizeType::BOTH); }, guarded, false, ObjectManager::OptimizeType::BOTH);
} }