Ticket #599: fogging+optimization.patch
File fogging+optimization.patch, 43.4 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/simulation/components/BuildingAI.js
335 335 336 336 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 337 337 338 // Entities that are hidden and miraged are considered visible 339 var cmpFogging = Engine.QueryInterface(target, IID_Fogging); 340 if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner())) 341 return true; 342 338 343 if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner(), false) == "hidden") 339 344 return false; 340 345 -
binaries/data/mods/public/simulation/components/BuildRestrictions.js
102 102 if (!cmpRangeManager || !cmpOwnership) 103 103 return result; // Fail 104 104 105 var cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging); 105 106 var explored = (cmpRangeManager.GetLosVisibility(this.entity, cmpOwnership.GetOwner(), true) != "hidden"); 106 if (!explored )107 if (!explored && !(cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner()))) 107 108 { 108 109 result.message = markForTranslation("%(name)s cannot be built in unexplored area"); 109 110 return result; // Fail -
binaries/data/mods/public/simulation/components/GuiInterface.js
175 175 "garrisonHolder": null, 176 176 "gate": null, 177 177 "guard": null, 178 "mirage": null, 178 179 "pack": null, 179 180 "player": -1, 180 181 "position": null, … … 303 304 }; 304 305 } 305 306 307 var cmpMirage = Engine.QueryInterface(ent, IID_Mirage); 308 if (cmpMirage) 309 { 310 ret.mirage = { 311 "parent": cmpMirage.GetParent(), 312 }; 313 } 314 306 315 var cmpGate = Engine.QueryInterface(ent, IID_Gate); 307 316 if (cmpGate) 308 317 { -
binaries/data/mods/public/simulation/components/interfaces/Messages.js
1 /**2 * Broadcast message3 * sent when one entity is changed to other:4 * from Foundation component when building constuction is done5 * and from Promotion component when unit is promoted6 * Data: { entity: <integer>, newentity: <integer> }7 */8 Engine.RegisterMessageType("EntityRenamed");9 10 1 Engine.RegisterMessageType("DiplomacyChanged"); -
binaries/data/mods/public/simulation/components/UnitAI.js
3896 3896 if (cmpFormation) 3897 3897 return true; 3898 3898 3899 var cmpMirage = Engine.QueryInterface(ent, IID_Mirage); 3900 if (cmpMirage) 3901 return true; 3902 3899 3903 var cmpHealth = Engine.QueryInterface(ent, IID_Health); 3900 3904 if (!cmpHealth) 3901 3905 return false; … … 4386 4390 if (!cmpRangeManager) 4387 4391 return false; 4388 4392 4393 // Entities that are hidden and miraged are considered visible 4394 var cmpFogging = Engine.QueryInterface(target, IID_Fogging); 4395 if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner())) 4396 return true; 4397 4389 4398 if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner(), false) == "hidden") 4390 4399 return false; 4391 4400 -
binaries/data/mods/public/simulation/templates/template_gaia.xml
1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity parent="template_entity_quasi"> 3 <Fogging/> 3 4 <Identity> 4 5 <Civ>gaia</Civ> 5 6 <GenericName>Gaia</GenericName> -
binaries/data/mods/public/simulation/templates/template_structure.xml
37 37 <SinkRate>3.0</SinkRate> 38 38 <SinkAccel>9.8</SinkAccel> 39 39 </Decay> 40 <Fogging/> 40 41 <Health> 41 42 <DeathType>corpse</DeathType> 42 43 <RegenRate>0</RegenRate> -
source/ps/TemplateLoader.cpp
80 80 return true; 81 81 } 82 82 83 // Handle special case "mirage|foo" 84 if (templateName.find("mirage|") == 0) 85 { 86 // Load the base entity template, if it wasn't already loaded 87 std::string baseName = templateName.substr(7); 88 if (!LoadTemplateFile(baseName, depth+1)) 89 { 90 LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str()); 91 return false; 92 } 93 // Copy a subset to the requested template 94 CopyMirageSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName]); 95 return true; 96 } 97 83 98 // Handle special case "foundation|foo" 84 99 if (templateName.find("foundation|") == 0) 85 100 { … … 380 395 } 381 396 } 382 397 398 void CTemplateLoader::CopyMirageSubset(CParamNode& out, const CParamNode& in) 399 { 400 // Currently used for mirage entities replacing real ones in fog-of-war 401 402 std::set<std::string> permittedComponentTypes; 403 permittedComponentTypes.insert("Footprint"); 404 permittedComponentTypes.insert("Health"); 405 permittedComponentTypes.insert("Minimap"); 406 permittedComponentTypes.insert("Ownership"); 407 permittedComponentTypes.insert("Position"); 408 permittedComponentTypes.insert("ResourceSupply"); 409 permittedComponentTypes.insert("Selectable"); 410 permittedComponentTypes.insert("VisualActor"); 411 412 CParamNode::LoadXMLString(out, "<Entity/>"); 413 out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes); 414 415 // Select a subset of identity data. We don't want to have, for example, a CC mirage 416 // that has also the CC class and then prevents construction of other CCs 417 std::set<std::string> identitySubset; 418 identitySubset.insert("Civ"); 419 identitySubset.insert("GenericName"); 420 identitySubset.insert("SpecificName"); 421 identitySubset.insert("Tooltip"); 422 identitySubset.insert("History"); 423 identitySubset.insert("Icon"); 424 CParamNode identity; 425 CParamNode::LoadXMLString(identity, "<Identity/>"); 426 identity.CopyFilteredChildrenOfChild(in.GetChild("Entity"), "Identity", identitySubset); 427 CParamNode::LoadXMLString(out, ("<Entity>"+utf8_from_wstring(identity.ToXML())+"</Entity>").c_str()); 428 429 // Set the entity as mirage entity 430 CParamNode::LoadXMLString(out, "<Entity><Mirage/></Entity>"); 431 CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range><RetainInFog>true</RetainInFog><AlwaysVisible>false</AlwaysVisible></Vision></Entity>"); 432 } 433 383 434 void CTemplateLoader::CopyFoundationSubset(CParamNode& out, const CParamNode& in) 384 435 { 385 436 // TODO: this is all kind of yucky and hard-coded; it'd be nice to have a more generic … … 394 445 permittedComponentTypes.insert("Obstruction"); 395 446 permittedComponentTypes.insert("Selectable"); 396 447 permittedComponentTypes.insert("Footprint"); 448 permittedComponentTypes.insert("Fogging"); 397 449 permittedComponentTypes.insert("Armour"); 398 450 permittedComponentTypes.insert("Health"); 399 451 permittedComponentTypes.insert("StatusBars"); -
source/ps/TemplateLoader.h
79 79 void CopyPreviewSubset(CParamNode& out, const CParamNode& in, bool corpse); 80 80 81 81 /** 82 * Copy the components of an entity template necessary for a fogged "mirage" 83 * entity (position, actor) into a new entity template 84 */ 85 void CopyMirageSubset(CParamNode& out, const CParamNode& in); 86 87 /** 82 88 * Copy the components of an entity template necessary for a construction foundation 83 89 * (position, actor, armour, health, etc) into a new entity template 84 90 */ -
source/simulation2/components/CCmpFogging.cpp
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "simulation2/system/Component.h" 21 #include "simulation2/MessageTypes.h" 22 #include "ICmpFogging.h" 23 24 #include "lib/utf8.h" 25 26 #include "ICmpOwnership.h" 27 #include "ICmpPlayerManager.h" 28 #include "ICmpRangeManager.h" 29 #include "ICmpTemplateManager.h" 30 #include "ICmpVisual.h" 31 32 #include "ICmpMirage.h" 33 #include "ICmpPosition.h" 34 35 class CCmpFogging : public ICmpFogging 36 { 37 public: 38 static void ClassInit(CComponentManager& componentManager) 39 { 40 componentManager.SubscribeToMessageType(MT_VisibilityChanged); 41 componentManager.SubscribeToMessageType(MT_Destroy); 42 } 43 44 DEFAULT_COMPONENT_ALLOCATOR(Fogging) 45 46 static std::string GetSchema() 47 { 48 return "<a:help>Allows this entity to be replaced by mirages entities in the fog-of-war.</a:help>" 49 "<empty/>"; 50 } 51 52 virtual void Init(const CParamNode& UNUSED(paramNode)) 53 { 54 CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity()); 55 size_t numPlayers = cmpPlayerManager->GetNumPlayers(); 56 57 for (size_t i = 0; i < numPlayers; ++i) 58 { 59 m_Mirages.push_back(INVALID_ENTITY); 60 m_Miraged.push_back(false); 61 } 62 } 63 64 virtual void Deinit() 65 { 66 } 67 68 template<typename S> 69 void SerializeCommon(S& serialize) 70 { 71 SerializeVector<SerializeU32_Unbounded>()(serialize, "mirages", m_Mirages); 72 SerializeVector<SerializeBool>()(serialize, "enable mirages", m_Miraged); 73 } 74 75 virtual void Serialize(ISerializer& serialize) 76 { 77 SerializeCommon(serialize); 78 } 79 80 virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize) 81 { 82 SerializeCommon(deserialize); 83 } 84 85 virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) 86 { 87 switch (msg.GetType()) 88 { 89 case MT_VisibilityChanged: 90 { 91 const CMessageVisibilityChanged& msgData = static_cast<const CMessageVisibilityChanged&> (msg); 92 UpdateMirage(msgData.player); 93 break; 94 } 95 case MT_Destroy: 96 for (std::vector<entity_id_t>::iterator it = m_Mirages.begin(); it < m_Mirages.end(); ++it) 97 { 98 CmpPtr<ICmpMirage> cmpMirage(GetSimContext(), *it); 99 if (cmpMirage) 100 cmpMirage->SetParent(INVALID_ENTITY); 101 } 102 break; 103 } 104 } 105 106 virtual void UpdateMirage(player_id_t player) 107 { 108 CComponentManager& componentManager = GetSimContext().GetComponentManager(); 109 CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity()); 110 CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSystemEntity()); 111 112 std::string templateName = "mirage|" + cmpTemplateManager->GetCurrentTemplateName(GetEntityId()); 113 114 ICmpRangeManager::ELosVisibility visibility = cmpRangeManager->GetLosVisibility(GetEntityHandle(), player); 115 116 // Nothing to update 117 if (visibility == ICmpRangeManager::VIS_FOGGED) 118 return; 119 120 // Destroy mirages when we get back into LoS 121 if (visibility == ICmpRangeManager::VIS_VISIBLE) 122 { 123 if (m_Mirages[player] != INVALID_ENTITY) 124 { 125 componentManager.DestroyComponentsSoon(m_Mirages[player]); 126 m_Mirages[player] = INVALID_ENTITY; 127 } 128 return; 129 } 130 131 // Else, we are hidden and we should consider miraging 132 133 if (!m_Miraged[player] || m_Mirages[player] != INVALID_ENTITY) 134 return; 135 136 m_Mirages[player] = componentManager.AllocateNewEntity(); 137 componentManager.AddEntity(wstring_from_utf8(templateName), m_Mirages[player]); 138 139 CmpPtr<ICmpMirage> cmpMirage(GetSimContext(), m_Mirages[player]); 140 if (!cmpMirage) 141 { 142 LOGERROR(L"Failed to load mirage entity for template %hs", templateName.c_str()); 143 m_Mirages[player] = INVALID_ENTITY; 144 return; 145 } 146 147 // Setup basic mirage properties 148 cmpMirage->SetPlayer(player); 149 cmpMirage->SetParent(GetEntityId()); 150 151 // Copy cmpOwnership data 152 CmpPtr<ICmpOwnership> cmpParentOwnership(GetEntityHandle()); 153 if (!cmpParentOwnership) 154 { 155 LOGERROR(L"Failed to access the ownership data of the fogged entity %hs", templateName.c_str()); 156 return; 157 } 158 CmpPtr<ICmpOwnership> cmpMirageOwnership(GetSimContext(), m_Mirages[player]); 159 if (!cmpMirageOwnership) 160 { 161 LOGERROR(L"No valid Ownership in template %hs", templateName.c_str()); 162 return; 163 } 164 player_id_t parentOwner = cmpParentOwnership->GetOwner(); 165 cmpMirageOwnership->SetOwner(parentOwner); 166 167 // Copy cmpPosition data 168 CmpPtr<ICmpPosition> cmpParentPosition(GetEntityHandle()); 169 if (!cmpParentPosition) 170 { 171 LOGERROR(L"Failed to access the position data of the fogged entity %hs", templateName.c_str()); 172 return; 173 } 174 CmpPtr<ICmpPosition> cmpMiragePosition(GetSimContext(), m_Mirages[player]); 175 if (!cmpMiragePosition) 176 { 177 LOGERROR(L"No valid Position component in template %hs", templateName.c_str()); 178 return; 179 } 180 // The entity may not have been moved in-world yet, if we are e.g. placing a new building 181 if (!cmpParentPosition->IsInWorld()) 182 return; 183 CFixedVector3D pos = cmpParentPosition->GetPosition(); 184 cmpMiragePosition->JumpTo(pos.X, pos.Z); 185 CFixedVector3D rot = cmpParentPosition->GetRotation(); 186 cmpMiragePosition->SetXZRotation(rot.X, rot.Z); 187 cmpMiragePosition->SetYRotation(rot.Y); 188 189 // Copy cmpVisualActor data 190 CmpPtr<ICmpVisual> cmpParentVisualActor(GetEntityHandle()); 191 if (!cmpParentVisualActor) 192 { 193 LOGERROR(L"Failed to access the visual actor of the fogged entity %hs", templateName.c_str()); 194 return; 195 } 196 CmpPtr<ICmpVisual> cmpMirageVisualActor(GetSimContext(), m_Mirages[player]); 197 if (!cmpMirageVisualActor) 198 { 199 LOGERROR(L"No valid Visual actor in template %hs", templateName.c_str()); 200 return; 201 } 202 u32 parentSeed = cmpParentVisualActor->GetActorSeed(); 203 cmpMirageVisualActor->SetActorSeed(parentSeed); 204 } 205 206 virtual bool IsMiraged(player_id_t player) 207 { 208 if (player > m_Miraged.size()) 209 { 210 LOGERROR(L"Tried to query miraging info for invalid player"); 211 return false; 212 } 213 214 return m_Miraged[player]; 215 } 216 217 virtual void SetMiraged(player_id_t player, bool enable) 218 { 219 if (player > m_Miraged.size()) 220 { 221 LOGERROR(L"Tried to enable/disable a mirage for invalid player"); 222 return; 223 } 224 225 m_Miraged[player] = enable; 226 } 227 228 private: 229 /// Vector of mirages, one for each player 230 std::vector<entity_id_t> m_Mirages; 231 232 /// For each player, remember if the entity must be mirage'd 233 /// (i.e. has already been seen) or not. 234 std::vector<bool> m_Miraged; 235 }; 236 237 REGISTER_COMPONENT_TYPE(Fogging) -
source/simulation2/components/CCmpMirage.cpp
Property changes on: source/simulation2/components/CCmpFogging.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "simulation2/system/Component.h" 21 #include "simulation2/MessageTypes.h" 22 #include "ICmpMirage.h" 23 #include "ICmpRangeManager.h" 24 25 class CCmpMirage : public ICmpMirage 26 { 27 public: 28 static void ClassInit(CComponentManager& componentManager) 29 { 30 componentManager.SubscribeToMessageType(MT_VisibilityChanged); 31 componentManager.SubscribeToMessageType(MT_Destroy); 32 } 33 34 DEFAULT_COMPONENT_ALLOCATOR(Mirage) 35 36 static std::string GetSchema() 37 { 38 return "<a:help>Mirage entities replace real entities in the fog-of-war.</a:help>" 39 "<empty/>"; 40 } 41 42 virtual void Init(const CParamNode& UNUSED(paramNode)) 43 { 44 } 45 46 virtual void Deinit() 47 { 48 } 49 50 template<typename S> 51 void SerializeCommon(S& serialize) 52 { 53 serialize.NumberI32_Unbounded("player", m_Player); 54 serialize.NumberU32_Unbounded("parent", m_Parent); 55 } 56 57 virtual void Serialize(ISerializer& serialize) 58 { 59 SerializeCommon(serialize); 60 } 61 62 virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize) 63 { 64 SerializeCommon(deserialize); 65 } 66 67 virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) 68 { 69 switch (msg.GetType()) 70 { 71 case MT_VisibilityChanged: 72 { 73 const CMessageVisibilityChanged& msgData = static_cast<const CMessageVisibilityChanged&> (msg); 74 if (msgData.player == m_Player 75 && msgData.newVisibility == ICmpRangeManager::VIS_VISIBLE 76 && m_Parent == INVALID_ENTITY) 77 GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId()); 78 break; 79 } 80 case MT_Destroy: 81 { 82 if (GetParent() == INVALID_ENTITY) 83 break; 84 85 CMessageEntityRenamed msg(GetEntityId(), GetParent()); 86 GetSimContext().GetComponentManager().BroadcastMessage(msg); 87 break; 88 } 89 } 90 } 91 92 virtual void SetPlayer(player_id_t player) 93 { 94 m_Player = player; 95 } 96 97 virtual player_id_t GetPlayer() 98 { 99 return m_Player; 100 } 101 102 virtual void SetParent(entity_id_t ent) 103 { 104 m_Parent = ent; 105 } 106 107 virtual entity_id_t GetParent() 108 { 109 return m_Parent; 110 } 111 112 private: 113 player_id_t m_Player; 114 entity_id_t m_Parent; 115 }; 116 117 REGISTER_COMPONENT_TYPE(Mirage) -
source/simulation2/components/CCmpRangeManager.cpp
Property changes on: source/simulation2/components/CCmpMirage.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 23 23 #include "ICmpTerrain.h" 24 24 #include "simulation2/system/EntityMap.h" 25 25 #include "simulation2/MessageTypes.h" 26 #include "simulation2/components/ICmpFogging.h" 27 #include "simulation2/components/ICmpMirage.h" 28 #include "simulation2/components/ICmpOwnership.h" 26 29 #include "simulation2/components/ICmpPosition.h" 27 30 #include "simulation2/components/ICmpTerritoryManager.h" 28 31 #include "simulation2/components/ICmpVision.h" … … 39 42 #include "renderer/Scene.h" 40 43 #include "lib/ps_stl.h" 41 44 42 45 #define LOS_TILES_RATIO 8 43 46 #define DEBUG_RANGE_MANAGER_BOUNDS 0 44 47 45 48 /** … … 138 141 EntityData() : retainInFog(0), owner(-1), inWorld(0), flags(1) { } 139 142 entity_pos_t x, z; 140 143 entity_pos_t visionRange; 144 u32 visibilities; // 2-bit visibility, per player 141 145 u8 retainInFog; // boolean 142 146 i8 owner; 143 147 u8 inWorld; // boolean … … 144 148 u8 flags; // See GetEntityFlagMask 145 149 }; 146 150 147 cassert(sizeof(EntityData) == 16);151 cassert(sizeof(EntityData) == 20); 148 152 149 153 /** 150 154 * Serialization helper template for Query … … 197 201 serialize.NumberFixed_Unbounded("z", value.z); 198 202 serialize.NumberFixed_Unbounded("vision", value.visionRange); 199 203 serialize.NumberU8("retain in fog", value.retainInFog, 0, 1); 204 serialize.NumberU32_Unbounded("visibilities", value.visibilities); 200 205 serialize.NumberI8_Unbounded("owner", value.owner); 201 206 serialize.NumberU8("in world", value.inWorld, 0, 1); 202 207 serialize.NumberU8_Unbounded("flags", value.flags); … … 283 288 bool m_LosCircular; 284 289 i32 m_TerrainVerticesPerSide; 285 290 size_t m_TerritoriesDirtyID; 291 292 // Cache for visibility tracking (not serialized) 293 i32 m_LosTilesPerSide; 294 bool* m_DirtyVisibility; 295 std::vector<std::set<entity_id_t>> m_LosTiles; 296 // List of entities that must be updated, regardless of the status of their tile 297 std::vector<entity_id_t> m_ModifiedEntities; 286 298 287 299 // Counts of units seeing vertex, per vertex, per player (starting with player 0). 288 300 // Use u16 to avoid overflows when we have very large (but not infeasibly large) numbers … … 332 344 m_LosCircular = false; 333 345 m_TerrainVerticesPerSide = 0; 334 346 347 m_DirtyVisibility = NULL; 348 335 349 m_TerritoriesDirtyID = 0; 336 350 } 337 351 338 352 virtual void Deinit() 339 353 { 354 delete[] m_DirtyVisibility; 340 355 } 341 356 342 357 template<typename S> … … 355 370 serialize.Bool("los circular", m_LosCircular); 356 371 serialize.NumberI32_Unbounded("terrain verts per side", m_TerrainVerticesPerSide); 357 372 358 // We don't serialize m_Subdivision or m_LosPlayerCounts 373 SerializeVector<SerializeU32_Unbounded>()(serialize, "modified entities", m_ModifiedEntities); 374 375 // We don't serialize m_Subdivision, m_LosPlayerCounts or m_LosTiles 359 376 // since they can be recomputed from the entity data when deserializing; 360 377 // m_LosState must be serialized since it depends on the history of exploration 361 378 … … 432 449 CFixedVector2D to(msgData.x, msgData.z); 433 450 m_Subdivision.Move(ent, from, to); 434 451 LosMove(it->second.owner, it->second.visionRange, from, to); 452 i32 oldLosTile = PosToLosTilesHelper(it->second.x, it->second.z); 453 i32 newLosTile = PosToLosTilesHelper(msgData.x, msgData.z); 454 if (oldLosTile != newLosTile) 455 { 456 RemoveFromTile(oldLosTile, ent); 457 AddToTile(newLosTile, ent); 458 } 435 459 } 436 460 else 437 461 { … … 438 462 CFixedVector2D to(msgData.x, msgData.z); 439 463 m_Subdivision.Add(ent, to); 440 464 LosAdd(it->second.owner, it->second.visionRange, to); 465 AddToTile(PosToLosTilesHelper(msgData.x, msgData.z), ent); 441 466 } 442 467 443 468 it->second.inWorld = 1; … … 451 476 CFixedVector2D from(it->second.x, it->second.z); 452 477 m_Subdivision.Remove(ent, from); 453 478 LosRemove(it->second.owner, it->second.visionRange, from); 479 RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent); 454 480 } 455 481 456 482 it->second.inWorld = 0; … … 458 484 it->second.z = entity_pos_t::Zero(); 459 485 } 460 486 487 m_ModifiedEntities.push_back(ent); 488 461 489 break; 462 490 } 463 491 case MT_OwnershipChanged: … … 495 523 break; 496 524 497 525 if (it->second.inWorld) 526 { 498 527 m_Subdivision.Remove(ent, CFixedVector2D(it->second.x, it->second.z)); 528 RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent); 529 } 499 530 500 531 // This will be called after Ownership's OnDestroy, so ownership will be set 501 532 // to -1 already and we don't have to do a LosRemove here … … 539 570 case MT_Update: 540 571 { 541 572 m_DebugOverlayDirty = true; 573 UpdateVisibilityData(); 542 574 UpdateTerritoriesLos(); 543 575 ExecuteActiveQueries(); 544 576 break; … … 559 591 m_WorldX1 = x1; 560 592 m_WorldZ1 = z1; 561 593 m_TerrainVerticesPerSide = (i32)vertices; 594 595 m_LosTilesPerSide = (m_TerrainVerticesPerSide - 1)/LOS_TILES_RATIO; 562 596 563 597 ResetDerivedData(false); 564 598 } … … 639 673 } 640 674 m_LosStateRevealed.clear(); 641 675 m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide); 676 677 delete[] m_DirtyVisibility; 678 m_DirtyVisibility = new bool[m_LosTilesPerSide*m_LosTilesPerSide](); 679 m_LosTiles.clear(); 680 m_LosTiles.resize(m_LosTilesPerSide*m_LosTilesPerSide); 642 681 643 682 for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it) 644 683 { 645 684 if (it->second.inWorld) 685 { 646 686 LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z)); 687 AddToTile(PosToLosTilesHelper(it->second.x, it->second.z), it->first); 688 } 647 689 } 648 690 649 691 m_TotalInworldVertices = 0; … … 1364 1406 CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide); 1365 1407 1366 1408 if (los.IsVisible(i, j)) 1409 { 1410 // If we see an entity, we should mirage it as soon as it falls into fog-of-war 1411 CmpPtr<ICmpFogging> cmpFogging(ent); 1412 if (cmpFogging) 1413 cmpFogging->SetMiraged(player, true); 1414 1367 1415 return VIS_VISIBLE; 1416 } 1368 1417 1369 1418 // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region 1370 1419 if (los.IsExplored(i, j)) … … 1371 1420 { 1372 1421 CmpPtr<ICmpVision> cmpVision(ent); 1373 1422 if (forceRetainInFog || (cmpVision && cmpVision->GetRetainInFog())) 1374 return VIS_FOGGED; 1423 { 1424 // Mirage entities are visible for one specific player 1425 CmpPtr<ICmpMirage> cmpMirage(ent); 1426 if (cmpMirage) 1427 { 1428 if (cmpMirage->GetPlayer() == player) 1429 return VIS_FOGGED; 1430 else 1431 return VIS_HIDDEN; 1432 } 1433 1434 // Normal entities should be visible only for their owner 1435 CmpPtr<ICmpOwnership> cmpOwnership(ent); 1436 if (cmpOwnership) 1437 { 1438 if (cmpOwnership->GetOwner() == player) 1439 return VIS_FOGGED; 1440 else 1441 return VIS_HIDDEN; 1442 } 1443 1444 return VIS_VISIBLE; 1445 } 1375 1446 } 1376 1447 1377 1448 // Otherwise not visible … … 1384 1455 return GetLosVisibility(handle, player, forceRetainInFog); 1385 1456 } 1386 1457 1458 i32 PosToLosTilesHelper(entity_pos_t x, entity_pos_t z) 1459 { 1460 i32 i = Clamp( 1461 (x/(entity_pos_t::FromInt(TERRAIN_TILE_SIZE * LOS_TILES_RATIO))).ToInt_RoundToZero(), 1462 0, 1463 m_LosTilesPerSide - 1); 1464 i32 j = Clamp( 1465 (z/(entity_pos_t::FromInt(TERRAIN_TILE_SIZE * LOS_TILES_RATIO))).ToInt_RoundToZero(), 1466 0, 1467 m_LosTilesPerSide - 1); 1468 return j*m_LosTilesPerSide + i; 1469 } 1387 1470 1471 void AddToTile(i32 tile, entity_id_t ent) 1472 { 1473 m_LosTiles[tile].insert(ent); 1474 } 1475 1476 void RemoveFromTile(i32 tile, entity_id_t ent) 1477 { 1478 for (std::set<entity_id_t>::iterator tileIt = m_LosTiles[tile].begin(); 1479 tileIt != m_LosTiles[tile].end(); 1480 ++tileIt) 1481 { 1482 if (*tileIt == ent) 1483 { 1484 m_LosTiles[tile].erase(tileIt); 1485 return; 1486 } 1487 } 1488 } 1489 1490 void UpdateVisibilityData() 1491 { 1492 PROFILE("UpdateVisibilityData"); 1493 1494 for (i32 n = 0; n < m_LosTilesPerSide*m_LosTilesPerSide; ++n) 1495 { 1496 if (m_DirtyVisibility[n]) 1497 { 1498 for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin(); 1499 it != m_LosTiles[n].end(); 1500 ++it) 1501 { 1502 UpdateVisibility(*it); 1503 } 1504 m_DirtyVisibility[n] = false; 1505 } 1506 } 1507 1508 for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it) 1509 { 1510 UpdateVisibility(*it); 1511 } 1512 m_ModifiedEntities.clear(); 1513 } 1514 1515 void UpdateVisibility(entity_id_t ent) 1516 { 1517 EntityMap<EntityData>::iterator itEnts = m_EntityData.find(ent); 1518 if (itEnts == m_EntityData.end()) 1519 return; 1520 1521 for (player_id_t player = 1; player <= MAX_LOS_PLAYER_ID; ++player) 1522 { 1523 u8 oldVis = (itEnts->second.visibilities >> (2*player)) & 0x3; 1524 u8 newVis = GetLosVisibility(itEnts->first, player, false); 1525 1526 if (oldVis != newVis) 1527 { 1528 CMessageVisibilityChanged msg(player, ent, oldVis, newVis); 1529 GetSimContext().GetComponentManager().PostMessage(ent, msg); 1530 itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*player)) | (newVis << 2*player); 1531 } 1532 } 1533 } 1534 1388 1535 virtual void SetLosRevealAll(player_id_t player, bool enabled) 1389 1536 { 1390 1537 if (player == -1) … … 1532 1679 explored += !(m_LosState[idx] & (LOS_EXPLORED << (2*(owner-1)))); 1533 1680 m_LosState[idx] |= ((LOS_VISIBLE | LOS_EXPLORED) << (2*(owner-1))); 1534 1681 } 1682 m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true; 1535 1683 } 1536 1684 1537 1685 ASSERT(counts[idx] < 65535); … … 1559 1707 { 1560 1708 // (If LosIsOffWorld then this is a no-op, so don't bother doing the check) 1561 1709 m_LosState[idx] &= ~(LOS_VISIBLE << (2*(owner-1))); 1710 1711 i32 i = i0 + idx - idx0; 1712 m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true; 1562 1713 } 1563 1714 } 1564 1715 } -
source/simulation2/components/CCmpUnitRenderer.cpp
391 391 CmpPtr<ICmpVision> cmpVision(unit.entity); 392 392 if (cmpVision && cmpVision->GetAlwaysVisible()) 393 393 unit.visibility = ICmpRangeManager::VIS_VISIBLE; 394 395 // Uncomment the following two lines to prevent the models from popping into existence 396 // near the LOS boundary. Is rather resource intensive. 397 //else if (cmpVision && cmpVision->GetRetainInFog()) 398 // unit.visibility = ICmpRangeManager::VIS_VISIBLE; 399 394 400 else 395 401 { 396 402 CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity()); 397 // Uncomment the following lines to prevent the models from popping into existence 398 // near the LOS boundary. Is rather resource intensive. 399 //if (cmpVision->GetRetainInFog()) 400 // unit.visibility = ICmpRangeManager::VIS_VISIBLE; 401 //else 402 unit.visibility = cmpRangeManager->GetLosVisibility(unit.entity, 403 GetSimContext().GetCurrentDisplayedPlayer()); 403 unit.visibility = cmpRangeManager->GetLosVisibility(unit.entity, 404 GetSimContext().GetCurrentDisplayedPlayer()); 404 405 } 405 406 } 406 407 else -
source/simulation2/components/CCmpVisualActor.cpp
532 532 void ReloadActor(); 533 533 534 534 void Update(fixed turnLength); 535 void UpdateVisibility();536 535 }; 537 536 538 537 REGISTER_COMPONENT_TYPE(VisualActor) -
source/simulation2/components/ICmpFogging.cpp
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "ICmpFogging.h" 21 22 #include "simulation2/system/InterfaceScripted.h" 23 24 BEGIN_INTERFACE_WRAPPER(Fogging) 25 DEFINE_INTERFACE_METHOD_1("UpdateMirage", void, ICmpFogging, UpdateMirage, player_id_t) 26 DEFINE_INTERFACE_METHOD_1("IsMiraged", bool, ICmpFogging, IsMiraged, player_id_t) 27 DEFINE_INTERFACE_METHOD_2("SetMiraged", void, ICmpFogging, SetMiraged, player_id_t, bool) 28 END_INTERFACE_WRAPPER(Fogging) -
source/simulation2/components/ICmpFogging.h
Property changes on: source/simulation2/components/ICmpFogging.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_ICMPFOGGING 19 #define INCLUDED_ICMPFOGGING 20 21 #include "simulation2/system/Interface.h" 22 23 #include "simulation2/helpers/Player.h" 24 25 26 /** 27 * Handles the fogging of out-of-sight enemy entities, by creating mirage 28 * entities. 29 * This allows hiding changes, especially destruction status or health. 30 */ 31 class ICmpFogging : public IComponent 32 { 33 public: 34 virtual void UpdateMirage(player_id_t player) = 0; 35 virtual bool IsMiraged(player_id_t player) = 0; 36 virtual void SetMiraged(player_id_t player, bool enable) = 0; 37 DECLARE_INTERFACE_TYPE(Fogging) 38 }; 39 40 #endif // INCLUDED_ICMPFOGGING -
source/simulation2/components/ICmpMirage.cpp
Property changes on: source/simulation2/components/ICmpFogging.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "ICmpMirage.h" 21 22 #include "simulation2/system/InterfaceScripted.h" 23 24 BEGIN_INTERFACE_WRAPPER(Mirage) 25 DEFINE_INTERFACE_METHOD_1("SetPlayer", void, ICmpMirage, SetPlayer, player_id_t) 26 DEFINE_INTERFACE_METHOD_0("GetPlayer", player_id_t, ICmpMirage, GetPlayer) 27 DEFINE_INTERFACE_METHOD_1("SetParent", void, ICmpMirage, SetParent, entity_id_t) 28 DEFINE_INTERFACE_METHOD_0("GetParent", entity_id_t, ICmpMirage, GetParent) 29 END_INTERFACE_WRAPPER(Mirage) -
source/simulation2/components/ICmpMirage.h
Property changes on: source/simulation2/components/ICmpMirage.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 2014 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_ICMPMIRAGE 19 #define INCLUDED_ICMPMIRAGE 20 21 #include "simulation2/system/Interface.h" 22 23 #include "simulation2/helpers/Player.h" 24 25 /** 26 * Component allowing mirage entities to communicate with their parent entity. 27 * See ICmpFogging. 28 */ 29 class ICmpMirage : public IComponent 30 { 31 public: 32 virtual void SetPlayer(player_id_t player) = 0; 33 virtual player_id_t GetPlayer() = 0; 34 virtual void SetParent(entity_id_t ent) = 0; 35 virtual entity_id_t GetParent() = 0; 36 DECLARE_INTERFACE_TYPE(Mirage) 37 }; 38 39 #endif // INCLUDED_ICMPMIRAGE -
source/simulation2/components/ICmpRangeManager.cpp
Property changes on: source/simulation2/components/ICmpMirage.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify -
source/simulation2/components/ICmpRangeManager.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 216 216 217 217 enum ELosVisibility 218 218 { 219 VIS_HIDDEN ,220 VIS_FOGGED ,221 VIS_VISIBLE 219 VIS_HIDDEN = 0, 220 VIS_FOGGED = 1, 221 VIS_VISIBLE = 2 222 222 }; 223 223 224 224 /** -
source/simulation2/MessageTypes.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 241 241 entity_id_t entity; 242 242 }; 243 243 244 /** 245 * This is sent when one entity is changed to other: from Foundation component when building 246 * constuction is done, from Promotion component, from Fogging component etc. 247 */ 248 class CMessageEntityRenamed : public CMessage 249 { 250 public: 251 DEFAULT_MESSAGE_IMPL(EntityRenamed) 252 253 CMessageEntityRenamed(entity_id_t entity, entity_id_t newentity) : 254 entity(entity), newentity(newentity) 255 { 256 } 257 258 entity_id_t entity; 259 entity_id_t newentity; 260 }; 261 244 262 class CMessageOwnershipChanged : public CMessage 245 263 { 246 264 public: … … 362 380 }; 363 381 364 382 /** 383 * Sent, at most once per turn, when the visibility of an entity changed 384 */ 385 class CMessageVisibilityChanged : public CMessage 386 { 387 public: 388 DEFAULT_MESSAGE_IMPL(VisibilityChanged) 389 390 CMessageVisibilityChanged(player_id_t player, entity_id_t ent, int oldVisibility, int newVisibility) : 391 player(player), ent(ent), oldVisibility(oldVisibility), newVisibility(newVisibility) 392 { 393 } 394 395 player_id_t player; 396 entity_id_t ent; 397 int oldVisibility; 398 int newVisibility; 399 }; 400 401 /** 365 402 * Sent when ObstructionManager's view of the shape of the world has changed 366 403 * (changing the TILE_OUTOFBOUNDS tiles returned by Rasterise). 367 404 */ -
source/simulation2/scripting/MessageTypeConversions.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 194 194 195 195 //////////////////////////////// 196 196 197 jsval CMessageEntityRenamed::ToJSVal(ScriptInterface& scriptInterface) const 198 { 199 TOJSVAL_SETUP(); 200 SET_MSG_PROPERTY(entity); 201 SET_MSG_PROPERTY(newentity); 202 return OBJECT_TO_JSVAL(obj); 203 } 204 205 CMessage* CMessageEntityRenamed::FromJSVal(ScriptInterface& scriptInterface, jsval val) 206 { 207 FROMJSVAL_SETUP(); 208 GET_MSG_PROPERTY(entity_id_t, entity); 209 GET_MSG_PROPERTY(entity_id_t, newentity); 210 return new CMessageEntityRenamed(entity, newentity); 211 } 212 213 //////////////////////////////// 214 197 215 jsval CMessageOwnershipChanged::ToJSVal(ScriptInterface& scriptInterface) const 198 216 { 199 217 TOJSVAL_SETUP(); … … 310 328 311 329 //////////////////////////////// 312 330 331 jsval CMessageVisibilityChanged::ToJSVal(ScriptInterface& scriptInterface) const 332 { 333 TOJSVAL_SETUP(); 334 SET_MSG_PROPERTY(player); 335 SET_MSG_PROPERTY(ent); 336 SET_MSG_PROPERTY(oldVisibility); 337 SET_MSG_PROPERTY(newVisibility); 338 return OBJECT_TO_JSVAL(obj); 339 } 340 341 CMessage* CMessageVisibilityChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val) 342 { 343 FROMJSVAL_SETUP(); 344 GET_MSG_PROPERTY(player_id_t, player); 345 GET_MSG_PROPERTY(entity_id_t, ent); 346 GET_MSG_PROPERTY(int, oldVisibility); 347 GET_MSG_PROPERTY(int, newVisibility); 348 return new CMessageVisibilityChanged(player, ent, oldVisibility, newVisibility); 349 } 350 351 //////////////////////////////// 352 313 353 jsval CMessageWaterChanged::ToJSVal(ScriptInterface& scriptInterface) const 314 354 { 315 355 TOJSVAL_SETUP(); -
source/simulation2/TypeList.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 41 41 MESSAGE(Deserialized) // non-deterministic (use with caution) 42 42 MESSAGE(Create) 43 43 MESSAGE(Destroy) 44 MESSAGE(EntityRenamed) 44 45 MESSAGE(OwnershipChanged) 45 46 MESSAGE(PositionChanged) 46 47 MESSAGE(InterpolatedPositionChanged) … … 48 49 MESSAGE(MotionChanged) 49 50 MESSAGE(RangeUpdate) 50 51 MESSAGE(TerrainChanged) 52 MESSAGE(VisibilityChanged) 51 53 MESSAGE(WaterChanged) 52 54 MESSAGE(ObstructionMapShapeChanged) 53 55 MESSAGE(TerritoriesChanged) … … 80 82 INTERFACE(Decay) 81 83 COMPONENT(Decay) 82 84 85 INTERFACE(Fogging) 86 COMPONENT(Fogging) 87 83 88 // Note: The VisualActor component relies on this component being initialized before itself, in order to support using 84 89 // an entity's footprint shape for the selection boxes. This dependency is not strictly necessary, but it does avoid 85 90 // some extra plumbing code to set up on-demand initialization. If you find yourself forced to break this dependency, … … 96 101 INTERFACE(Minimap) 97 102 COMPONENT(Minimap) 98 103 104 INTERFACE(Mirage) 105 COMPONENT(Mirage) 106 99 107 INTERFACE(Motion) 100 108 COMPONENT(MotionBall) 101 109 COMPONENT(MotionScripted)