1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Do not place object visible tiles over the top of the map.

This commit is contained in:
Tomasz Zieliński 2023-04-10 19:26:53 +02:00
parent 9ea746a68c
commit 3c87b3934d
7 changed files with 57 additions and 1 deletions

View File

@ -133,6 +133,11 @@ int3 CGObjectInstance::getPosition() const
return pos;
}
int3 CGObjectInstance::getTopVisiblePos() const
{
return pos - appearance->getTopVisibleOffset();
}
void CGObjectInstance::setOwner(const PlayerColor & ow)
{
tempOwner = ow;

View File

@ -159,6 +159,7 @@ public:
bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) (h3m pos)
int3 visitablePos() const override;
int3 getPosition() const override;
int3 getTopVisiblePos() const;
bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) (h3m pos)
bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) (h3m pos)
std::set<int3> getBlockedPos() const; //returns set of positions blocked by this object

View File

@ -524,6 +524,22 @@ bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const
return dirMap[dy][dx] != 0;
}
void ObjectTemplate::calculateTopVisibleOffset()
{
for(int y = static_cast<int>(getHeight()) - 1; y >= 0; y--) //Templates start from bottom-right corner
{
for(int x = 0; x < static_cast<int>(getWidth()); x++)
{
if (isVisibleAt(x, y))
{
topVisibleOffset = int3(x, y, 0);
return;
}
}
}
topVisibleOffset = int3(0, 0, 0);
}
void ObjectTemplate::calculateVisitableOffset()
{
for(int y = 0; y < static_cast<int>(getHeight()); y++)
@ -559,6 +575,7 @@ void ObjectTemplate::recalculate()
calculateBlockedOffsets();
calculateBlockMapOffset();
calculateVisitableOffset();
calculateTopVisibleOffset();
if (visitable && visitDir == 0)
logMod->warn("Template for %s is visitable but has no visitable directions!", animationFile);

View File

@ -87,7 +87,12 @@ public:
inline int3 getBlockMapOffset() const
{
return blockMapOffset;
};
};
inline int3 getTopVisibleOffset() const
{
return topVisibleOffset;
}
// Checks if object is visitable from certain direction. X and Y must be between -1..+1
bool isVisitableFrom(si8 X, si8 Y) const;
@ -137,6 +142,7 @@ private:
std::set<int3> blockedOffsets;
int3 blockMapOffset;
int3 visitableOffset;
int3 topVisibleOffset;
void recalculate();
@ -146,6 +152,7 @@ private:
void calculateBlockedOffsets();
void calculateBlockMapOffset();
void calculateVisitableOffset();
void calculateTopVisibleOffset();
public:
template <typename Handler> void serialize(Handler &h, const int version)

View File

@ -112,6 +112,9 @@ int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object
continue;
obj.setPosition(tile);
if (obj.getVisibleTop().y < 0)
continue;
if(!searchArea.contains(obj.getArea()) || !searchArea.overlap(obj.getAccessibleArea()))
continue;
@ -131,6 +134,9 @@ int3 ObjectManager::findPlaceForObject(const rmg::Area & searchArea, rmg::Object
for(const auto & tile : searchArea.getTiles())
{
obj.setPosition(tile);
if (obj.getVisibleTop().y < 0)
continue;
if(!searchArea.contains(obj.getArea()) || !searchArea.overlap(obj.getAccessibleArea()))
continue;

View File

@ -45,6 +45,11 @@ const Area & Object::Instance::getBlockedArea() const
return dBlockedAreaCache;
}
int3 Object::Instance::getTopTile() const
{
return object().getTopVisiblePos();
}
int3 Object::Instance::getPosition(bool isAbsolute) const
{
if(isAbsolute)
@ -284,6 +289,19 @@ const Area & Object::getArea() const
return dFullAreaCache;
}
const int3 Object::getVisibleTop() const
{
int3 topTile(-1, 10000, -1); //Start at the bottom
for (const auto& i : dInstances)
{
if (i.getTopTile().y < topTile.y)
{
topTile = i.getTopTile();
}
}
return topTile;
}
void Object::Instance::finalize(RmgMap & map)
{
if(!map.isOnMap(getPosition(true)))

View File

@ -38,6 +38,7 @@ public:
void setTemplate(TerrainId terrain); //cache invalidation
void setAnyTemplate(); //cache invalidation
int3 getTopTile() const;
int3 getPosition(bool isAbsolute = false) const;
void setPosition(const int3 & position); //cache invalidation
void setPositionRaw(const int3 & position); //no cache invalidation
@ -75,6 +76,7 @@ public:
void setTemplate(const TerrainId & terrain);
const Area & getArea() const; //lazy cache invalidation
const int3 getVisibleTop() const;
void finalize(RmgMap & map);
void clear();