From 962da61f127474f93ff254ca06935c1c782aa59d Mon Sep 17 00:00:00 2001 From: historic_bruno Date: Fri, 8 Jun 2012 04:41:39 +0000 Subject: [PATCH] Adds shared LOS for allied players, based on patch by Deiz/F00. Fixes #1334. This was SVN commit r11949. --- .../public/simulation/components/Player.js | 30 ++++++++++-- source/graphics/LOSTexture.cpp | 2 +- .../components/CCmpRangeManager.cpp | 48 +++++++++++++++++-- .../components/ICmpRangeManager.cpp | 1 + .../simulation2/components/ICmpRangeManager.h | 20 +++++--- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/Player.js b/binaries/data/mods/public/simulation/components/Player.js index 56c3a8a6b2..c646cb6b56 100644 --- a/binaries/data/mods/public/simulation/components/Player.js +++ b/binaries/data/mods/public/simulation/components/Player.js @@ -221,6 +221,30 @@ Player.prototype.GetDiplomacy = function() Player.prototype.SetDiplomacy = function(dipl) { this.diplomacy = dipl; + this.UpdateSharedLos(); +}; + +Player.prototype.SetDiplomacyIndex = function(idx, value) +{ + // TODO: send a message too? + this.diplomacy[idx] = value; + this.UpdateSharedLos(); +}; + +Player.prototype.UpdateSharedLos = function() +{ + var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); + if (!cmpRangeManager) + return; + + // TODO: only check our alliances currently, more advanced checks + // will be needed when we have full diplomacy + var sharedLos = []; + for (var i = 0; i < this.diplomacy.length; ++i) + if (this.IsAlly(i)) + sharedLos.push(i); + + cmpRangeManager.SetSharedLos(this.playerID, sharedLos); }; Player.prototype.GetFormations = function() @@ -275,7 +299,7 @@ Player.prototype.IsAI = function() Player.prototype.SetAlly = function(id) { - this.diplomacy[id] = 1; + this.SetDiplomacyIndex(id, 1); }; /** @@ -288,7 +312,7 @@ Player.prototype.IsAlly = function(id) Player.prototype.SetEnemy = function(id) { - this.diplomacy[id] = -1; + this.SetDiplomacyIndex(id, -1); }; /** @@ -301,7 +325,7 @@ Player.prototype.IsEnemy = function(id) Player.prototype.SetNeutral = function(id) { - this.diplomacy[id] = 0; + this.SetDiplomacyIndex(id, 0); }; /** diff --git a/source/graphics/LOSTexture.cpp b/source/graphics/LOSTexture.cpp index e89c7d7dcc..68e2f42c5b 100644 --- a/source/graphics/LOSTexture.cpp +++ b/source/graphics/LOSTexture.cpp @@ -178,7 +178,7 @@ void CLOSTexture::RecomputeTexture(int unit) if (!cmpRangeManager) return; - ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID())); + ICmpRangeManager::CLosQuerier los(cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID())); GenerateBitmap(los, &losData[0], m_MapSize, m_MapSize); diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index 44a098db82..83bc43b799 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -57,7 +57,7 @@ struct Query * Convert an owner ID (-1 = unowned, 0 = gaia, 1..30 = players) * into a 32-bit mask for quick set-membership tests. */ -static u32 CalcOwnerMask(i32 owner) +static u32 CalcOwnerMask(player_id_t owner) { if (owner >= -1 && owner < 31) return 1 << (1+owner); @@ -65,6 +65,23 @@ static u32 CalcOwnerMask(i32 owner) return 0; // owner was invalid } +/** + * Returns shared LOS mask for given list of players. + */ +static u32 CalcSharedLosMask(std::vector players) +{ + u32 playerMask = 0; + player_id_t player; + for (size_t i = 0; i < players.size(); i++) + { + player = players[i]; + if (player > 0 && player <= 16) + playerMask |= ICmpRangeManager::LOS_MASK << (2*(player-1)); + } + + return playerMask; +} + /** * Representation of an entity, with the data needed for queries. */ @@ -212,6 +229,9 @@ public: // (TODO: this is usually a waste of memory) std::vector m_LosStateRevealed; + // Shared LOS masks, one per player. + std::map m_SharedLosMasks; + static std::string GetSchema() { return ""; @@ -234,6 +254,10 @@ public: // will get confused when trying to run from enemies m_LosRevealAll[0] = true; + // This is not really an error condition, an entity recently created or destroyed + // might have an owner of INVALID_PLAYER + m_SharedLosMasks[INVALID_PLAYER] = 0; + m_LosCircular = false; m_TerrainVerticesPerSide = 0; @@ -265,6 +289,8 @@ public: // m_LosState must be serialized since it depends on the history of exploration SerializeVector()(serialize, "los state", m_LosState); + + SerializeMap()(serialize, "shared los masks", m_SharedLosMasks); } virtual void Serialize(ISerializer& serialize) @@ -910,9 +936,9 @@ public: virtual CLosQuerier GetLosQuerier(player_id_t player) { if (GetLosRevealAll(player)) - return CLosQuerier(player, m_LosStateRevealed, m_TerrainVerticesPerSide); + return CLosQuerier(GetSharedLosMask(player), m_LosStateRevealed, m_TerrainVerticesPerSide); else - return CLosQuerier(player, m_LosState, m_TerrainVerticesPerSide); + return CLosQuerier(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); } virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog) @@ -939,8 +965,7 @@ public: } // Visible if within a visible region - - CLosQuerier los(player, m_LosState, m_TerrainVerticesPerSide); + CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); if (los.IsVisible(i, j)) return VIS_VISIBLE; @@ -991,6 +1016,19 @@ public: return m_LosCircular; } + virtual void SetSharedLos(player_id_t player, std::vector players) + { + m_SharedLosMasks[player] = CalcSharedLosMask(players); + } + + virtual u32 GetSharedLosMask(player_id_t player) + { + std::map::const_iterator it = m_SharedLosMasks.find(player); + ENSURE(it != m_SharedLosMasks.end()); + + return m_SharedLosMasks[player]; + } + void UpdateTerritoriesLos() { CmpPtr cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY); diff --git a/source/simulation2/components/ICmpRangeManager.cpp b/source/simulation2/components/ICmpRangeManager.cpp index 4503ef2596..18d3bee473 100644 --- a/source/simulation2/components/ICmpRangeManager.cpp +++ b/source/simulation2/components/ICmpRangeManager.cpp @@ -48,5 +48,6 @@ DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevea 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_2("SetSharedLos", void, ICmpRangeManager, SetSharedLos, player_id_t, std::vector) DEFINE_INTERFACE_METHOD_1("GetPercentMapExplored", i32, ICmpRangeManager, GetPercentMapExplored, player_id_t) END_INTERFACE_WRAPPER(RangeManager) diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h index 142936e016..1a6abba9fb 100644 --- a/source/simulation2/components/ICmpRangeManager.h +++ b/source/simulation2/components/ICmpRangeManager.h @@ -185,13 +185,10 @@ public: friend class CCmpRangeManager; friend class TestLOSTexture; - CLosQuerier(player_id_t player, const std::vector& data, ssize_t verticesPerSide) : + CLosQuerier(u32 playerMask, const std::vector& data, ssize_t verticesPerSide) : m_Data(&data[0]), m_VerticesPerSide(verticesPerSide) { - if (player > 0 && player <= 16) - m_PlayerMask = LOS_MASK << (2*(player-1)); - else - m_PlayerMask = 0; + m_PlayerMask = playerMask; } const CLosQuerier& operator=(const CLosQuerier&); // not implemented @@ -266,7 +263,8 @@ public: }; /** - * Returns a CLosQuerier for checking whether vertex positions are visible to the given player. + * Returns a CLosQuerier for checking whether vertex positions are visible to the given player + * (or other players it shares LOS with). */ virtual CLosQuerier GetLosQuerier(player_id_t player) = 0; @@ -307,6 +305,16 @@ public: */ virtual bool GetLosCircular() = 0; + /** + * Sets shared LOS data for player to the given list of players. + */ + virtual void SetSharedLos(player_id_t player, std::vector players) = 0; + + /** + * Returns shared LOS mask for player. + */ + virtual u32 GetSharedLosMask(player_id_t player) = 0; + /** * Get percent map explored statistics for specified player. */