diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index 5e83f04d4e..b45d7e9f7c 100644 --- a/binaries/data/mods/public/simulation/components/GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -255,7 +255,7 @@ GuiInterface.prototype.GetEntityState = function(player, ent) } var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - ret.visibility = cmpRangeManager.GetLosVisibility(ent, player); + ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false); return ret; }; @@ -508,22 +508,24 @@ GuiInterface.prototype.SetBuildingPlacementPreview = function(player, cmd) pos.SetYRotation(cmd.angle); } - // Check whether it's in a visible region + // Check whether it's in a visible or fogged region + // tell GetLosVisibility to force RetainInFog because preview entities set this to false, + // which would show them as hidden instead of fogged var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var visible = (cmpRangeManager && cmpRangeManager.GetLosVisibility(ent, player) == "visible"); + var hidden = (cmpRangeManager && cmpRangeManager.GetLosVisibility(ent, player, true) == "hidden"); var validPlacement = false; - - if (visible) + + if (!hidden) { // Check whether it's obstructed by other entities or invalid terrain var cmpBuildRestrictions = Engine.QueryInterface(ent, IID_BuildRestrictions); if (!cmpBuildRestrictions) error("cmpBuildRestrictions not defined"); - + validPlacement = (cmpBuildRestrictions && cmpBuildRestrictions.CheckPlacement(player)); } - var ok = (visible && validPlacement); - + var ok = (!hidden && validPlacement); + // Set it to a red shade if this is an invalid location var cmpVisual = Engine.QueryInterface(ent, IID_Visual); if (cmpVisual) diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index e6988ca981..b112dbe8e3 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -1945,7 +1945,7 @@ UnitAI.prototype.CheckTargetVisible = function(target) if (!cmpRangeManager) return false; - if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner()) == "hidden") + if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner(), false) == "hidden") return false; // Either visible directly, or visible in fog diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index e3e59944f3..d86a1c1798 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -216,10 +216,12 @@ function ProcessCommand(player, cmd) // TODO: AI has no visibility info if (!cmpPlayer.IsAI()) { - // Check whether it's in a visible region + // Check whether it's in a visible or fogged region + // tell GetLosVisibility to force RetainInFog because preview entities set this to false, + // which would show them as hidden instead of fogged var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var visible = (cmpRangeManager.GetLosVisibility(ent, player) == "visible"); - if (!visible) + var hidden = (cmpRangeManager.GetLosVisibility(ent, player, true) == "hidden"); + if (hidden) { if (g_DebugCommands) { diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index 28581e0995..e9c275bd57 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -872,7 +872,7 @@ public: return CLosQuerier(player, m_LosState, m_TerrainVerticesPerSide); } - virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player) + virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog) { // (We can't use m_EntityData since this needs to handle LOCAL entities too) @@ -906,7 +906,7 @@ public: if (los.IsExplored(i, j)) { CmpPtr cmpVision(GetSimContext(), ent); - if (!cmpVision.null() && cmpVision->GetRetainInFog()) + if (forceRetainInFog || (!cmpVision.null() && cmpVision->GetRetainInFog())) return VIS_FOGGED; } diff --git a/source/simulation2/components/ICmpRangeManager.cpp b/source/simulation2/components/ICmpRangeManager.cpp index 3350b588e4..29f0bafe61 100644 --- a/source/simulation2/components/ICmpRangeManager.cpp +++ b/source/simulation2/components/ICmpRangeManager.cpp @@ -21,9 +21,9 @@ #include "simulation2/system/InterfaceScripted.h" -std::string ICmpRangeManager::GetLosVisibility_wrapper(entity_id_t ent, int player) +std::string ICmpRangeManager::GetLosVisibility_wrapper(entity_id_t ent, int player, bool forceRetainInFog) { - ELosVisibility visibility = GetLosVisibility(ent, player); + ELosVisibility visibility = GetLosVisibility(ent, player, forceRetainInFog); switch (visibility) { case VIS_HIDDEN: return "hidden"; @@ -43,7 +43,7 @@ DEFINE_INTERFACE_METHOD_1("ResetActiveQuery", std::vector, ICmpRang DEFINE_INTERFACE_METHOD_1("GetEntitiesByPlayer", std::vector, ICmpRangeManager, GetEntitiesByPlayer, player_id_t) DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpRangeManager, SetDebugOverlay, bool) DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevealAll, player_id_t, bool) -DEFINE_INTERFACE_METHOD_2("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t) +DEFINE_INTERFACE_METHOD_3("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t, bool) DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool) DEFINE_INTERFACE_METHOD_0("GetLosCircular", bool, ICmpRangeManager, GetLosCircular) DEFINE_INTERFACE_METHOD_1("GetPercentMapExplored", i32, ICmpRangeManager, GetPercentMapExplored, player_id_t) diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h index e3fb98c0dd..c001400565 100644 --- a/source/simulation2/components/ICmpRangeManager.h +++ b/source/simulation2/components/ICmpRangeManager.h @@ -260,14 +260,17 @@ public: * Returns the visibility status of the given entity, with respect to the given player. * Returns VIS_HIDDEN if the entity doesn't exist or is not in the world. * This respects the GetLosRevealAll flag. + * If forceRetainInFog is true, the visibility acts as if CCmpVision's RetainInFog flag were set. + * TODO: This is a hack to allow preview entities in FoW to return fogged instead of hidden, + * see http://trac.wildfiregames.com/ticket/958 */ - virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player) = 0; + virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog = false) = 0; /** * GetLosVisibility wrapped for script calls. * Returns "hidden", "fogged" or "visible". */ - std::string GetLosVisibility_wrapper(entity_id_t ent, player_id_t player); + std::string GetLosVisibility_wrapper(entity_id_t ent, player_id_t player, bool forceRetainInFog); /** * Set whether the whole map should be made visible to the given player.