# Health decay for buildings not in a civ center's territory.
This was SVN commit r10034.
This commit is contained in:
parent
6b26820090
commit
308cb26dd4
@ -15,6 +15,6 @@ TEX los, fragment.texcoord[1], texture[2], 2D;
|
|||||||
MUL result.color.rgb, color, los.a;
|
MUL result.color.rgb, color, los.a;
|
||||||
|
|
||||||
// Use alpha from base texture
|
// Use alpha from base texture
|
||||||
MOV result.color.a, base.a;
|
MUL result.color.a, objectColor.a, base.a;
|
||||||
|
|
||||||
END
|
END
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
function TerritoryDecay() {}
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.Schema =
|
||||||
|
"<element name='HealthDecayRate' a:help='Decay rate in hitpoints per second'>" +
|
||||||
|
"<data type='positiveInteger'/>" +
|
||||||
|
"</element>";
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.Init = function()
|
||||||
|
{
|
||||||
|
this.timer = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.IsConnected = function()
|
||||||
|
{
|
||||||
|
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|
||||||
|
if (!cmpPosition || !cmpPosition.IsInWorld())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
||||||
|
if (!cmpOwnership)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
|
||||||
|
if (!cmpTerritoryManager)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var pos = cmpPosition.GetPosition2D();
|
||||||
|
var tileOwner = cmpTerritoryManager.GetOwner(pos.x, pos.y);
|
||||||
|
if (tileOwner != cmpOwnership.GetOwner())
|
||||||
|
return false;
|
||||||
|
// TODO: this should probably use the same territory restriction
|
||||||
|
// logic as BuildRestrictions, to handle allies etc
|
||||||
|
|
||||||
|
return cmpTerritoryManager.IsConnected(pos.x, pos.y);
|
||||||
|
};
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.UpdateDecayState = function()
|
||||||
|
{
|
||||||
|
var connected = this.IsConnected();
|
||||||
|
if (!connected && !this.timer)
|
||||||
|
{
|
||||||
|
// Start decaying
|
||||||
|
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
||||||
|
this.timer = cmpTimer.SetInterval(this.entity, IID_TerritoryDecay, "Decay", 1000, 1000, {});
|
||||||
|
}
|
||||||
|
else if (connected && this.timer)
|
||||||
|
{
|
||||||
|
// Stop decaying
|
||||||
|
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
||||||
|
cmpTimer.CancelTimer(this.timer);
|
||||||
|
this.timer = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.OnTerritoriesChanged = function(msg)
|
||||||
|
{
|
||||||
|
this.UpdateDecayState();
|
||||||
|
};
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.OnOwnershipChanged = function(msg)
|
||||||
|
{
|
||||||
|
this.UpdateDecayState();
|
||||||
|
};
|
||||||
|
|
||||||
|
TerritoryDecay.prototype.Decay = function()
|
||||||
|
{
|
||||||
|
var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
|
||||||
|
if (!cmpHealth)
|
||||||
|
return; // error
|
||||||
|
|
||||||
|
cmpHealth.Reduce(+this.template.HealthDecayRate);
|
||||||
|
};
|
||||||
|
|
||||||
|
Engine.RegisterComponentType(IID_TerritoryDecay, "TerritoryDecay", TerritoryDecay);
|
@ -82,7 +82,11 @@ Timer.prototype.OnUpdate = function(msg)
|
|||||||
|
|
||||||
var cmp = Engine.QueryInterface(t[0], t[1]);
|
var cmp = Engine.QueryInterface(t[0], t[1]);
|
||||||
if (!cmp)
|
if (!cmp)
|
||||||
continue; // the entity was probably destroyed
|
{
|
||||||
|
// The entity was probably destroyed; clean up the timer
|
||||||
|
delete this.timers[id];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var lateness = this.time - t[3];
|
var lateness = this.time - t[3];
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Engine.RegisterInterface("TerritoryDecay");
|
@ -44,6 +44,7 @@
|
|||||||
<Static width="26.0" depth="30.0"/>
|
<Static width="26.0" depth="30.0"/>
|
||||||
</Obstruction>
|
</Obstruction>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>40</Radius>
|
<Radius>40</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
<Static width="28.0" depth="20.0"/>
|
<Static width="28.0" depth="20.0"/>
|
||||||
</Obstruction>
|
</Obstruction>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>40</Radius>
|
<Radius>40</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
<Static width="26.0" depth="10.5"/>
|
<Static width="26.0" depth="10.5"/>
|
||||||
</Obstruction>
|
</Obstruction>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>36</Radius>
|
<Radius>36</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<Selectable/>
|
<Selectable/>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
<OverrideCost>64</OverrideCost>
|
<OverrideCost>64</OverrideCost>
|
||||||
|
<Root>false</Root>
|
||||||
<Weight>0</Weight>
|
<Weight>0</Weight>
|
||||||
<Radius>0</Radius>
|
<Radius>0</Radius>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<Selectable/>
|
<Selectable/>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
<OverrideCost>0</OverrideCost>
|
<OverrideCost>0</OverrideCost>
|
||||||
|
<Root>false</Root>
|
||||||
<Weight>0</Weight>
|
<Weight>0</Weight>
|
||||||
<Radius>0</Radius>
|
<Radius>0</Radius>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -66,6 +66,9 @@
|
|||||||
<BarHeight>0.6</BarHeight>
|
<BarHeight>0.6</BarHeight>
|
||||||
<HeightOffset>12.0</HeightOffset>
|
<HeightOffset>12.0</HeightOffset>
|
||||||
</StatusBars>
|
</StatusBars>
|
||||||
|
<TerritoryDecay>
|
||||||
|
<HealthDecayRate>20</HealthDecayRate>
|
||||||
|
</TerritoryDecay>
|
||||||
<Vision>
|
<Vision>
|
||||||
<Range>40</Range>
|
<Range>40</Range>
|
||||||
<RetainInFog>true</RetainInFog>
|
<RetainInFog>true</RetainInFog>
|
||||||
|
@ -76,6 +76,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>true</Root>
|
||||||
<Radius>180</Radius>
|
<Radius>180</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
<HeightOffset>8.0</HeightOffset>
|
<HeightOffset>8.0</HeightOffset>
|
||||||
</StatusBars>
|
</StatusBars>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>20</Radius>
|
<Radius>20</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>40</Radius>
|
<Radius>40</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
<HeightOffset>21.0</HeightOffset>
|
<HeightOffset>21.0</HeightOffset>
|
||||||
</StatusBars>
|
</StatusBars>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>32</Radius>
|
<Radius>32</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>20</Radius>
|
<Radius>20</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>40</Radius>
|
<Radius>40</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>20</Radius>
|
<Radius>20</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>60</Radius>
|
<Radius>60</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
</SoundGroups>
|
</SoundGroups>
|
||||||
</Sound>
|
</Sound>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>100</Radius>
|
<Radius>100</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
<Static width="24.0" depth="24.0"/>
|
<Static width="24.0" depth="24.0"/>
|
||||||
</Obstruction>
|
</Obstruction>
|
||||||
<TerritoryInfluence>
|
<TerritoryInfluence>
|
||||||
|
<Root>false</Root>
|
||||||
<Radius>40</Radius>
|
<Radius>40</Radius>
|
||||||
<Weight>65536</Weight>
|
<Weight>65536</Weight>
|
||||||
</TerritoryInfluence>
|
</TerritoryInfluence>
|
||||||
|
@ -192,7 +192,7 @@ void CTerritoryTexture::GenerateBitmap(const Grid<u8>& territories, u8* bitmap,
|
|||||||
{
|
{
|
||||||
for (ssize_t i = 0; i < w; ++i)
|
for (ssize_t i = 0; i < w; ++i)
|
||||||
{
|
{
|
||||||
u8 val = territories.get(i, j);
|
u8 val = territories.get(i, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK;
|
||||||
|
|
||||||
CColor color(1, 0, 1, 1);
|
CColor color(1, 0, 1, 1);
|
||||||
if (val < colors.size())
|
if (val < colors.size())
|
||||||
@ -202,14 +202,10 @@ void CTerritoryTexture::GenerateBitmap(const Grid<u8>& territories, u8* bitmap,
|
|||||||
*p++ = (int)(color.g*255.f);
|
*p++ = (int)(color.g*255.f);
|
||||||
*p++ = (int)(color.r*255.f);
|
*p++ = (int)(color.r*255.f);
|
||||||
|
|
||||||
if ((i > 0 && territories.get(i-1, j) != val)
|
if ((i > 0 && (territories.get(i-1, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
|
||||||
|| (i < w-1 && territories.get(i+1, j) != val)
|
|| (i < w-1 && (territories.get(i+1, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
|
||||||
|| (j > 0 && territories.get(i, j-1) != val)
|
|| (j > 0 && (territories.get(i, j-1) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
|
||||||
|| (j < h-1 && territories.get(i, j+1) != val)
|
|| (j < h-1 && (territories.get(i, j+1) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
|
||||||
// || (i > 0 && j > 0 && territories.get(i-1, j-1) != val)
|
|
||||||
// || (i < w-1 && j > 0 && territories.get(i+1, j-1) != val)
|
|
||||||
// || (i > 0 && j > h-1 && territories.get(i-1, j+1) != val)
|
|
||||||
// || (i < w-1 && j < h-1 && territories.get(i+1, j+1) != val)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
*p++ = alphaMax;
|
*p++ = alphaMax;
|
||||||
|
@ -286,6 +286,19 @@ public:
|
|||||||
int32_t i0, j0, i1, j1; // inclusive lower bound, exclusive upper bound, in tiles
|
int32_t i0, j0, i1, j1; // inclusive lower bound, exclusive upper bound, in tiles
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sent when territory assignments have changed.
|
||||||
|
*/
|
||||||
|
class CMessageTerritoriesChanged : public CMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DEFAULT_MESSAGE_IMPL(TerritoriesChanged)
|
||||||
|
|
||||||
|
CMessageTerritoriesChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sent by CCmpRangeManager at most once per turn, when an active range query
|
* Sent by CCmpRangeManager at most once per turn, when an active range query
|
||||||
* has had matching units enter/leave the range since the last RangeUpdate.
|
* has had matching units enter/leave the range since the last RangeUpdate.
|
||||||
|
@ -45,6 +45,7 @@ MESSAGE(PositionChanged)
|
|||||||
MESSAGE(MotionChanged)
|
MESSAGE(MotionChanged)
|
||||||
MESSAGE(RangeUpdate)
|
MESSAGE(RangeUpdate)
|
||||||
MESSAGE(TerrainChanged)
|
MESSAGE(TerrainChanged)
|
||||||
|
MESSAGE(TerritoriesChanged)
|
||||||
MESSAGE(PathResult)
|
MESSAGE(PathResult)
|
||||||
|
|
||||||
// TemplateManager must come before all other (non-test) components,
|
// TemplateManager must come before all other (non-test) components,
|
||||||
|
@ -916,7 +916,7 @@ public:
|
|||||||
{
|
{
|
||||||
for (u16 i = 0; i < grid.m_W; ++i)
|
for (u16 i = 0; i < grid.m_W; ++i)
|
||||||
{
|
{
|
||||||
u8 p = grid.get(i, j);
|
u8 p = grid.get(i, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK;
|
||||||
if (p > 0 && p <= MAX_LOS_PLAYER_ID)
|
if (p > 0 && p <= MAX_LOS_PLAYER_ID)
|
||||||
{
|
{
|
||||||
m_LosState[i + j*m_TerrainVerticesPerSide] |= (LOS_EXPLORED << (2*(p-1)));
|
m_LosState[i + j*m_TerrainVerticesPerSide] |= (LOS_EXPLORED << (2*(p-1)));
|
||||||
|
@ -60,6 +60,11 @@ public:
|
|||||||
Init(paramNode);
|
Init(paramNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool IsLoaded()
|
||||||
|
{
|
||||||
|
return m_Terrain->GetVerticesPerSide() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z)
|
virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z)
|
||||||
{
|
{
|
||||||
CFixedVector3D normal;
|
CFixedVector3D normal;
|
||||||
|
@ -30,6 +30,7 @@ public:
|
|||||||
DEFAULT_COMPONENT_ALLOCATOR(TerritoryInfluence)
|
DEFAULT_COMPONENT_ALLOCATOR(TerritoryInfluence)
|
||||||
|
|
||||||
i32 m_Cost;
|
i32 m_Cost;
|
||||||
|
bool m_Root;
|
||||||
u32 m_Weight;
|
u32 m_Weight;
|
||||||
u32 m_Radius;
|
u32 m_Radius;
|
||||||
|
|
||||||
@ -43,6 +44,9 @@ public:
|
|||||||
"</data>"
|
"</data>"
|
||||||
"</element>"
|
"</element>"
|
||||||
"</optional>"
|
"</optional>"
|
||||||
|
"<element name='Root'>"
|
||||||
|
"<data type='boolean'/>"
|
||||||
|
"</element>"
|
||||||
"<element name='Weight'>"
|
"<element name='Weight'>"
|
||||||
"<data type='nonNegativeInteger'/>"
|
"<data type='nonNegativeInteger'/>"
|
||||||
"</element>"
|
"</element>"
|
||||||
@ -58,6 +62,7 @@ public:
|
|||||||
else
|
else
|
||||||
m_Cost = -1;
|
m_Cost = -1;
|
||||||
|
|
||||||
|
m_Root = paramNode.GetChild("Root").ToBool();
|
||||||
m_Weight = paramNode.GetChild("Weight").ToInt();
|
m_Weight = paramNode.GetChild("Weight").ToInt();
|
||||||
m_Radius = paramNode.GetChild("Radius").ToInt();
|
m_Radius = paramNode.GetChild("Radius").ToInt();
|
||||||
}
|
}
|
||||||
@ -80,6 +85,11 @@ public:
|
|||||||
return m_Cost;
|
return m_Cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool IsRoot()
|
||||||
|
{
|
||||||
|
return m_Root;
|
||||||
|
}
|
||||||
|
|
||||||
virtual u32 GetWeight()
|
virtual u32 GetWeight()
|
||||||
{
|
{
|
||||||
return m_Weight;
|
return m_Weight;
|
||||||
|
@ -66,6 +66,8 @@ public:
|
|||||||
componentManager.SubscribeGloballyToMessageType(MT_OwnershipChanged);
|
componentManager.SubscribeGloballyToMessageType(MT_OwnershipChanged);
|
||||||
componentManager.SubscribeGloballyToMessageType(MT_PositionChanged);
|
componentManager.SubscribeGloballyToMessageType(MT_PositionChanged);
|
||||||
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
componentManager.SubscribeToMessageType(MT_TerrainChanged);
|
||||||
|
componentManager.SubscribeToMessageType(MT_Update);
|
||||||
|
componentManager.SubscribeToMessageType(MT_Interpolate);
|
||||||
componentManager.SubscribeToMessageType(MT_RenderSubmit);
|
componentManager.SubscribeToMessageType(MT_RenderSubmit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,20 +82,39 @@ public:
|
|||||||
float m_BorderThickness;
|
float m_BorderThickness;
|
||||||
float m_BorderSeparation;
|
float m_BorderSeparation;
|
||||||
|
|
||||||
|
// Player ID in lower 7 bits; connected flag in high bit
|
||||||
Grid<u8>* m_Territories;
|
Grid<u8>* m_Territories;
|
||||||
TerritoryOverlay* m_DebugOverlay;
|
|
||||||
std::vector<SOverlayTexturedLine> m_BoundaryLines;
|
// Set to true when territories change; will send a TerritoriesChanged message
|
||||||
|
// during the Update phase
|
||||||
|
bool m_TriggerEvent;
|
||||||
|
|
||||||
|
struct SBoundaryLine
|
||||||
|
{
|
||||||
|
bool connected;
|
||||||
|
CColor color;
|
||||||
|
SOverlayTexturedLine overlay;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<SBoundaryLine> m_BoundaryLines;
|
||||||
bool m_BoundaryLinesDirty;
|
bool m_BoundaryLinesDirty;
|
||||||
|
|
||||||
|
double m_AnimTime; // time since start of rendering, in seconds
|
||||||
|
|
||||||
|
TerritoryOverlay* m_DebugOverlay;
|
||||||
|
|
||||||
virtual void Init(const CParamNode& UNUSED(paramNode))
|
virtual void Init(const CParamNode& UNUSED(paramNode))
|
||||||
{
|
{
|
||||||
m_Territories = NULL;
|
m_Territories = NULL;
|
||||||
m_DebugOverlay = NULL;
|
m_DebugOverlay = NULL;
|
||||||
// m_DebugOverlay = new TerritoryOverlay(*this);
|
// m_DebugOverlay = new TerritoryOverlay(*this);
|
||||||
m_BoundaryLinesDirty = true;
|
m_BoundaryLinesDirty = true;
|
||||||
|
m_TriggerEvent = true;
|
||||||
|
|
||||||
m_DirtyID = 1;
|
m_DirtyID = 1;
|
||||||
|
|
||||||
|
m_AnimTime = 0.0;
|
||||||
|
|
||||||
CParamNode externalParamNode;
|
CParamNode externalParamNode;
|
||||||
CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml");
|
CParamNode::LoadXML(externalParamNode, L"simulation/data/territorymanager.xml");
|
||||||
|
|
||||||
@ -141,6 +162,22 @@ public:
|
|||||||
MakeDirty();
|
MakeDirty();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_Update:
|
||||||
|
{
|
||||||
|
if (m_TriggerEvent)
|
||||||
|
{
|
||||||
|
m_TriggerEvent = false;
|
||||||
|
CMessageTerritoriesChanged msg;
|
||||||
|
GetSimContext().GetComponentManager().BroadcastMessage(msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MT_Interpolate:
|
||||||
|
{
|
||||||
|
const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
|
||||||
|
Interpolate(msgData.frameTime, msgData.offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MT_RenderSubmit:
|
case MT_RenderSubmit:
|
||||||
{
|
{
|
||||||
const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg);
|
const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg);
|
||||||
@ -166,10 +203,12 @@ public:
|
|||||||
virtual const Grid<u8>& GetTerritoryGrid()
|
virtual const Grid<u8>& GetTerritoryGrid()
|
||||||
{
|
{
|
||||||
CalculateTerritories();
|
CalculateTerritories();
|
||||||
|
ENSURE(m_Territories);
|
||||||
return *m_Territories;
|
return *m_Territories;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int32_t GetOwner(entity_pos_t x, entity_pos_t z);
|
virtual player_id_t GetOwner(entity_pos_t x, entity_pos_t z);
|
||||||
|
virtual bool IsConnected(entity_pos_t x, entity_pos_t z);
|
||||||
|
|
||||||
// To support lazy updates of territory render data,
|
// To support lazy updates of territory render data,
|
||||||
// we maintain a DirtyID here and increment it whenever territories change;
|
// we maintain a DirtyID here and increment it whenever territories change;
|
||||||
@ -182,6 +221,7 @@ public:
|
|||||||
SAFE_DELETE(m_Territories);
|
SAFE_DELETE(m_Territories);
|
||||||
++m_DirtyID;
|
++m_DirtyID;
|
||||||
m_BoundaryLinesDirty = true;
|
m_BoundaryLinesDirty = true;
|
||||||
|
m_TriggerEvent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool NeedUpdate(size_t* dirtyID)
|
virtual bool NeedUpdate(size_t* dirtyID)
|
||||||
@ -205,6 +245,7 @@ public:
|
|||||||
|
|
||||||
struct TerritoryBoundary
|
struct TerritoryBoundary
|
||||||
{
|
{
|
||||||
|
bool connected;
|
||||||
player_id_t owner;
|
player_id_t owner;
|
||||||
std::vector<CVector2D> points;
|
std::vector<CVector2D> points;
|
||||||
};
|
};
|
||||||
@ -213,6 +254,8 @@ public:
|
|||||||
|
|
||||||
void UpdateBoundaryLines();
|
void UpdateBoundaryLines();
|
||||||
|
|
||||||
|
void Interpolate(float frameTime, float frameOffset);
|
||||||
|
|
||||||
void RenderSubmit(SceneCollector& collector);
|
void RenderSubmit(SceneCollector& collector);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,8 +293,8 @@ static void ProcessNeighbour(u32 falloff, u16 i, u16 j, u32 pg, bool diagonal,
|
|||||||
|
|
||||||
static void FloodFill(Grid<u32>& grid, Grid<u8>& costGrid, OpenQueue& openTiles, u32 falloff)
|
static void FloodFill(Grid<u32>& grid, Grid<u8>& costGrid, OpenQueue& openTiles, u32 falloff)
|
||||||
{
|
{
|
||||||
u32 tilesW = grid.m_W;
|
u16 tilesW = grid.m_W;
|
||||||
u32 tilesH = grid.m_H;
|
u16 tilesH = grid.m_H;
|
||||||
|
|
||||||
while (!openTiles.empty())
|
while (!openTiles.empty())
|
||||||
{
|
{
|
||||||
@ -281,16 +324,21 @@ static void FloodFill(Grid<u32>& grid, Grid<u8>& costGrid, OpenQueue& openTiles,
|
|||||||
|
|
||||||
void CCmpTerritoryManager::CalculateTerritories()
|
void CCmpTerritoryManager::CalculateTerritories()
|
||||||
{
|
{
|
||||||
PROFILE("CalculateTerritories");
|
|
||||||
|
|
||||||
if (m_Territories)
|
if (m_Territories)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PROFILE("CalculateTerritories");
|
||||||
|
|
||||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||||
|
|
||||||
|
// If the terrain hasn't been loaded (e.g. this is called during map initialisation),
|
||||||
|
// abort the computation (and assume callers can cope with m_Territories == NULL)
|
||||||
|
if (!cmpTerrain->IsLoaded())
|
||||||
|
return;
|
||||||
|
|
||||||
u16 tilesW = cmpTerrain->GetTilesPerSide();
|
u16 tilesW = cmpTerrain->GetTilesPerSide();
|
||||||
u16 tilesH = cmpTerrain->GetTilesPerSide();
|
u16 tilesH = cmpTerrain->GetTilesPerSide();
|
||||||
|
|
||||||
SAFE_DELETE(m_Territories);
|
|
||||||
m_Territories = new Grid<u8>(tilesW, tilesH);
|
m_Territories = new Grid<u8>(tilesW, tilesH);
|
||||||
|
|
||||||
// Compute terrain-passability-dependent costs per tile
|
// Compute terrain-passability-dependent costs per tile
|
||||||
@ -324,6 +372,7 @@ void CCmpTerritoryManager::CalculateTerritories()
|
|||||||
|
|
||||||
// Split influence entities into per-player lists, ignoring any with invalid properties
|
// Split influence entities into per-player lists, ignoring any with invalid properties
|
||||||
std::map<player_id_t, std::vector<entity_id_t> > influenceEntities;
|
std::map<player_id_t, std::vector<entity_id_t> > influenceEntities;
|
||||||
|
std::vector<entity_id_t> rootInfluenceEntities;
|
||||||
for (CComponentManager::InterfaceList::iterator it = influences.begin(); it != influences.end(); ++it)
|
for (CComponentManager::InterfaceList::iterator it = influences.begin(); it != influences.end(); ++it)
|
||||||
{
|
{
|
||||||
// Ignore any with no weight or radius (to avoid divide-by-zero later)
|
// Ignore any with no weight or radius (to avoid divide-by-zero later)
|
||||||
@ -340,12 +389,19 @@ void CCmpTerritoryManager::CalculateTerritories()
|
|||||||
if (owner <= 0)
|
if (owner <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// We only have 7 bits to store tile ownership, so ignore unrepresentable players
|
||||||
|
if (owner > TERRITORY_PLAYER_MASK)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Ignore if invalid position
|
// Ignore if invalid position
|
||||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), it->first);
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), it->first);
|
||||||
if (cmpPosition.null() || !cmpPosition->IsInWorld())
|
if (cmpPosition.null() || !cmpPosition->IsInWorld())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
influenceEntities[owner].push_back(it->first);
|
influenceEntities[owner].push_back(it->first);
|
||||||
|
|
||||||
|
if (cmpTerritoryInfluence->IsRoot())
|
||||||
|
rootInfluenceEntities.push_back(it->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each player, store the sum of influences on each tile
|
// For each player, store the sum of influences on each tile
|
||||||
@ -413,6 +469,64 @@ void CCmpTerritoryManager::CalculateTerritories()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect territories connected to a 'root' influence (typically a civ center)
|
||||||
|
// belonging to their player, and mark them with the connected flag
|
||||||
|
for (std::vector<entity_id_t>::iterator it = rootInfluenceEntities.begin(); it != rootInfluenceEntities.end(); ++it)
|
||||||
|
{
|
||||||
|
// (These components must be valid else the entities wouldn't be added to this list)
|
||||||
|
CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), *it);
|
||||||
|
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *it);
|
||||||
|
|
||||||
|
CFixedVector2D pos = cmpPosition->GetPosition2D();
|
||||||
|
u16 i = (u16)clamp((pos.X / (int)CELL_SIZE).ToInt_RoundToNegInfinity(), 0, tilesW-1);
|
||||||
|
u16 j = (u16)clamp((pos.Y / (int)CELL_SIZE).ToInt_RoundToNegInfinity(), 0, tilesH-1);
|
||||||
|
|
||||||
|
u8 owner = (u8)cmpOwnership->GetOwner();
|
||||||
|
|
||||||
|
if (m_Territories->get(i, j) != owner)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO: would be nice to refactor some of the many flood fill
|
||||||
|
// algorithms in this component
|
||||||
|
|
||||||
|
Grid<u8>& grid = *m_Territories;
|
||||||
|
|
||||||
|
u16 maxi = (u16)(grid.m_W-1);
|
||||||
|
u16 maxj = (u16)(grid.m_H-1);
|
||||||
|
|
||||||
|
std::vector<std::pair<u16, u16> > tileStack;
|
||||||
|
|
||||||
|
#define MARK_AND_PUSH(i, j) STMT(grid.set(i, j, owner | TERRITORY_CONNECTED_MASK); tileStack.push_back(std::make_pair(i, j)); )
|
||||||
|
|
||||||
|
MARK_AND_PUSH(i, j);
|
||||||
|
while (!tileStack.empty())
|
||||||
|
{
|
||||||
|
int ti = tileStack.back().first;
|
||||||
|
int tj = tileStack.back().second;
|
||||||
|
tileStack.pop_back();
|
||||||
|
|
||||||
|
if (ti > 0 && grid.get(ti-1, tj) == owner)
|
||||||
|
MARK_AND_PUSH(ti-1, tj);
|
||||||
|
if (ti < maxi && grid.get(ti+1, tj) == owner)
|
||||||
|
MARK_AND_PUSH(ti+1, tj);
|
||||||
|
if (tj > 0 && grid.get(ti, tj-1) == owner)
|
||||||
|
MARK_AND_PUSH(ti, tj-1);
|
||||||
|
if (tj < maxj && grid.get(ti, tj+1) == owner)
|
||||||
|
MARK_AND_PUSH(ti, tj+1);
|
||||||
|
|
||||||
|
if (ti > 0 && tj > 0 && grid.get(ti-1, tj-1) == owner)
|
||||||
|
MARK_AND_PUSH(ti-1, tj-1);
|
||||||
|
if (ti > 0 && tj < maxj && grid.get(ti-1, tj+1) == owner)
|
||||||
|
MARK_AND_PUSH(ti-1, tj+1);
|
||||||
|
if (ti < maxi && tj > 0 && grid.get(ti+1, tj-1) == owner)
|
||||||
|
MARK_AND_PUSH(ti+1, tj-1);
|
||||||
|
if (ti < maxi && tj < maxj && grid.get(ti+1, tj+1) == owner)
|
||||||
|
MARK_AND_PUSH(ti+1, tj+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MARK_AND_PUSH
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -481,6 +595,7 @@ std::vector<CCmpTerritoryManager::TerritoryBoundary> CCmpTerritoryManager::Compu
|
|||||||
std::vector<CCmpTerritoryManager::TerritoryBoundary> boundaries;
|
std::vector<CCmpTerritoryManager::TerritoryBoundary> boundaries;
|
||||||
|
|
||||||
CalculateTerritories();
|
CalculateTerritories();
|
||||||
|
ENSURE(m_Territories);
|
||||||
|
|
||||||
// Copy the territories grid so we can mess with it
|
// Copy the territories grid so we can mess with it
|
||||||
Grid<u8> grid (*m_Territories);
|
Grid<u8> grid (*m_Territories);
|
||||||
@ -506,7 +621,8 @@ std::vector<CCmpTerritoryManager::TerritoryBoundary> CCmpTerritoryManager::Compu
|
|||||||
// we reach the starting point again
|
// we reach the starting point again
|
||||||
|
|
||||||
boundaries.push_back(TerritoryBoundary());
|
boundaries.push_back(TerritoryBoundary());
|
||||||
boundaries.back().owner = owner;
|
boundaries.back().connected = (owner & TERRITORY_CONNECTED_MASK);
|
||||||
|
boundaries.back().owner = (owner & TERRITORY_PLAYER_MASK);
|
||||||
std::vector<CVector2D>& points = boundaries.back().points;
|
std::vector<CVector2D>& points = boundaries.back().points;
|
||||||
|
|
||||||
u8 dir = 0; // 0 == bottom edge of tile, 1 == right, 2 == top, 3 == left
|
u8 dir = 0; // 0 == bottom edge of tile, 1 == right, 2 == top, 3 == left
|
||||||
@ -585,9 +701,9 @@ std::vector<CCmpTerritoryManager::TerritoryBoundary> CCmpTerritoryManager::Compu
|
|||||||
// process it a second time
|
// process it a second time
|
||||||
std::vector<std::pair<u16, u16> > tileStack;
|
std::vector<std::pair<u16, u16> > tileStack;
|
||||||
|
|
||||||
#define ZERO_AND_PUSH(i, j) STMT(grid.set(i, j, 0); tileStack.push_back(std::make_pair(i, j)); )
|
#define MARK_AND_PUSH(i, j) STMT(grid.set(i, j, 0); tileStack.push_back(std::make_pair(i, j)); )
|
||||||
|
|
||||||
ZERO_AND_PUSH(i, j);
|
MARK_AND_PUSH(i, j);
|
||||||
while (!tileStack.empty())
|
while (!tileStack.empty())
|
||||||
{
|
{
|
||||||
int ti = tileStack.back().first;
|
int ti = tileStack.back().first;
|
||||||
@ -595,25 +711,25 @@ std::vector<CCmpTerritoryManager::TerritoryBoundary> CCmpTerritoryManager::Compu
|
|||||||
tileStack.pop_back();
|
tileStack.pop_back();
|
||||||
|
|
||||||
if (ti > 0 && grid.get(ti-1, tj) == owner)
|
if (ti > 0 && grid.get(ti-1, tj) == owner)
|
||||||
ZERO_AND_PUSH(ti-1, tj);
|
MARK_AND_PUSH(ti-1, tj);
|
||||||
if (ti < maxi && grid.get(ti+1, tj) == owner)
|
if (ti < maxi && grid.get(ti+1, tj) == owner)
|
||||||
ZERO_AND_PUSH(ti+1, tj);
|
MARK_AND_PUSH(ti+1, tj);
|
||||||
if (tj > 0 && grid.get(ti, tj-1) == owner)
|
if (tj > 0 && grid.get(ti, tj-1) == owner)
|
||||||
ZERO_AND_PUSH(ti, tj-1);
|
MARK_AND_PUSH(ti, tj-1);
|
||||||
if (tj < maxj && grid.get(ti, tj+1) == owner)
|
if (tj < maxj && grid.get(ti, tj+1) == owner)
|
||||||
ZERO_AND_PUSH(ti, tj+1);
|
MARK_AND_PUSH(ti, tj+1);
|
||||||
|
|
||||||
if (ti > 0 && tj > 0 && grid.get(ti-1, tj-1) == owner)
|
if (ti > 0 && tj > 0 && grid.get(ti-1, tj-1) == owner)
|
||||||
ZERO_AND_PUSH(ti-1, tj-1);
|
MARK_AND_PUSH(ti-1, tj-1);
|
||||||
if (ti > 0 && tj < maxj && grid.get(ti-1, tj+1) == owner)
|
if (ti > 0 && tj < maxj && grid.get(ti-1, tj+1) == owner)
|
||||||
ZERO_AND_PUSH(ti-1, tj+1);
|
MARK_AND_PUSH(ti-1, tj+1);
|
||||||
if (ti < maxi && tj > 0 && grid.get(ti+1, tj-1) == owner)
|
if (ti < maxi && tj > 0 && grid.get(ti+1, tj-1) == owner)
|
||||||
ZERO_AND_PUSH(ti+1, tj-1);
|
MARK_AND_PUSH(ti+1, tj-1);
|
||||||
if (ti < maxi && tj < maxj && grid.get(ti+1, tj+1) == owner)
|
if (ti < maxi && tj < maxj && grid.get(ti+1, tj+1) == owner)
|
||||||
ZERO_AND_PUSH(ti+1, tj+1);
|
MARK_AND_PUSH(ti+1, tj+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ZERO_AND_PUSH
|
#undef MARK_AND_PUSH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -658,18 +774,21 @@ void CCmpTerritoryManager::UpdateBoundaryLines()
|
|||||||
if (!cmpPlayer.null())
|
if (!cmpPlayer.null())
|
||||||
color = cmpPlayer->GetColour();
|
color = cmpPlayer->GetColour();
|
||||||
|
|
||||||
m_BoundaryLines.push_back(SOverlayTexturedLine());
|
m_BoundaryLines.push_back(SBoundaryLine());
|
||||||
m_BoundaryLines.back().m_Terrain = terrain;
|
m_BoundaryLines.back().connected = boundaries[i].connected;
|
||||||
m_BoundaryLines.back().m_TextureBase = textureBase;
|
m_BoundaryLines.back().color = color;
|
||||||
m_BoundaryLines.back().m_TextureMask = textureMask;
|
|
||||||
m_BoundaryLines.back().m_Color = color;
|
m_BoundaryLines.back().overlay.m_Terrain = terrain;
|
||||||
m_BoundaryLines.back().m_Thickness = m_BorderThickness;
|
m_BoundaryLines.back().overlay.m_TextureBase = textureBase;
|
||||||
|
m_BoundaryLines.back().overlay.m_TextureMask = textureMask;
|
||||||
|
m_BoundaryLines.back().overlay.m_Color = color;
|
||||||
|
m_BoundaryLines.back().overlay.m_Thickness = m_BorderThickness;
|
||||||
|
|
||||||
SimRender::SmoothPointsAverage(boundaries[i].points, true);
|
SimRender::SmoothPointsAverage(boundaries[i].points, true);
|
||||||
|
|
||||||
SimRender::InterpolatePointsRNS(boundaries[i].points, true, m_BorderSeparation);
|
SimRender::InterpolatePointsRNS(boundaries[i].points, true, m_BorderSeparation);
|
||||||
|
|
||||||
std::vector<float>& points = m_BoundaryLines.back().m_Coords;
|
std::vector<float>& points = m_BoundaryLines.back().overlay.m_Coords;
|
||||||
for (size_t j = 0; j < boundaries[i].points.size(); ++j)
|
for (size_t j = 0; j < boundaries[i].points.size(); ++j)
|
||||||
{
|
{
|
||||||
points.push_back(boundaries[i].points[j].X);
|
points.push_back(boundaries[i].points[j].X);
|
||||||
@ -678,8 +797,10 @@ void CCmpTerritoryManager::UpdateBoundaryLines()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector)
|
void CCmpTerritoryManager::Interpolate(float frameTime, float UNUSED(frameOffset))
|
||||||
{
|
{
|
||||||
|
m_AnimTime += frameTime;
|
||||||
|
|
||||||
if (m_BoundaryLinesDirty)
|
if (m_BoundaryLinesDirty)
|
||||||
{
|
{
|
||||||
UpdateBoundaryLines();
|
UpdateBoundaryLines();
|
||||||
@ -687,15 +808,42 @@ void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < m_BoundaryLines.size(); ++i)
|
for (size_t i = 0; i < m_BoundaryLines.size(); ++i)
|
||||||
collector.Submit(&m_BoundaryLines[i]);
|
{
|
||||||
|
if (!m_BoundaryLines[i].connected)
|
||||||
|
{
|
||||||
|
CColor c = m_BoundaryLines[i].color;
|
||||||
|
c.a *= 0.2f + 0.8f * fabsf((float)cos(m_AnimTime * M_PI)); // TODO: should let artists tweak this
|
||||||
|
m_BoundaryLines[i].overlay.m_Color = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CCmpTerritoryManager::GetOwner(entity_pos_t x, entity_pos_t z)
|
void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_BoundaryLines.size(); ++i)
|
||||||
|
collector.Submit(&m_BoundaryLines[i].overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
player_id_t CCmpTerritoryManager::GetOwner(entity_pos_t x, entity_pos_t z)
|
||||||
{
|
{
|
||||||
u16 i, j;
|
u16 i, j;
|
||||||
CalculateTerritories();
|
CalculateTerritories();
|
||||||
|
if (!m_Territories)
|
||||||
|
return 0;
|
||||||
|
|
||||||
NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H);
|
NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H);
|
||||||
return m_Territories->get(i, j);
|
return m_Territories->get(i, j) & TERRITORY_PLAYER_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCmpTerritoryManager::IsConnected(entity_pos_t x, entity_pos_t z)
|
||||||
|
{
|
||||||
|
u16 i, j;
|
||||||
|
CalculateTerritories();
|
||||||
|
if (!m_Territories)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H);
|
||||||
|
return m_Territories->get(i, j) & TERRITORY_CONNECTED_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerritoryOverlay::StartRender()
|
void TerritoryOverlay::StartRender()
|
||||||
|
@ -29,6 +29,8 @@ class CTerrain;
|
|||||||
class ICmpTerrain : public IComponent
|
class ICmpTerrain : public IComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual bool IsLoaded() = 0;
|
||||||
|
|
||||||
virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) = 0;
|
virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) = 0;
|
||||||
|
|
||||||
virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) = 0;
|
virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) = 0;
|
||||||
|
@ -30,6 +30,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual i32 GetCost() = 0;
|
virtual i32 GetCost() = 0;
|
||||||
|
|
||||||
|
virtual bool IsRoot() = 0;
|
||||||
|
|
||||||
virtual u32 GetWeight() = 0;
|
virtual u32 GetWeight() = 0;
|
||||||
|
|
||||||
virtual u32 GetRadius() = 0;
|
virtual u32 GetRadius() = 0;
|
||||||
|
@ -22,5 +22,6 @@
|
|||||||
#include "simulation2/system/InterfaceScripted.h"
|
#include "simulation2/system/InterfaceScripted.h"
|
||||||
|
|
||||||
BEGIN_INTERFACE_WRAPPER(TerritoryManager)
|
BEGIN_INTERFACE_WRAPPER(TerritoryManager)
|
||||||
DEFINE_INTERFACE_METHOD_2("GetOwner", int32_t, ICmpTerritoryManager, GetOwner, entity_pos_t, entity_pos_t)
|
DEFINE_INTERFACE_METHOD_2("GetOwner", player_id_t, ICmpTerritoryManager, GetOwner, entity_pos_t, entity_pos_t)
|
||||||
|
DEFINE_INTERFACE_METHOD_2("IsConnected", bool, ICmpTerritoryManager, IsConnected, entity_pos_t, entity_pos_t)
|
||||||
END_INTERFACE_WRAPPER(TerritoryManager)
|
END_INTERFACE_WRAPPER(TerritoryManager)
|
||||||
|
@ -18,8 +18,10 @@
|
|||||||
#ifndef INCLUDED_ICMPTERRITORYMANAGER
|
#ifndef INCLUDED_ICMPTERRITORYMANAGER
|
||||||
#define INCLUDED_ICMPTERRITORYMANAGER
|
#define INCLUDED_ICMPTERRITORYMANAGER
|
||||||
|
|
||||||
#include "simulation2/helpers/Grid.h"
|
|
||||||
#include "simulation2/system/Interface.h"
|
#include "simulation2/system/Interface.h"
|
||||||
|
|
||||||
|
#include "simulation2/helpers/Grid.h"
|
||||||
|
#include "simulation2/helpers/Player.h"
|
||||||
#include "simulation2/components/ICmpPosition.h"
|
#include "simulation2/components/ICmpPosition.h"
|
||||||
|
|
||||||
class ICmpTerritoryManager : public IComponent
|
class ICmpTerritoryManager : public IComponent
|
||||||
@ -27,14 +29,27 @@ class ICmpTerritoryManager : public IComponent
|
|||||||
public:
|
public:
|
||||||
virtual bool NeedUpdate(size_t* dirtyID) = 0;
|
virtual bool NeedUpdate(size_t* dirtyID) = 0;
|
||||||
|
|
||||||
|
static const int TERRITORY_PLAYER_MASK = 0x7F;
|
||||||
|
static const int TERRITORY_CONNECTED_MASK = 0x80;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each tile, the TERRITORY_PLAYER_MASK bits are player ID;
|
||||||
|
* TERRITORY_CONNECTED_MASK is set if the tile is connected to a root object
|
||||||
|
* (civ center etc).
|
||||||
|
*/
|
||||||
virtual const Grid<u8>& GetTerritoryGrid() = 0;
|
virtual const Grid<u8>& GetTerritoryGrid() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get owner of territory at given position
|
* Get owner of territory at given position.
|
||||||
*
|
|
||||||
* @return player ID of owner; 0 if neutral territory
|
* @return player ID of owner; 0 if neutral territory
|
||||||
*/
|
*/
|
||||||
virtual int32_t GetOwner(entity_pos_t x, entity_pos_t z) = 0;
|
virtual player_id_t GetOwner(entity_pos_t x, entity_pos_t z) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get whether territory at given position is connected to a root object
|
||||||
|
* (civ center etc) owned by that territory's player.
|
||||||
|
*/
|
||||||
|
virtual bool IsConnected(entity_pos_t x, entity_pos_t z) = 0;
|
||||||
|
|
||||||
DECLARE_INTERFACE_TYPE(TerritoryManager)
|
DECLARE_INTERFACE_TYPE(TerritoryManager)
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2010 Wildfire Games.
|
/* Copyright (C) 2011 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -26,20 +26,20 @@
|
|||||||
#define TOJSVAL_SETUP() \
|
#define TOJSVAL_SETUP() \
|
||||||
JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \
|
JSObject* obj = JS_NewObject(scriptInterface.GetContext(), NULL, NULL, NULL); \
|
||||||
if (! obj) \
|
if (! obj) \
|
||||||
return JSVAL_VOID
|
return JSVAL_VOID;
|
||||||
|
|
||||||
#define SET_MSG_PROPERTY(name) \
|
#define SET_MSG_PROPERTY(name) \
|
||||||
do { \
|
do { \
|
||||||
jsval prop = ScriptInterface::ToJSVal(scriptInterface.GetContext(), this->name); \
|
jsval prop = ScriptInterface::ToJSVal(scriptInterface.GetContext(), this->name); \
|
||||||
if (! JS_SetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \
|
if (! JS_SetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \
|
||||||
return JSVAL_VOID; \
|
return JSVAL_VOID; \
|
||||||
} while (0)
|
} while (0);
|
||||||
|
|
||||||
#define FROMJSVAL_SETUP() \
|
#define FROMJSVAL_SETUP() \
|
||||||
if (! JSVAL_IS_OBJECT(val)) \
|
if (! JSVAL_IS_OBJECT(val)) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
JSObject* obj = JSVAL_TO_OBJECT(val)
|
JSObject* obj = JSVAL_TO_OBJECT(val); \
|
||||||
jsval prop;
|
jsval prop;
|
||||||
|
|
||||||
#define GET_MSG_PROPERTY(type, name) \
|
#define GET_MSG_PROPERTY(type, name) \
|
||||||
if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \
|
if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, &prop)) \
|
||||||
@ -58,10 +58,10 @@ jsval CMessage::ToJSValCached(ScriptInterface& scriptInterface) const
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
jsval CMessageTurnStart::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const
|
jsval CMessageTurnStart::ToJSVal(ScriptInterface& scriptInterface) const
|
||||||
{
|
{
|
||||||
LOGWARNING(L"CMessageTurnStart::ToJSVal not implemented");
|
TOJSVAL_SETUP();
|
||||||
return JSVAL_VOID;
|
return OBJECT_TO_JSVAL(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMessage* CMessageTurnStart::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val))
|
CMessage* CMessageTurnStart::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val))
|
||||||
@ -254,6 +254,19 @@ CMessage* CMessageTerrainChanged::FromJSVal(ScriptInterface& scriptInterface, js
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
jsval CMessageTerritoriesChanged::ToJSVal(ScriptInterface& scriptInterface) const
|
||||||
|
{
|
||||||
|
TOJSVAL_SETUP();
|
||||||
|
return OBJECT_TO_JSVAL(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
CMessage* CMessageTerritoriesChanged::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val))
|
||||||
|
{
|
||||||
|
return new CMessageTerritoriesChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
jsval CMessageRangeUpdate::ToJSVal(ScriptInterface& scriptInterface) const
|
jsval CMessageRangeUpdate::ToJSVal(ScriptInterface& scriptInterface) const
|
||||||
{
|
{
|
||||||
TOJSVAL_SETUP();
|
TOJSVAL_SETUP();
|
||||||
|
Loading…
Reference in New Issue
Block a user