diff --git a/binaries/data/mods/public/simulation/components/Player.js b/binaries/data/mods/public/simulation/components/Player.js
index 56c3a8a..5dc6a5c 100644
a
|
b
|
Player.prototype.GetDiplomacy = function()
|
221 | 221 | Player.prototype.SetDiplomacy = function(dipl) |
222 | 222 | { |
223 | 223 | this.diplomacy = dipl; |
| 224 | this.UpdateSharedLos(); |
| 225 | }; |
| 226 | |
| 227 | Player.prototype.SetDiplomacyIndex = function(ind, value) |
| 228 | { |
| 229 | this.diplomacy[ind] = value; |
| 230 | this.UpdateSharedLos(); |
| 231 | }; |
| 232 | |
| 233 | Player.prototype.UpdateSharedLos = function() |
| 234 | { |
| 235 | var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); |
| 236 | if (!cmpRangeManager) |
| 237 | return; |
| 238 | |
| 239 | var allies = []; |
| 240 | for (var i = 0; i < this.diplomacy.length; ++i) |
| 241 | if (this.IsAlly(i)) |
| 242 | allies.push(i); |
| 243 | |
| 244 | cmpRangeManager.SetSharedLosMask( this.playerID, allies ); |
224 | 245 | }; |
225 | 246 | |
226 | 247 | Player.prototype.GetFormations = function() |
… |
… |
Player.prototype.IsAI = function()
|
275 | 296 | |
276 | 297 | Player.prototype.SetAlly = function(id) |
277 | 298 | { |
278 | | this.diplomacy[id] = 1; |
| 299 | this.SetDiplomacyIndex(id, 1); |
279 | 300 | }; |
280 | 301 | |
281 | 302 | /** |
… |
… |
Player.prototype.IsAlly = function(id)
|
288 | 309 | |
289 | 310 | Player.prototype.SetEnemy = function(id) |
290 | 311 | { |
291 | | this.diplomacy[id] = -1; |
| 312 | this.SetDiplomacyIndex(id, -1); |
292 | 313 | }; |
293 | 314 | |
294 | 315 | /** |
… |
… |
Player.prototype.IsEnemy = function(id)
|
301 | 322 | |
302 | 323 | Player.prototype.SetNeutral = function(id) |
303 | 324 | { |
304 | | this.diplomacy[id] = 0; |
| 325 | this.SetDiplomacyIndex(id, 0); |
305 | 326 | }; |
306 | 327 | |
307 | 328 | /** |
diff --git a/source/graphics/LOSTexture.cpp b/source/graphics/LOSTexture.cpp
index e89c7d7..5f9ebf7 100644
a
|
b
|
void CLOSTexture::RecomputeTexture(int unit)
|
178 | 178 | if (!cmpRangeManager) |
179 | 179 | return; |
180 | 180 | |
181 | | ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID())); |
| 181 | u32 playerMask = cmpRangeManager->GetSharedLosMask(g_Game->GetPlayerID()); |
| 182 | ICmpRangeManager::CLosQuerier los (cmpRangeManager->GetLosQuerier(g_Game->GetPlayerID(), playerMask)); |
182 | 183 | |
183 | 184 | GenerateBitmap(los, &losData[0], m_MapSize, m_MapSize); |
184 | 185 | |
diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp
index 44a098d..7d10b3d 100644
a
|
b
|
|
22 | 22 | |
23 | 23 | #include "simulation2/MessageTypes.h" |
24 | 24 | #include "simulation2/components/ICmpPosition.h" |
| 25 | #include "simulation2/components/ICmpPlayerManager.h" |
25 | 26 | #include "simulation2/components/ICmpTerritoryManager.h" |
26 | 27 | #include "simulation2/components/ICmpVision.h" |
27 | 28 | #include "simulation2/helpers/Render.h" |
… |
… |
public:
|
212 | 213 | // (TODO: this is usually a waste of memory) |
213 | 214 | std::vector<u32> m_LosStateRevealed; |
214 | 215 | |
| 216 | // Shared LOS masks, one per player. |
| 217 | std::vector<u32> m_PlayerLosMasks; |
| 218 | |
215 | 219 | static std::string GetSchema() |
216 | 220 | { |
217 | 221 | return "<a:component type='system'/><empty/>"; |
… |
… |
public:
|
915 | 919 | return CLosQuerier(player, m_LosState, m_TerrainVerticesPerSide); |
916 | 920 | } |
917 | 921 | |
| 922 | virtual CLosQuerier GetLosQuerier(player_id_t player, u32 playerMask) |
| 923 | { |
| 924 | if (GetLosRevealAll(player)) |
| 925 | return CLosQuerier(playerMask, m_LosStateRevealed, m_TerrainVerticesPerSide); |
| 926 | else |
| 927 | return CLosQuerier(playerMask, m_LosState, m_TerrainVerticesPerSide); |
| 928 | } |
| 929 | |
918 | 930 | virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog) |
919 | 931 | { |
| 932 | return GetLosVisibility(ent, player, 0, forceRetainInFog); |
| 933 | } |
| 934 | |
| 935 | virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, u32 playerMask, bool forceRetainInFog) |
| 936 | { |
920 | 937 | // (We can't use m_EntityData since this needs to handle LOCAL entities too) |
921 | 938 | |
922 | 939 | // Entities not with positions in the world are never visible |
… |
… |
public:
|
939 | 956 | } |
940 | 957 | |
941 | 958 | // Visible if within a visible region |
| 959 | if (!playerMask) |
| 960 | playerMask = GetSharedLosMask(player); |
942 | 961 | |
943 | | CLosQuerier los(player, m_LosState, m_TerrainVerticesPerSide); |
| 962 | CLosQuerier los(playerMask, m_LosState, m_TerrainVerticesPerSide); |
944 | 963 | |
945 | 964 | if (los.IsVisible(i, j)) |
946 | 965 | return VIS_VISIBLE; |
… |
… |
public:
|
957 | 976 | return VIS_HIDDEN; |
958 | 977 | } |
959 | 978 | |
| 979 | virtual u32 GetLosVisibilityMask(std::vector<player_id_t> players) |
| 980 | { |
| 981 | u32 playerMask = 0; |
| 982 | player_id_t player; |
| 983 | |
| 984 | for (size_t i = 0; i < players.size(); i++) |
| 985 | { |
| 986 | player = players[i]; |
| 987 | if (player > 0 && player <= 16) |
| 988 | playerMask |= LOS_MASK << (2*(player-1)); |
| 989 | } |
| 990 | |
| 991 | return playerMask; |
| 992 | } |
| 993 | |
960 | 994 | virtual void SetLosRevealAll(player_id_t player, bool enabled) |
961 | 995 | { |
962 | 996 | m_LosRevealAll[player] = enabled; |
… |
… |
public:
|
991 | 1025 | return m_LosCircular; |
992 | 1026 | } |
993 | 1027 | |
| 1028 | virtual void SetSharedLosMask(player_id_t player, std::vector<player_id_t> players) |
| 1029 | { |
| 1030 | CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSimContext(), SYSTEM_ENTITY); |
| 1031 | if (!cmpPlayerManager) |
| 1032 | return; |
| 1033 | |
| 1034 | int numPlayers = cmpPlayerManager->GetNumPlayers(); |
| 1035 | m_PlayerLosMasks.resize(numPlayers); |
| 1036 | |
| 1037 | if (player >= 0 && player <= (int)m_PlayerLosMasks.size()) |
| 1038 | m_PlayerLosMasks[player] = GetLosVisibilityMask(players); |
| 1039 | } |
| 1040 | |
| 1041 | virtual u32 GetSharedLosMask(player_id_t player) |
| 1042 | { |
| 1043 | if (player < 0 || player >= (int)m_PlayerLosMasks.size()) |
| 1044 | return 0; |
| 1045 | |
| 1046 | return m_PlayerLosMasks[player]; |
| 1047 | } |
| 1048 | |
994 | 1049 | void UpdateTerritoriesLos() |
995 | 1050 | { |
996 | 1051 | CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSimContext(), SYSTEM_ENTITY); |
diff --git a/source/simulation2/components/ICmpRangeManager.cpp b/source/simulation2/components/ICmpRangeManager.cpp
index 4503ef2..ad18ff2 100644
a
|
b
|
DEFINE_INTERFACE_METHOD_2("SetLosRevealAll", void, ICmpRangeManager, SetLosRevea
|
48 | 48 | DEFINE_INTERFACE_METHOD_3("GetLosVisibility", std::string, ICmpRangeManager, GetLosVisibility_wrapper, entity_id_t, player_id_t, bool) |
49 | 49 | DEFINE_INTERFACE_METHOD_1("SetLosCircular", void, ICmpRangeManager, SetLosCircular, bool) |
50 | 50 | DEFINE_INTERFACE_METHOD_0("GetLosCircular", bool, ICmpRangeManager, GetLosCircular) |
| 51 | DEFINE_INTERFACE_METHOD_2("SetSharedLosMask", void, ICmpRangeManager, SetSharedLosMask, player_id_t, std::vector<player_id_t>) |
51 | 52 | DEFINE_INTERFACE_METHOD_1("GetPercentMapExplored", i32, ICmpRangeManager, GetPercentMapExplored, player_id_t) |
52 | 53 | END_INTERFACE_WRAPPER(RangeManager) |
diff --git a/source/simulation2/components/ICmpRangeManager.h b/source/simulation2/components/ICmpRangeManager.h
index 142936e..2ebd6ff 100644
a
|
b
|
public:
|
194 | 194 | m_PlayerMask = 0; |
195 | 195 | } |
196 | 196 | |
| 197 | CLosQuerier(u32 playerMask, const std::vector<u32>& data, ssize_t verticesPerSide) : |
| 198 | m_Data(&data[0]), m_VerticesPerSide(verticesPerSide) |
| 199 | { |
| 200 | m_PlayerMask = playerMask; |
| 201 | } |
| 202 | |
197 | 203 | const CLosQuerier& operator=(const CLosQuerier&); // not implemented |
198 | 204 | |
199 | 205 | public: |
… |
… |
public:
|
269 | 275 | * Returns a CLosQuerier for checking whether vertex positions are visible to the given player. |
270 | 276 | */ |
271 | 277 | virtual CLosQuerier GetLosQuerier(player_id_t player) = 0; |
| 278 | virtual CLosQuerier GetLosQuerier(player_id_t player, u32 playerMask) = 0; |
272 | 279 | |
273 | 280 | /** |
274 | 281 | * Returns the visibility status of the given entity, with respect to the given player. |
… |
… |
public:
|
279 | 286 | * see http://trac.wildfiregames.com/ticket/958 |
280 | 287 | */ |
281 | 288 | virtual ELosVisibility GetLosVisibility(entity_id_t ent, player_id_t player, bool forceRetainInFog = false) = 0; |
| 289 | virtual u32 GetLosVisibilityMask(std::vector<player_id_t> players) = 0; |
282 | 290 | |
283 | 291 | /** |
284 | 292 | * GetLosVisibility wrapped for script calls. |
… |
… |
public:
|
308 | 316 | virtual bool GetLosCircular() = 0; |
309 | 317 | |
310 | 318 | /** |
| 319 | * Sets LOS mask for a player based on the supplied array of players. |
| 320 | */ |
| 321 | virtual void SetSharedLosMask(player_id_t player, std::vector<player_id_t> players) = 0; |
| 322 | virtual u32 GetSharedLosMask(player_id_t player) = 0; |
| 323 | |
| 324 | /** |
311 | 325 | * Get percent map explored statistics for specified player. |
312 | 326 | */ |
313 | 327 | virtual i32 GetPercentMapExplored(player_id_t player) = 0; |