1
0
forked from 0ad/0ad

Reduce drastically the number of mirages by making fogging conditional: entities will be miraged only if their health/resource amount is modified, or if they have a non-gaia owner.

Fixes the animals hidden in the FoW, and adds the missing status bars
for mirages.

Also small cleanup of the code.

Refs #2913

This was SVN commit r16281.
This commit is contained in:
Nicolas Auvray 2015-02-07 15:48:32 +00:00
parent b66465de73
commit da0f33f137
11 changed files with 123 additions and 38 deletions

View File

@ -164,7 +164,7 @@ function displaySingle(entState, template)
Engine.GetGUIObjectByName("resourceCarryingIcon").tooltip = sprintf(translate("Gain: %(amount)s"), { amount: getTradingTooltip(entState.trader.goods.amount) });
}
// And for number of workers
else if (entState.foundation && !entState.mirage)
else if (entState.foundation && entState.visibility == "visible")
{
Engine.GetGUIObjectByName("resourceCarryingIcon").hidden = false;
Engine.GetGUIObjectByName("resourceCarryingText").hidden = false;
@ -172,7 +172,7 @@ function displaySingle(entState, template)
Engine.GetGUIObjectByName("resourceCarryingText").caption = entState.foundation.numBuilders + " ";
Engine.GetGUIObjectByName("resourceCarryingIcon").tooltip = sprintf(translate("Number of builders.\nTasking another to this foundation would speed construction up by %(numb)s%%"), { numb : Math.round((Math.pow((entState.foundation.numBuilders+1)/entState.foundation.numBuilders, 0.7) - 1.0)*100) });
}
else if (entState.resourceSupply && (!entState.resourceSupply.killBeforeGather || !entState.hitpoints) && !entState.mirage)
else if (entState.resourceSupply && (!entState.resourceSupply.killBeforeGather || !entState.hitpoints) && entState.visibility == "visible")
{
Engine.GetGUIObjectByName("resourceCarryingIcon").hidden = false;
Engine.GetGUIObjectByName("resourceCarryingText").hidden = false;

View File

@ -5,17 +5,18 @@ const VIS_VISIBLE = 2;
function Fogging() {}
Fogging.prototype.Schema =
"<a:help>Allows this entity to be replaced by mirages entities in the fog-of-war.</a:help>" +
"<a:help>Allows this entity to be replaced by mirage entities in the fog-of-war.</a:help>" +
"<empty/>";
Fogging.prototype.Init = function()
{
this.activated = false;
this.mirages = [];
this.miraged = [];
this.seen = [];
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
for (var player = 0; player < cmpPlayerManager.GetNumPlayers(); ++player)
let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
for (let player = 0; player < cmpPlayerManager.GetNumPlayers(); ++player)
{
this.mirages.push(INVALID_ENTITY);
this.miraged.push(false);
@ -23,8 +24,36 @@ Fogging.prototype.Init = function()
}
};
Fogging.prototype.Activate = function()
{
let mustUpdate = !this.activated;
this.activated = true;
if (mustUpdate)
{
// Load a mirage for each player who has already seen the entity
let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
for (let player = 0; player < cmpPlayerManager.GetNumPlayers(); ++player)
{
if (this.seen[player])
this.LoadMirage(player);
}
}
};
Fogging.prototype.IsActivated = function()
{
return this.activated;
}
Fogging.prototype.LoadMirage = function(player)
{
if (!this.activated)
{
error("LoadMirage called for an entity with fogging deactivated");
return;
}
this.miraged[player] = true;
if (this.mirages[player] == INVALID_ENTITY)
@ -108,10 +137,17 @@ Fogging.prototype.LoadMirage = function(player)
// Notify the GUI the entity has been replaced by a mirage, in case it is selected at this moment
var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
cmpGuiInterface.AddMiragedEntity(player, this.entity, this.mirages[player]);
// Notify the range manager the visibility of this entity must be updated
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
cmpRangeManager.RequestVisibilityUpdate(this.entity);
};
Fogging.prototype.ForceMiraging = function(player)
{
if (!this.activated)
return;
this.seen[player] = true;
this.LoadMirage(player);
};
@ -140,21 +176,6 @@ Fogging.prototype.WasSeen = function(player)
return this.seen[player];
};
Fogging.prototype.OnVisibilityChanged = function(msg)
{
if (msg.player >= this.mirages.length)
return;
if (msg.newVisibility == VIS_VISIBLE)
{
this.miraged[msg.player] = false;
this.seen[msg.player] = true;
}
if (msg.newVisibility == VIS_FOGGED)
this.LoadMirage(msg.player);
};
Fogging.prototype.OnDestroy = function(msg)
{
for (var player = 0; player < this.mirages.length; ++player)
@ -172,4 +193,26 @@ Fogging.prototype.OnDestroy = function(msg)
}
};
Fogging.prototype.OnOwnershipChanged = function(msg)
{
// Always activate fogging for non-Gaia entities
if (msg.to > 0)
this.Activate();
};
Fogging.prototype.OnVisibilityChanged = function(msg)
{
if (msg.player >= this.mirages.length)
return;
if (msg.newVisibility == VIS_VISIBLE)
{
this.miraged[msg.player] = false;
this.seen[msg.player] = true;
}
if (msg.newVisibility == VIS_FOGGED && this.activated)
this.LoadMirage(msg.player);
};
Engine.RegisterComponentType(IID_Fogging, "Fogging", Fogging);

View File

@ -70,6 +70,11 @@ Health.prototype.SetHitpoints = function(value)
if (this.hitpoints == 0)
return;
// Before changing the value, activate Fogging if necessary to hide changes
let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
if (cmpFogging)
cmpFogging.Activate();
var old = this.hitpoints;
this.hitpoints = Math.max(1, Math.min(this.GetMaxHitpoints(), value));
@ -150,6 +155,11 @@ Health.prototype.Kill = function()
*/
Health.prototype.Reduce = function(amount)
{
// Before changing the value, activate Fogging if necessary to hide changes
let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
if (cmpFogging)
cmpFogging.Activate();
var state = { "killed": false };
if (amount >= 0 && this.hitpoints == this.GetMaxHitpoints())
{
@ -208,6 +218,11 @@ Health.prototype.Reduce = function(amount)
Health.prototype.Increase = function(amount)
{
// Before changing the value, activate Fogging if necessary to hide changes
let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
if (cmpFogging)
cmpFogging.Activate();
if (this.hitpoints == this.GetMaxHitpoints())
return {"old": this.hitpoints, "new":this.hitpoints};

View File

@ -97,6 +97,11 @@ ResourceSupply.prototype.GetDiminishingReturns = function()
ResourceSupply.prototype.TakeResources = function(rate)
{
// Before changing the amount, activate Fogging if necessary to hide changes
let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
if (cmpFogging)
cmpFogging.Activate();
if (this.infinite)
return { "amount": rate, "exhausted": false };

View File

@ -101,23 +101,23 @@ StatusBars.prototype.RegenerateSprites = function()
yoffset -= height * 1.2;
};
var cmpMirage = Engine.QueryInterface(this.entity, IID_Mirage);
var cmpPack = Engine.QueryInterface(this.entity, IID_Pack);
if (cmpPack && cmpPack.IsPacking())
{
AddBar("pack", cmpPack.GetProgress());
}
var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
if (cmpHealth && cmpHealth.GetHitpoints() > 0)
{
AddBar("health", cmpHealth.GetHitpoints() / cmpHealth.GetMaxHitpoints());
}
else if (cmpMirage && cmpMirage.Health())
AddBar("health", cmpMirage.GetHitpoints() / cmpMirage.GetMaxHitpoints());
var cmpResourceSupply = Engine.QueryInterface(this.entity, IID_ResourceSupply);
if (cmpResourceSupply)
{
AddBar("supply", cmpResourceSupply.IsInfinite() ? 1 : cmpResourceSupply.GetCurrentAmount() / cmpResourceSupply.GetMaxAmount());
}
else if (cmpMirage && cmpMirage.ResourceSupply())
AddBar("supply", cmpMirage.IsInfinite() ? 1 : cmpMirage.GetAmount() / cmpMirage.GetMaxAmount());
/*
// Rank icon disabled for now - see discussion around

View File

@ -433,8 +433,11 @@ void CTemplateLoader::CopyMirageSubset(CParamNode& out, const CParamNode& in)
permittedComponentTypes.insert("Footprint");
permittedComponentTypes.insert("Minimap");
permittedComponentTypes.insert("Ownership");
permittedComponentTypes.insert("OverlayRenderer");
permittedComponentTypes.insert("Position");
permittedComponentTypes.insert("Selectable");
permittedComponentTypes.insert("StatusBars");
permittedComponentTypes.insert("Visibility");
permittedComponentTypes.insert("VisualActor");
CParamNode::LoadXMLString(out, "<Entity/>");
@ -456,7 +459,6 @@ void CTemplateLoader::CopyMirageSubset(CParamNode& out, const CParamNode& in)
// Set the entity as mirage entity
CParamNode::LoadXMLString(out, "<Entity><Mirage/></Entity>");
CParamNode::LoadXMLString(out, "<Entity><Visibility><RetainInFog>true</RetainInFog><AlwaysVisible>false</AlwaysVisible><Preview>false</Preview></Visibility></Entity>");
}
void CTemplateLoader::CopyFoundationSubset(CParamNode& out, const CParamNode& in)

View File

@ -1454,12 +1454,15 @@ public:
return VIS_HIDDEN;
}
// Fogged entities must not disappear while the mirage is not ready
// Fogged entities are hidden in two cases:
// - They were not scouted
// - A mirage replaces them
CmpPtr<ICmpFogging> cmpFogging(ent);
if (cmpFogging && cmpFogging->WasSeen(player) && !cmpFogging->IsMiraged(player))
return VIS_FOGGED;
if (cmpFogging && cmpFogging->IsActivated() &&
(!cmpFogging->WasSeen(player) || cmpFogging->IsMiraged(player)))
return VIS_HIDDEN;
return VIS_HIDDEN;
return VIS_FOGGED;
}
ELosVisibility ComputeLosVisibility(entity_id_t ent, player_id_t player)
@ -1557,13 +1560,21 @@ public:
for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it)
{
UpdateVisibility(*it);
// Don't bother updating if we already did it in a global update
if (!m_GlobalVisibilityUpdate)
UpdateVisibility(*it);
}
m_ModifiedEntities.clear();
m_GlobalVisibilityUpdate = false;
}
virtual void RequestVisibilityUpdate(entity_id_t ent)
{
if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), ent) == m_ModifiedEntities.end())
m_ModifiedEntities.push_back(ent);
}
void UpdateVisibility(entity_id_t ent)
{
// Warning: Code related to fogging (like posting VisibilityChanged messages)
@ -1594,10 +1605,6 @@ public:
{
if (oldVisibilities[player-1] == newVisibilities[player-1])
continue;
// Another visibility update can be necessary to take in account new mirages
if (std::find(m_ModifiedEntities.begin(), m_ModifiedEntities.end(), ent) == m_ModifiedEntities.end())
m_ModifiedEntities.push_back(ent);
CMessageVisibilityChanged msg(player, ent, oldVisibilities[player-1], newVisibilities[player-1]);
GetSimContext().GetComponentManager().PostMessage(ent, msg);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 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
@ -30,6 +30,11 @@ class CCmpFoggingScripted : public ICmpFogging
public:
DEFAULT_SCRIPT_WRAPPER(FoggingScripted)
virtual bool IsActivated()
{
return m_Script.Call<bool>("IsActivated");
}
virtual bool WasSeen(player_id_t player)
{
return m_Script.Call<bool>("WasSeen", player);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 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
@ -30,6 +30,7 @@
class ICmpFogging : public IComponent
{
public:
virtual bool IsActivated() = 0;
virtual bool WasSeen(player_id_t player) = 0;
virtual bool IsMiraged(player_id_t player) = 0;
virtual void ForceMiraging(player_id_t player) = 0;

View File

@ -52,6 +52,7 @@ DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevea
DEFINE_INTERFACE_METHOD_1("GetLosRevealAll", bool, ICmpRangeManager, GetLosRevealAll, player_id_t)
DEFINE_INTERFACE_METHOD_5("GetElevationAdaptedRange", entity_pos_t, ICmpRangeManager, GetElevationAdaptedRange, CFixedVector3D, CFixedVector3D, entity_pos_t, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t)
DEFINE_INTERFACE_METHOD_1("RequestVisibilityUpdate", void, ICmpRangeManager, RequestVisibilityUpdate, entity_id_t)
DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool)
DEFINE_INTERFACE_METHOD_0("GetLosCircular", bool, ICmpRangeManager, GetLosCircular)
DEFINE_INTERFACE_METHOD_2("SetSharedLos", void, ICmpRangeManager, SetSharedLos, player_id_t, std::vector<player_id_t>)

View File

@ -323,6 +323,12 @@ public:
virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player) = 0;
virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player) = 0;
/**
* Request the update of the visibility cache of ent at next turn.
* Typically used for fogging.
*/
virtual void RequestVisibilityUpdate(entity_id_t ent) = 0;
/**
* GetLosVisibility wrapped for script calls.