Make the Ptolemaic lighthouse reveal the shore on the entire map.
Fixes #3174 This was SVN commit r16628.
This commit is contained in:
parent
4db041e3c6
commit
642500b49e
@ -17,7 +17,7 @@
|
||||
<GenericName>Lighthouse</GenericName>
|
||||
<SpecificName>Pharos</SpecificName>
|
||||
<Classes datatype="tokens">Lighthouse Town -City</Classes>
|
||||
<Tooltip>Build along the shore to reveal the shorelines over the entire map (Not implemented). Very large vision range: 180 meters.</Tooltip>
|
||||
<Tooltip>Build along the shore to reveal the shorelines over the entire map. Very large vision range: 180 meters.</Tooltip>
|
||||
<History>The Ptolemaic dynasty in Egypt built the magnificent Lighthouse of Alexandria near the harbor mouth of that Nile Delta city. This structure could be seen for many kilometers out to sea and was one of the Seven Wonders of the World.</History>
|
||||
<Icon>structures/lighthouse.png</Icon>
|
||||
<RequiredTechnology>phase_town</RequiredTechnology>
|
||||
@ -41,6 +41,7 @@
|
||||
</TerritoryInfluence>
|
||||
<Vision>
|
||||
<Range>180</Range>
|
||||
<RevealShore>true</RevealShore>
|
||||
</Vision>
|
||||
<VisualActor>
|
||||
<Actor>structures/ptolemies/lighthouse.xml</Actor>
|
||||
|
@ -512,7 +512,12 @@ void CTemplateLoader::CopyFoundationSubset(CParamNode& out, const CParamNode& in
|
||||
// Foundations should be visible themselves in fog-of-war if their base template is,
|
||||
// but shouldn't have any vision range
|
||||
if (out.GetChild("Entity").GetChild("Vision").IsOk())
|
||||
{
|
||||
CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range></Vision></Entity>");
|
||||
// Foundations should not have special vision capabilities either
|
||||
if (out.GetChild("Entity").GetChild("Vision").GetChild("RevealShore").IsOk())
|
||||
CParamNode::LoadXMLString(out, "<Entity><Vision><RevealShore>false</RevealShore></Vision></Entity>");
|
||||
}
|
||||
}
|
||||
|
||||
void CTemplateLoader::CopyConstructionSubset(CParamNode& out, const CParamNode& in)
|
||||
|
@ -306,6 +306,121 @@ const Grid<u16>& CCmpPathfinder::GetPassabilityGrid()
|
||||
return *m_Grid;
|
||||
}
|
||||
|
||||
Grid<u16> CCmpPathfinder::ComputeShoreGrid(bool expandOnWater)
|
||||
{
|
||||
PROFILE3("ComputeShoreGrid");
|
||||
|
||||
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
|
||||
|
||||
// TODO: these bits should come from ICmpTerrain
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
// avoid integer overflow in intermediate calculation
|
||||
const u16 shoreMax = 32767;
|
||||
|
||||
// First pass - find underwater tiles
|
||||
Grid<bool> waterGrid(m_MapSize, m_MapSize);
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < m_MapSize; ++i)
|
||||
{
|
||||
fixed x, z;
|
||||
TileCenter(i, j, x, z);
|
||||
|
||||
bool underWater = cmpWaterManager && (cmpWaterManager->GetWaterLevel(x, z) > terrain.GetExactGroundLevelFixed(x, z));
|
||||
waterGrid.set(i, j, underWater);
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass - find shore tiles
|
||||
Grid<u16> shoreGrid(m_MapSize, m_MapSize);
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < m_MapSize; ++i)
|
||||
{
|
||||
// Find a land tile
|
||||
if (!waterGrid.get(i, j))
|
||||
{
|
||||
// If it's bordered by water, it's a shore tile
|
||||
if ((i > 0 && waterGrid.get(i-1, j)) || (i > 0 && j < m_MapSize-1 && waterGrid.get(i-1, j+1)) || (i > 0 && j > 0 && waterGrid.get(i-1, j-1))
|
||||
|| (i < m_MapSize-1 && waterGrid.get(i+1, j)) || (i < m_MapSize-1 && j < m_MapSize-1 && waterGrid.get(i+1, j+1)) || (i < m_MapSize-1 && j > 0 && waterGrid.get(i+1, j-1))
|
||||
|| (j > 0 && waterGrid.get(i, j-1)) || (j < m_MapSize-1 && waterGrid.get(i, j+1))
|
||||
)
|
||||
shoreGrid.set(i, j, 0);
|
||||
else
|
||||
shoreGrid.set(i, j, shoreMax);
|
||||
}
|
||||
// If we want to expand on water, we want water tiles not to be shore tiles
|
||||
else if (expandOnWater)
|
||||
shoreGrid.set(i, j, shoreMax);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand influences to find shore distance
|
||||
for (u16 y = 0; y < m_MapSize; ++y)
|
||||
{
|
||||
u16 min = shoreMax;
|
||||
for (u16 x = 0; x < m_MapSize; ++x)
|
||||
{
|
||||
if (!waterGrid.get(x, y) || expandOnWater)
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
for (u16 x = m_MapSize; x > 0; --x)
|
||||
{
|
||||
if (!waterGrid.get(x-1, y) || expandOnWater)
|
||||
{
|
||||
u16 g = shoreGrid.get(x - 1, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x - 1, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (u16 x = 0; x < m_MapSize; ++x)
|
||||
{
|
||||
u16 min = shoreMax;
|
||||
for (u16 y = 0; y < m_MapSize; ++y)
|
||||
{
|
||||
if (!waterGrid.get(x, y) || expandOnWater)
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
for (u16 y = m_MapSize; y > 0; --y)
|
||||
{
|
||||
if (!waterGrid.get(x, y-1) || expandOnWater)
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y - 1);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y - 1, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shoreGrid;
|
||||
}
|
||||
|
||||
void CCmpPathfinder::UpdateGrid()
|
||||
{
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
|
||||
@ -369,113 +484,11 @@ void CCmpPathfinder::UpdateGrid()
|
||||
// Obstructions or terrain changed - we need to recompute passability
|
||||
// TODO: only bother recomputing the region that has actually changed
|
||||
|
||||
Grid<u16> shoreGrid = ComputeShoreGrid();
|
||||
|
||||
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
|
||||
|
||||
// TOOD: these bits should come from ICmpTerrain
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
// avoid integer overflow in intermediate calculation
|
||||
const u16 shoreMax = 32767;
|
||||
|
||||
// First pass - find underwater tiles
|
||||
Grid<bool> waterGrid(m_MapSize, m_MapSize);
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < m_MapSize; ++i)
|
||||
{
|
||||
fixed x, z;
|
||||
TileCenter(i, j, x, z);
|
||||
|
||||
bool underWater = cmpWaterManager && (cmpWaterManager->GetWaterLevel(x, z) > terrain.GetExactGroundLevelFixed(x, z));
|
||||
waterGrid.set(i, j, underWater);
|
||||
}
|
||||
}
|
||||
// Second pass - find shore tiles
|
||||
Grid<u16> shoreGrid(m_MapSize, m_MapSize);
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < m_MapSize; ++i)
|
||||
{
|
||||
// Find a land tile
|
||||
if (!waterGrid.get(i, j))
|
||||
{
|
||||
if ((i > 0 && waterGrid.get(i-1, j)) || (i > 0 && j < m_MapSize-1 && waterGrid.get(i-1, j+1)) || (i > 0 && j > 0 && waterGrid.get(i-1, j-1))
|
||||
|| (i < m_MapSize-1 && waterGrid.get(i+1, j)) || (i < m_MapSize-1 && j < m_MapSize-1 && waterGrid.get(i+1, j+1)) || (i < m_MapSize-1 && j > 0 && waterGrid.get(i+1, j-1))
|
||||
|| (j > 0 && waterGrid.get(i, j-1)) || (j < m_MapSize-1 && waterGrid.get(i, j+1))
|
||||
)
|
||||
{ // If it's bordered by water, it's a shore tile
|
||||
shoreGrid.set(i, j, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shoreGrid.set(i, j, shoreMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expand influences on land to find shore distance
|
||||
for (u16 y = 0; y < m_MapSize; ++y)
|
||||
{
|
||||
u16 min = shoreMax;
|
||||
for (u16 x = 0; x < m_MapSize; ++x)
|
||||
{
|
||||
if (!waterGrid.get(x, y))
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
for (u16 x = m_MapSize; x > 0; --x)
|
||||
{
|
||||
if (!waterGrid.get(x-1, y))
|
||||
{
|
||||
u16 g = shoreGrid.get(x-1, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x-1, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (u16 x = 0; x < m_MapSize; ++x)
|
||||
{
|
||||
u16 min = shoreMax;
|
||||
for (u16 y = 0; y < m_MapSize; ++y)
|
||||
{
|
||||
if (!waterGrid.get(x, y))
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
for (u16 y = m_MapSize; y > 0; --y)
|
||||
{
|
||||
if (!waterGrid.get(x, y-1))
|
||||
{
|
||||
u16 g = shoreGrid.get(x, y-1);
|
||||
if (g > min)
|
||||
shoreGrid.set(x, y-1, min);
|
||||
else if (g < min)
|
||||
min = g;
|
||||
|
||||
++min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply passability classes to terrain
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -242,6 +242,8 @@ public:
|
||||
|
||||
virtual const Grid<u16>& GetPassabilityGrid();
|
||||
|
||||
virtual Grid<u16> ComputeShoreGrid(bool expandOnWater = false);
|
||||
|
||||
virtual void ComputePath(entity_pos_t x0, entity_pos_t z0, const Goal& goal, pass_class_t passClass, cost_class_t costClass, Path& ret);
|
||||
|
||||
virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, const Goal& goal, pass_class_t passClass, cost_class_t costClass, entity_id_t notify);
|
||||
|
@ -1807,6 +1807,39 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void RevealShore(player_id_t p, bool enable)
|
||||
{
|
||||
if (p <= 0 || p > MAX_LOS_PLAYER_ID)
|
||||
return;
|
||||
|
||||
// Maximum distance to the shore
|
||||
const u16 maxdist = 10;
|
||||
|
||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
|
||||
const Grid<u16>& shoreGrid = cmpPathfinder->ComputeShoreGrid(true);
|
||||
ENSURE(shoreGrid.m_W == m_TerrainVerticesPerSide-1 && shoreGrid.m_H == m_TerrainVerticesPerSide-1);
|
||||
|
||||
std::vector<u16>& counts = m_LosPlayerCounts.at(p);
|
||||
ENSURE(!counts.empty());
|
||||
u16* countsData = &counts[0];
|
||||
|
||||
for (u16 j = 0; j < shoreGrid.m_H; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < shoreGrid.m_W; ++i)
|
||||
{
|
||||
u16 shoredist = shoreGrid.get(i, j);
|
||||
if (shoredist > maxdist)
|
||||
continue;
|
||||
|
||||
// Maybe we could be more clever and don't add dummy strips of one tile
|
||||
if (enable)
|
||||
LosAddStripHelper(p, i, i, j, countsData);
|
||||
else
|
||||
LosRemoveStripHelper(p, i, i, j, countsData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given vertex is outside the normal bounds of the world
|
||||
* (i.e. outside the range of a circular map)
|
||||
@ -1861,23 +1894,7 @@ public:
|
||||
m_LosState[idx] |= ((LOS_VISIBLE | LOS_EXPLORED) << (2*(owner-1)));
|
||||
}
|
||||
|
||||
// Mark the LoS tiles around the updated vertex
|
||||
// 1: left-up, 2: right-up, 3: left-down, 4: right-down
|
||||
int n1 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n2 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
int n3 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
|
||||
u16 sharedDirtyVisibilityMask = m_SharedDirtyVisibilityMasks[owner];
|
||||
|
||||
if (j > 0 && i > 0)
|
||||
m_DirtyVisibility[n1] |= sharedDirtyVisibilityMask;
|
||||
if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n2] |= sharedDirtyVisibilityMask;
|
||||
if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0)
|
||||
m_DirtyVisibility[n3] |= sharedDirtyVisibilityMask;
|
||||
if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n4] |= sharedDirtyVisibilityMask;
|
||||
MarkVisibilityDirtyAroundTile(owner, i, j);
|
||||
}
|
||||
|
||||
ASSERT(counts[idx] < 65535);
|
||||
@ -1907,28 +1924,32 @@ public:
|
||||
m_LosState[idx] &= ~(LOS_VISIBLE << (2*(owner-1)));
|
||||
|
||||
i32 i = i0 + idx - idx0;
|
||||
|
||||
// Mark the LoS tiles around the updated vertex
|
||||
// 1: left-up, 2: right-up, 3: left-down, 4: right-down
|
||||
int n1 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n2 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
int n3 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
|
||||
u16 sharedDirtyVisibilityMask = m_SharedDirtyVisibilityMasks[owner];
|
||||
|
||||
if (j > 0 && i > 0)
|
||||
m_DirtyVisibility[n1] |= sharedDirtyVisibilityMask;
|
||||
if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n2] |= sharedDirtyVisibilityMask;
|
||||
if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0)
|
||||
m_DirtyVisibility[n3] |= sharedDirtyVisibilityMask;
|
||||
if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n4] |= sharedDirtyVisibilityMask;
|
||||
MarkVisibilityDirtyAroundTile(owner, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void MarkVisibilityDirtyAroundTile(u8 owner, i32 i, i32 j)
|
||||
{
|
||||
// Mark the LoS tiles around the updated vertex
|
||||
// 1: left-up, 2: right-up, 3: left-down, 4: right-down
|
||||
int n1 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n2 = ((j-1)/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
int n3 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + (i-1)/LOS_TILES_RATIO;
|
||||
int n4 = (j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO;
|
||||
|
||||
u16 sharedDirtyVisibilityMask = m_SharedDirtyVisibilityMasks[owner];
|
||||
|
||||
if (j > 0 && i > 0)
|
||||
m_DirtyVisibility[n1] |= sharedDirtyVisibilityMask;
|
||||
if (n2 != n1 && j > 0 && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n2] |= sharedDirtyVisibilityMask;
|
||||
if (n3 != n1 && j < m_TerrainVerticesPerSide && i > 0)
|
||||
m_DirtyVisibility[n3] |= sharedDirtyVisibilityMask;
|
||||
if (n4 != n1 && j < m_TerrainVerticesPerSide && i < m_TerrainVerticesPerSide)
|
||||
m_DirtyVisibility[n4] |= sharedDirtyVisibilityMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the LOS state of tiles within a given circular range,
|
||||
* either adding or removing visibility depending on the template parameter.
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include "ICmpVision.h"
|
||||
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/components/ICmpOwnership.h"
|
||||
#include "simulation2/components/ICmpPlayerManager.h"
|
||||
#include "simulation2/components/ICmpRangeManager.h"
|
||||
#include "simulation2/components/ICmpValueModificationManager.h"
|
||||
|
||||
class CCmpVision : public ICmpVision
|
||||
@ -30,6 +30,7 @@ class CCmpVision : public ICmpVision
|
||||
public:
|
||||
static void ClassInit(CComponentManager& componentManager)
|
||||
{
|
||||
componentManager.SubscribeToMessageType(MT_OwnershipChanged);
|
||||
componentManager.SubscribeToMessageType(MT_ValueModification);
|
||||
componentManager.SubscribeToMessageType(MT_Deserialized);
|
||||
}
|
||||
@ -39,18 +40,29 @@ public:
|
||||
// Template state:
|
||||
|
||||
entity_pos_t m_Range, m_BaseRange;
|
||||
bool m_RevealShore;
|
||||
|
||||
static std::string GetSchema()
|
||||
{
|
||||
return
|
||||
"<element name='Range'>"
|
||||
"<data type='nonNegativeInteger'/>"
|
||||
"</element>";
|
||||
"</element>"
|
||||
"<optional>"
|
||||
"<element name='RevealShore'>"
|
||||
"<data type='boolean'/>"
|
||||
"</element>"
|
||||
"</optional>";
|
||||
}
|
||||
|
||||
virtual void Init(const CParamNode& paramNode)
|
||||
{
|
||||
m_BaseRange = m_Range = paramNode.GetChild("Range").ToFixed();
|
||||
|
||||
if (paramNode.GetChild("RevealShore").IsOk())
|
||||
m_RevealShore = paramNode.GetChild("RevealShore").ToBool();
|
||||
else
|
||||
m_RevealShore = false;
|
||||
}
|
||||
|
||||
virtual void Deinit()
|
||||
@ -71,6 +83,20 @@ public:
|
||||
{
|
||||
switch (msg.GetType())
|
||||
{
|
||||
case MT_OwnershipChanged:
|
||||
{
|
||||
if (!m_RevealShore)
|
||||
break;
|
||||
|
||||
const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
|
||||
if (msgData.entity != GetEntityId())
|
||||
break;
|
||||
|
||||
CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
|
||||
cmpRangeManager->RevealShore(msgData.from, false);
|
||||
cmpRangeManager->RevealShore(msgData.to, true);
|
||||
break;
|
||||
}
|
||||
case MT_ValueModification:
|
||||
{
|
||||
const CMessageValueModification& msgData = static_cast<const CMessageValueModification&> (msg);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2013 Wildfire Games.
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -96,6 +96,11 @@ public:
|
||||
|
||||
virtual const Grid<u16>& GetPassabilityGrid() = 0;
|
||||
|
||||
/**
|
||||
* Get a grid representing the distance to the shore of the terrain tile.
|
||||
*/
|
||||
virtual Grid<u16> ComputeShoreGrid(bool expandOnWater = false) = 0;
|
||||
|
||||
/**
|
||||
* Compute a tile-based path from the given point to the goal, and return the set of waypoints.
|
||||
* The waypoints correspond to the centers of horizontally/vertically adjacent tiles
|
||||
|
@ -352,6 +352,14 @@ public:
|
||||
*/
|
||||
virtual void ExploreTerritories() = 0;
|
||||
|
||||
/**
|
||||
* Reveal the shore for specified player p.
|
||||
* This works like for entities: if RevealShore is called multiple times with enabled, it
|
||||
* will be necessary to call it the same number of times with !enabled to make the shore
|
||||
* fall back into the FoW.
|
||||
*/
|
||||
virtual void RevealShore(player_id_t p, bool enable) = 0;
|
||||
|
||||
/**
|
||||
* Set whether the whole map should be made visible to the given player.
|
||||
* If player is -1, the map will be made visible to all players.
|
||||
|
Loading…
Reference in New Issue
Block a user