From e72b603cce5fad4ecfaef0d8451acbcffd34efa7 Mon Sep 17 00:00:00 2001 From: historic_bruno Date: Mon, 24 Sep 2012 22:27:32 +0000 Subject: [PATCH] Implements Vision/Range tech modification This was SVN commit r12707. --- .../public/simulation/components/UnitAI.js | 7 +++ source/simulation2/MessageTypes.h | 18 +++++++ source/simulation2/TypeList.h | 1 + .../components/CCmpRangeManager.cpp | 38 ++++++++++++-- source/simulation2/components/CCmpVision.cpp | 52 +++++++++++++++++-- .../scripting/MessageTypeConversions.cpp | 20 +++++++ 6 files changed, 129 insertions(+), 7 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 4b831598c9..3b3ab2b64e 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -1953,6 +1953,13 @@ UnitAI.prototype.OnDestroy = function() rangeMan.DestroyActiveQuery(this.losGaiaRangeQuery); }; +UnitAI.prototype.OnVisionRangeChanged = function(msg) +{ + // Update range queries + if (this.entity == msg.entity) + this.SetupRangeQueries(); +}; + // Wrapper function that sets up the normal, healer, and Gaia range queries. UnitAI.prototype.SetupRangeQueries = function() { diff --git a/source/simulation2/MessageTypes.h b/source/simulation2/MessageTypes.h index f149f5060f..de8a31b566 100644 --- a/source/simulation2/MessageTypes.h +++ b/source/simulation2/MessageTypes.h @@ -380,4 +380,22 @@ public: player_id_t player; }; +/** + * Sent by CCmpVision when an entity's vision range changes. + */ +class CMessageVisionRangeChanged : public CMessage +{ +public: + DEFAULT_MESSAGE_IMPL(VisionRangeChanged) + + CMessageVisionRangeChanged(entity_id_t entity, entity_pos_t oldRange, entity_pos_t newRange) : + entity(entity), oldRange(oldRange), newRange(newRange) + { + } + + entity_id_t entity; + entity_pos_t oldRange; + entity_pos_t newRange; +}; + #endif // INCLUDED_MESSAGETYPES diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index 758b67b273..fc54a9da6c 100644 --- a/source/simulation2/TypeList.h +++ b/source/simulation2/TypeList.h @@ -48,6 +48,7 @@ MESSAGE(TerrainChanged) MESSAGE(TerritoriesChanged) MESSAGE(PathResult) MESSAGE(TechnologyModification) +MESSAGE(VisionRangeChanged) // TemplateManager must come before all other (non-test) components, // so that it is the first to be (de)serialized diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index 1363b1f8bf..45ff98bbaa 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -188,6 +188,7 @@ public: componentManager.SubscribeGloballyToMessageType(MT_PositionChanged); componentManager.SubscribeGloballyToMessageType(MT_OwnershipChanged); componentManager.SubscribeGloballyToMessageType(MT_Destroy); + componentManager.SubscribeGloballyToMessageType(MT_VisionRangeChanged); componentManager.SubscribeToMessageType(MT_Update); @@ -354,7 +355,7 @@ public: const CMessagePositionChanged& msgData = static_cast (msg); entity_id_t ent = msgData.entity; - std::map::iterator it = m_EntityData.find(ent); + std::map::iterator it = m_EntityData.find(ent); // Ignore if we're not already tracking this entity if (it == m_EntityData.end()) @@ -401,7 +402,7 @@ public: const CMessageOwnershipChanged& msgData = static_cast (msg); entity_id_t ent = msgData.entity; - std::map::iterator it = m_EntityData.find(ent); + std::map::iterator it = m_EntityData.find(ent); // Ignore if we're not already tracking this entity if (it == m_EntityData.end()) @@ -424,7 +425,7 @@ public: const CMessageDestroy& msgData = static_cast (msg); entity_id_t ent = msgData.entity; - std::map::iterator it = m_EntityData.find(ent); + std::map::iterator it = m_EntityData.find(ent); // Ignore if we're not already tracking this entity if (it == m_EntityData.end()) @@ -441,6 +442,37 @@ public: break; } + case MT_VisionRangeChanged: + { + const CMessageVisionRangeChanged& msgData = static_cast (msg); + entity_id_t ent = msgData.entity; + + std::map::iterator it = m_EntityData.find(ent); + + // Ignore if we're not already tracking this entity + if (it == m_EntityData.end()) + break; + + CmpPtr cmpVision(GetSimContext(), ent); + if (!cmpVision) + break; + + entity_pos_t oldRange = it->second.visionRange; + entity_pos_t newRange = msgData.newRange; + + // If the range changed and the entity's in-world, we need to manually adjust it + // but if it's not in-world, we only need to set the new vision range + CFixedVector2D pos(it->second.x, it->second.z); + if (it->second.inWorld) + LosRemove(it->second.owner, oldRange, pos); + + it->second.visionRange = newRange; + + if (it->second.inWorld) + LosAdd(it->second.owner, newRange, pos); + + break; + } case MT_Update: { m_DebugOverlayDirty = true; diff --git a/source/simulation2/components/CCmpVision.cpp b/source/simulation2/components/CCmpVision.cpp index cab52b0fa8..070ad44d7c 100644 --- a/source/simulation2/components/CCmpVision.cpp +++ b/source/simulation2/components/CCmpVision.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2012 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,18 +20,24 @@ #include "simulation2/system/Component.h" #include "ICmpVision.h" +#include "simulation2/MessageTypes.h" +#include "simulation2/components/ICmpOwnership.h" +#include "simulation2/components/ICmpPlayerManager.h" +#include "simulation2/components/ICmpTechnologyManager.h" + class CCmpVision : public ICmpVision { public: - static void ClassInit(CComponentManager& UNUSED(componentManager)) + static void ClassInit(CComponentManager& componentManager) { + componentManager.SubscribeGloballyToMessageType(MT_TechnologyModification); } DEFAULT_COMPONENT_ALLOCATOR(Vision) // Template state: - entity_pos_t m_Range; + entity_pos_t m_Range, m_BaseRange; bool m_RetainInFog; bool m_AlwaysVisible; @@ -51,7 +57,7 @@ public: virtual void Init(const CParamNode& paramNode) { - m_Range = paramNode.GetChild("Range").ToFixed(); + m_BaseRange = m_Range = paramNode.GetChild("Range").ToFixed(); m_RetainInFog = paramNode.GetChild("RetainInFog").ToBool(); m_AlwaysVisible = paramNode.GetChild("AlwaysVisible").ToBool(); } @@ -70,6 +76,44 @@ public: Init(paramNode); } + virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) + { + switch (msg.GetType()) + { + case MT_TechnologyModification: + { + const CMessageTechnologyModification& msgData = static_cast (msg); + if (msgData.component == L"Vision") + { + CmpPtr cmpOwnership(GetSimContext(), GetEntityId()); + if (cmpOwnership) + { + player_id_t owner = cmpOwnership->GetOwner(); + if (owner != INVALID_PLAYER && owner == msgData.player) + { + CmpPtr cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); + entity_id_t playerEnt = cmpPlayerManager->GetPlayerByID(owner); + CmpPtr cmpTechnologyManager(GetSimContext(), playerEnt); + if (playerEnt != INVALID_ENTITY && cmpTechnologyManager) + { + entity_pos_t newRange = cmpTechnologyManager->ApplyModifications(L"Vision/Range", m_BaseRange, GetEntityId()); + if (newRange != m_Range) + { + // Update our vision range and broadcast message + entity_pos_t oldRange = m_Range; + m_Range = newRange; + CMessageVisionRangeChanged msg(GetEntityId(), oldRange, newRange); + GetSimContext().GetComponentManager().BroadcastMessage(msg); + } + } + } + } + } + break; + } + } + } + virtual entity_pos_t GetRange() { return m_Range; diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index 21ed4542ad..c4109d7299 100644 --- a/source/simulation2/scripting/MessageTypeConversions.cpp +++ b/source/simulation2/scripting/MessageTypeConversions.cpp @@ -316,6 +316,26 @@ CMessage* CMessageTechnologyModification::FromJSVal(ScriptInterface& scriptInter return new CMessageTechnologyModification(component, player); } +//////////////////////////////// + +jsval CMessageVisionRangeChanged::ToJSVal(ScriptInterface& scriptInterface) const +{ + TOJSVAL_SETUP(); + SET_MSG_PROPERTY(entity); + SET_MSG_PROPERTY(oldRange); + SET_MSG_PROPERTY(newRange); + return OBJECT_TO_JSVAL(obj); +} + +CMessage* CMessageVisionRangeChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) +{ + FROMJSVAL_SETUP(); + GET_MSG_PROPERTY(entity_id_t, entity); + GET_MSG_PROPERTY(entity_pos_t, oldRange); + GET_MSG_PROPERTY(entity_pos_t, newRange); + return new CMessageVisionRangeChanged(entity, oldRange, newRange); +} + //////////////////////////////////////////////////////////////// CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, jsval val)