1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +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);
dRemovableAreaCache.translate(shift);
dFullAreaCache.translate(shift);
dBorderAboveCache.translate(shift);
dPosition = position;
for(auto& i : dInstances)
@ -386,6 +387,16 @@ const Area & Object::getArea() const
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
{
if (visibleTopOffset)
@ -445,6 +456,20 @@ uint32_t rmg::Object::getValue() const
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)
{
if(!map.isOnMap(getPosition(true)))
@ -501,6 +526,7 @@ void Object::clearCachedArea() const
dBlockVisitableCache.clear();
dVisitableCache.clear();
dRemovableAreaCache.clear();
dBorderAboveCache.clear();
}
void Object::clear()

View File

@ -38,6 +38,7 @@ public:
bool isBlockedVisitable() const;
bool isRemovable() const;
const Area & getAccessibleArea() const;
Area getBorderAbove() const;
void setTemplate(TerrainId terrain, CRandomGenerator &); //cache invalidation
void setAnyTemplate(CRandomGenerator &); //cache invalidation
@ -78,6 +79,7 @@ public:
const Area & getVisitableArea() const;
const Area & getRemovableArea() const;
const Area getEntrableArea() const;
const Area & getBorderAbove() const;
const int3 & getPosition() const;
void setPosition(const int3 & position);
@ -104,6 +106,7 @@ private:
mutable Area dBlockVisitableCache;
mutable Area dVisitableCache;
mutable Area dRemovableAreaCache;
mutable Area dBorderAboveCache;
int3 dPosition;
mutable std::optional<int3> visibleTopOffset;
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())
{
// Do not route road behind visitable tile
int3 visitablePos = instance->getVisitablePosition();
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));
});
auto borderAbove = instance->getBorderAbove();
rp->areaIsolated().unite(borderAbove);
}

View File

@ -77,11 +77,13 @@ bool RoadPlacer::createRoad(const int3 & 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
{
auto ret = 1.0f;
float weight = dst.dist2dSQ(src);
auto ret = weight * weight;
if (visitableTiles.contains(src) || visitableTiles.contains(dst))
{
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))
return -1.f;
// Add huge penalty for objects hiding roads
if (rmgObject.getBorderAbove().overlap(roads))
bestDistance /= 10.0f;
return bestDistance;
}, guarded, false, ObjectManager::OptimizeType::BOTH);
}