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:
parent
d5b6e31223
commit
186b6629c7
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user