mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Support revealing a small area of the map
This commit is contained in:
parent
5268cb62a6
commit
4056cb80c9
3 changed files with 89 additions and 0 deletions
|
|
@ -2130,6 +2130,88 @@ public:
|
|||
SeeExploredEntities(p);
|
||||
}
|
||||
|
||||
// Convert world-space circle to tile-space bounds
|
||||
struct TileCircle
|
||||
{
|
||||
i32 centerX, centerZ;
|
||||
i32 radius;
|
||||
i32 squaredRadius;
|
||||
i32 minX, maxX, minZ, maxZ;
|
||||
};
|
||||
|
||||
TileCircle WorldToTileCircle(entity_pos_t worldX, entity_pos_t worldZ, entity_pos_t radius)
|
||||
{
|
||||
const i32 centerTileX = (worldX / LOS_TILE_SIZE).ToInt_RoundToNearest();
|
||||
const i32 centerTileZ = (worldZ / LOS_TILE_SIZE).ToInt_RoundToNearest();
|
||||
const i32 tileRadius = (radius / LOS_TILE_SIZE).ToInt_RoundToInfinity();
|
||||
|
||||
return {
|
||||
centerTileX,
|
||||
centerTileZ,
|
||||
tileRadius,
|
||||
tileRadius * tileRadius,
|
||||
std::max(centerTileX - tileRadius, 0),
|
||||
std::min(centerTileX + tileRadius, m_LosVerticesPerSide - 1),
|
||||
std::max(centerTileZ - tileRadius, 0),
|
||||
std::min(centerTileZ + tileRadius, m_LosVerticesPerSide - 1)
|
||||
};
|
||||
}
|
||||
|
||||
// Apply an action to every tile within the circle
|
||||
template<typename Func>
|
||||
void ForEachTileInCircle(const TileCircle& circle, Func&& func)
|
||||
{
|
||||
for (i32 tileZ = circle.minZ; tileZ <= circle.maxZ; ++tileZ)
|
||||
{
|
||||
const i32 deltaZ = tileZ - circle.centerZ;
|
||||
const i32 squaredDeltaZ = deltaZ * deltaZ;
|
||||
|
||||
for (i32 tileX = circle.minX; tileX <= circle.maxX; ++tileX)
|
||||
{
|
||||
if (LosIsOffWorld(tileX, tileZ))
|
||||
continue;
|
||||
|
||||
const i32 deltaX = tileX - circle.centerX;
|
||||
if (deltaX * deltaX + squaredDeltaZ > circle.squaredRadius)
|
||||
continue;
|
||||
|
||||
func(tileX, tileZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExploreCircle(player_id_t playerId, entity_pos_t worldX, entity_pos_t worldZ, entity_pos_t radius) override
|
||||
{
|
||||
if (playerId <= 0 || playerId > MAX_LOS_PLAYER_ID)
|
||||
return;
|
||||
|
||||
const TileCircle circle = WorldToTileCircle(worldX, worldZ, radius);
|
||||
const u32 exploredBitMask = static_cast<u32>(LosState::EXPLORED) << (2 * (playerId - 1));
|
||||
u32& exploredCount = m_ExploredVertices.at(playerId);
|
||||
bool hasChanges = false;
|
||||
|
||||
// Mark newly explored tiles and count them
|
||||
ForEachTileInCircle(circle, [&](i32 tileX, i32 tileZ)
|
||||
{
|
||||
u32& losState = m_LosState.get(tileX, tileZ);
|
||||
if (!(losState & exploredBitMask))
|
||||
{
|
||||
losState |= exploredBitMask;
|
||||
++exploredCount;
|
||||
hasChanges = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasChanges)
|
||||
return;
|
||||
|
||||
// Mark visibility dirty for affected regions
|
||||
ForEachTileInCircle(circle, [&](i32 tileX, i32 tileZ)
|
||||
{
|
||||
MarkVisibilityDirtyAroundTile(playerId, tileX, tileZ);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Force any entity in explored territory to appear for player p.
|
||||
* This is useful for miraging entities inside the territory borders at the beginning of a game,
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ DEFINE_INTERFACE_METHOD("GetGaiaAndNonGaiaEntities", ICmpRangeManager, GetGaiaAn
|
|||
DEFINE_INTERFACE_METHOD("SetDebugOverlay", ICmpRangeManager, SetDebugOverlay)
|
||||
DEFINE_INTERFACE_METHOD("ExploreMap", ICmpRangeManager, ExploreMap)
|
||||
DEFINE_INTERFACE_METHOD("ExploreTerritories", ICmpRangeManager, ExploreTerritories)
|
||||
DEFINE_INTERFACE_METHOD("ExploreCircle", ICmpRangeManager, ExploreCircle)
|
||||
DEFINE_INTERFACE_METHOD("SetLosRevealWholeMap", ICmpRangeManager, SetLosRevealWholeMap)
|
||||
DEFINE_INTERFACE_METHOD("GetLosRevealWholeMap", ICmpRangeManager, GetLosRevealWholeMap)
|
||||
DEFINE_INTERFACE_METHOD("SetLosRevealWholeMapForAll", ICmpRangeManager, SetLosRevealWholeMapForAll)
|
||||
|
|
|
|||
|
|
@ -333,6 +333,12 @@ public:
|
|||
*/
|
||||
virtual void ExploreTerritories() = 0;
|
||||
|
||||
/**
|
||||
* Explore a circular area of the map for the given player.
|
||||
* This marks the tiles as explored (fogged) but not necessarily visible.
|
||||
*/
|
||||
virtual void ExploreCircle(player_id_t p, entity_pos_t x, entity_pos_t z, entity_pos_t radius) = 0;
|
||||
|
||||
/**
|
||||
* Reveal the shore for specified player p.
|
||||
* This works like for entities: if RevealShore is called multiple times with enabled, it
|
||||
|
|
|
|||
Loading…
Reference in a new issue