diff --git a/binaries/data/mods/public/simulation/components/Visibility.js b/binaries/data/mods/public/simulation/components/Visibility.js new file mode 100644 index 0000000000..0b137ca18c --- /dev/null +++ b/binaries/data/mods/public/simulation/components/Visibility.js @@ -0,0 +1,59 @@ +const VIS_HIDDEN = 0; +const VIS_FOGGED = 1; +const VIS_VISIBLE = 2; + +function Visibility() {} + +Visibility.prototype.Schema = + ""; + +Visibility.prototype.Init = function() +{ + +}; + +/** + * This function is called for entities in explored territory. + * isOutsideFog: true if we're in the vision range of a unit, false otherwise + * forceRetainInFog: useful for previewed entities, see the RangeManager system component documentation + */ +Visibility.prototype.GetLosVisibility = function(player, isOutsideFog, forceRetainInFog) +{ + if (isOutsideFog) + return VIS_VISIBLE; + + // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region + var cmpVision = Engine.QueryInterface(this.entity, IID_Vision); + if (!forceRetainInFog && !(cmpVision && cmpVision.GetRetainInFog())) + return VIS_HIDDEN; + + var cmpMirage = Engine.QueryInterface(this.entity, IID_Mirage); + if (cmpMirage && cmpMirage.GetPlayer() == player) + return VIS_FOGGED; + + var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); + if (!cmpOwnership) + return VIS_FOGGED; + + if (cmpOwnership.GetOwner() == player) + { + var cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging); + if (!cmpFogging) + return VIS_FOGGED; + + // Fogged entities must not disappear while the mirage is not ready + if (!cmpFogging.IsMiraged(player)) + return VIS_FOGGED; + + return VIS_HIDDEN; + } + + // Fogged entities must not disappear while the mirage is not ready + var cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging); + if (cmpFogging && cmpFogging.WasSeen(player) && !cmpFogging.IsMiraged(player)) + return VIS_FOGGED; + + return VIS_HIDDEN; +}; + +Engine.RegisterComponentType(IID_Visibility, "Visibility", Visibility); diff --git a/binaries/data/mods/public/simulation/templates/template_gaia.xml b/binaries/data/mods/public/simulation/templates/template_gaia.xml index 7a5f54b1c0..5acbdb1ff5 100644 --- a/binaries/data/mods/public/simulation/templates/template_gaia.xml +++ b/binaries/data/mods/public/simulation/templates/template_gaia.xml @@ -20,6 +20,7 @@ 0.333 5.0 + 0 true diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml index 47cc0efea7..c1cf8cfd15 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure.xml @@ -101,6 +101,7 @@ 5 + 40 true diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index 131fc734ed..79ad81a10d 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit.xml @@ -104,6 +104,7 @@ default default + 10 false diff --git a/source/ps/TemplateLoader.cpp b/source/ps/TemplateLoader.cpp index 3c985fc829..07ceea6c5b 100644 --- a/source/ps/TemplateLoader.cpp +++ b/source/ps/TemplateLoader.cpp @@ -352,6 +352,7 @@ void CTemplateLoader::CopyPreviewSubset(CParamNode& out, const CParamNode& in, b permittedComponentTypes.insert("Identity"); permittedComponentTypes.insert("Ownership"); permittedComponentTypes.insert("Position"); + permittedComponentTypes.insert("Visibility"); permittedComponentTypes.insert("VisualActor"); permittedComponentTypes.insert("Footprint"); permittedComponentTypes.insert("Obstruction"); @@ -408,6 +409,7 @@ void CTemplateLoader::CopyMirageSubset(CParamNode& out, const CParamNode& in) permittedComponentTypes.insert("Ownership"); permittedComponentTypes.insert("Position"); permittedComponentTypes.insert("Selectable"); + permittedComponentTypes.insert("Visibility"); permittedComponentTypes.insert("VisualActor"); CParamNode::LoadXMLString(out, ""); @@ -454,6 +456,7 @@ void CTemplateLoader::CopyFoundationSubset(CParamNode& out, const CParamNode& in permittedComponentTypes.insert("Decay"); permittedComponentTypes.insert("Cost"); permittedComponentTypes.insert("Sound"); + permittedComponentTypes.insert("Visibility"); permittedComponentTypes.insert("Vision"); permittedComponentTypes.insert("AIProxy"); permittedComponentTypes.insert("RallyPoint"); diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index eb5ac6a0ad..7b71ce1f46 100644 --- a/source/simulation2/TypeList.h +++ b/source/simulation2/TypeList.h @@ -174,6 +174,9 @@ COMPONENT(UnitMotionScripted) INTERFACE(UnitRenderer) COMPONENT(UnitRenderer) +INTERFACE(Visibility) +COMPONENT(VisibilityScripted) + INTERFACE(Vision) COMPONENT(Vision) diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index a0df174e86..1dfaef1915 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -28,6 +28,7 @@ #include "simulation2/components/ICmpOwnership.h" #include "simulation2/components/ICmpPosition.h" #include "simulation2/components/ICmpTerritoryManager.h" +#include "simulation2/components/ICmpVisibility.h" #include "simulation2/components/ICmpVision.h" #include "simulation2/components/ICmpWaterManager.h" #include "simulation2/helpers/Render.h" @@ -1377,10 +1378,6 @@ public: virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player, bool forceRetainInFog) { - // This function provides the real visibility of any entity (even local ones) at any time. - // The m_EntityData visibility is updated at most once per turn with this function's return value - // and must not be used for rendering - // Entities not with positions in the world are never visible if (ent.GetId() == INVALID_ENTITY) return VIS_HIDDEN; @@ -1409,42 +1406,21 @@ public: // Visible if within a visible region CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); + if (!los.IsExplored(i, j)) + return VIS_HIDDEN; + + // Try to ask the Visibility component of the entity, if any + CmpPtr cmpVisibility(ent); + if (cmpVisibility) + return cmpVisibility->GetLosVisibility(player, los.IsVisible(i, j), forceRetainInFog); + + // Default behaviour if (los.IsVisible(i, j)) return VIS_VISIBLE; - - if (!los.IsExplored(i, j)) - return VIS_HIDDEN; - - // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region - CmpPtr cmpVision(ent); - if (!forceRetainInFog && !(cmpVision && cmpVision->GetRetainInFog())) - return VIS_HIDDEN; - - if (cmpMirage && cmpMirage->GetPlayer() == player) - return VIS_FOGGED; - - CmpPtr cmpOwnership(ent); - if (!cmpOwnership) - return VIS_VISIBLE; - if (cmpOwnership->GetOwner() == player) - { - CmpPtr cmpFogging(ent); - if (!cmpFogging) - return VIS_VISIBLE; - - // Fogged entities must not disappear while the mirage is not ready - if (!cmpFogging->IsMiraged(player)) - return VIS_FOGGED; - - return VIS_HIDDEN; - } - - // Fogged entities must not disappear while the mirage is not ready - CmpPtr cmpFogging(ent); - if (cmpFogging && cmpFogging->WasSeen(player) && !cmpFogging->IsMiraged(player)) + if (forceRetainInFog) return VIS_FOGGED; - + return VIS_HIDDEN; } diff --git a/source/simulation2/components/ICmpVisibility.cpp b/source/simulation2/components/ICmpVisibility.cpp new file mode 100644 index 0000000000..d2963f991c --- /dev/null +++ b/source/simulation2/components/ICmpVisibility.cpp @@ -0,0 +1,52 @@ +/* Copyright (C) 2014 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "ICmpVisibility.h" + +#include "simulation2/scripting/ScriptComponent.h" +#include "simulation2/system/InterfaceScripted.h" + +BEGIN_INTERFACE_WRAPPER(Visibility) +END_INTERFACE_WRAPPER(Visibility) + +class CCmpVisibilityScripted : public ICmpVisibility +{ +public: + DEFAULT_SCRIPT_WRAPPER(VisibilityScripted) + + virtual ICmpRangeManager::ELosVisibility GetLosVisibility(player_id_t player, bool isOutsideFog, bool forceRetainInFog) + { + int visibility = m_Script.Call("GetLosVisibility", player, isOutsideFog, forceRetainInFog); + + switch (visibility) + { + case ICmpRangeManager::VIS_HIDDEN: + return ICmpRangeManager::VIS_HIDDEN; + case ICmpRangeManager::VIS_FOGGED: + return ICmpRangeManager::VIS_FOGGED; + case ICmpRangeManager::VIS_VISIBLE: + return ICmpRangeManager::VIS_VISIBLE; + default: + LOGERROR(L"Received the invalid visibility value %d from the Visibility scripted component!", visibility); + return ICmpRangeManager::VIS_HIDDEN; + } + } +}; + +REGISTER_COMPONENT_SCRIPT_WRAPPER(VisibilityScripted) diff --git a/source/simulation2/components/ICmpVisibility.h b/source/simulation2/components/ICmpVisibility.h new file mode 100644 index 0000000000..15f30efa21 --- /dev/null +++ b/source/simulation2/components/ICmpVisibility.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2014 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_ICMPVISIBILITY +#define INCLUDED_ICMPVISIBILITY + +#include "simulation2/system/Interface.h" + +#include "simulation2/components/ICmpRangeManager.h" + +class ICmpVisibility : public IComponent +{ +public: + virtual ICmpRangeManager::ELosVisibility GetLosVisibility(player_id_t player, bool isOutsideFog, bool forceRetainInFog) = 0; + + DECLARE_INTERFACE_TYPE(Visibility) +}; + +#endif // INCLUDED_ICMPVISIBILITY