Ticket #599: proxywip.patch
File proxywip.patch, 29.5 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/simulation/components/Foundation.js
diff --git a/binaries/data/mods/public/simulation/components/Foundation.js b/binaries/data/mods/public/simulation/components/Foundation.js index 14029da..a5df7a8 100644
a b Foundation.prototype.IsFinished = function() 56 56 return (this.buildProgress >= 1.0); 57 57 }; 58 58 59 Foundation.prototype.OnVisibilityChanged = function(msg) 60 { 61 if (msg.source != this.entity) 62 return; 63 var building = msg.source; 64 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 65 var cmpBuildingPosition = Engine.QueryInterface(building, IID_Position); 66 var pos = cmpPosition.GetPosition(); 67 cmpBuildingPosition.JumpTo(pos.x, pos.z); 68 var rot = cmpPosition.GetRotation(); 69 cmpBuildingPosition.SetYRotation(rot.y); 70 cmpBuildingPosition.SetXZRotation(rot.x, rot.z); 71 // TODO: should add a ICmpPosition::CopyFrom() instead of all this 72 73 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 74 var cmpBuildingOwnership = Engine.QueryInterface(building, IID_Ownership); 75 cmpBuildingOwnership.SetOwner(cmpOwnership.GetOwner()); 76 77 var cmpHealth = Engine.QueryInterface(this.entity, IID_Health); 78 var cmpBuildingHealth = Engine.QueryInterface(building, IID_Health); 79 cmpBuildingHealth.SetHitpoints(cmpHealth.GetHitpoints()); 80 } 81 59 82 Foundation.prototype.OnDestroy = function() 60 83 { 61 84 // Refund a portion of the construction cost, proportional to the amount of build progress remaining -
binaries/data/mods/public/simulation/components/GuiInterface.js
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index 16ee222..1c9513e 100644
a b GuiInterface.prototype.Init = function() 21 21 this.rallyPoints = undefined; 22 22 this.notifications = []; 23 23 this.renamedEntities = []; 24 this.proxiedEntities = {}; 24 25 }; 25 26 26 27 /* … … GuiInterface.prototype.GetExtendedSimulationState = function(player) 111 112 112 113 GuiInterface.prototype.GetRenamedEntities = function(player) 113 114 { 114 return this.renamedEntities; 115 var proxied = this.proxiedEntities[player]; 116 if (!proxied) proxied = []; 117 return this.renamedEntities.concat(proxied); 115 118 }; 116 119 117 120 GuiInterface.prototype.ClearRenamedEntities = function(player) 118 121 { 119 122 this.renamedEntities = []; 123 this.proxiedEntities[player] = []; 120 124 }; 121 125 122 126 GuiInterface.prototype.GetEntityState = function(player, ent) … … GuiInterface.prototype.OnGlobalEntityRenamed = function(msg) 713 717 this.renamedEntities.push(msg); 714 718 } 715 719 720 GuiInterface.prototype.OnGlobalDestroy = function(msg) 721 { 722 var cmpVisual = Engine.QueryInterface(msg.entity, IID_Visual); 723 if (!cmpVisual) 724 return; 725 var proxy = cmpVisual.GetProxyOwner(); 726 if (proxy == INVALID_ENTITY) 727 return; 728 // FIXME: we could end up flooding the list if there are lots of proxies coming into view 729 // at the same time, since we don't have a way of checking the target player 730 this.renamedEntities.push({"type": "EntityRenamed", "entity": msg.entity, "newentity": proxy}); 731 } 732 733 GuiInterface.prototype.OnGlobalVisibilityChanged = function(msg) 734 { 735 if (msg.source != INVALID_ENTITY) 736 this.proxiedEntities[msg.player].push({"type": "EntityRenamed", "entity": msg.source, "newentity": msg.proxy}); 737 } 738 739 GuiInterface.prototype.GetProxiedEntities = function(player) 740 { 741 return this.proxiedEntities[player]; 742 } 743 744 GuiInterface.prototype.ClearProxiedEntities = function(player) 745 { 746 this.proxiedEntities[player] = []; 747 } 748 716 749 // List the GuiInterface functions that can be safely called by GUI scripts. 717 750 // (GUI scripts are non-deterministic and untrusted, so these functions must be 718 751 // appropriately careful. They are called with a first argument "player", which is … … var exposedFunctions = { 742 775 "SetPathfinderDebugOverlay": 1, 743 776 "SetObstructionDebugOverlay": 1, 744 777 "SetMotionDebugOverlay": 1, 745 "SetRangeDebugOverlay": 1 ,778 "SetRangeDebugOverlay": 1 746 779 }; 747 780 748 781 GuiInterface.prototype.ScriptCall = function(player, name, args) -
binaries/data/mods/public/simulation/components/ResourceSupply.js
diff --git a/binaries/data/mods/public/simulation/components/ResourceSupply.js b/binaries/data/mods/public/simulation/components/ResourceSupply.js index 6dede9f..6a6830c 100644
a b ResourceSupply.prototype.GetType = function() 82 82 return { "generic": type, "specific": subtype }; 83 83 }; 84 84 85 ResourceSupply.prototype.OnVisibilityChanged = function(msg) 86 { 87 if (msg.source != this.entity) 88 return; 89 var entity = msg.proxy; 90 var supply = Engine.QueryInterface(entity, IID_ResourceSupply); 91 supply.amount = this.amount; 92 var proxyPosition = Engine.QueryInterface(entity, IID_Position); 93 var position = Engine.QueryInterface(this.entity, IID_Position); 94 var pos = position.GetPosition(); 95 proxyPosition.JumpTo(pos.x, pos.z); 96 var rot = position.GetRotation(); 97 proxyPosition.SetYRotation(rot.y); 98 proxyPosition.SetXZRotation(rot.x, rot.z); 99 // TODO: should add a ICmpPosition::CopyFrom() instead of all this 100 101 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 102 var cmpProxyOwnership = Engine.QueryInterface(entity, IID_Ownership); 103 cmpProxyOwnership.SetOwner(cmpOwnership.GetOwner()); 104 } 105 85 106 Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply); -
binaries/data/mods/public/simulation/components/UnitAI.js
diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 515707a..979ff58 100644
a b var UnitFsmSpec = { 790 790 }, 791 791 792 792 "GATHER": { 793 "EntityRenamed": function(msg) { 794 if (this.order.data.target == msg.entity) 795 this.order.data.target = msg.newentity; 796 }, 797 793 798 "APPROACHING": { 794 799 "enter": function() { 795 800 this.SelectAnimation("move"); … … UnitAI.prototype.OnDestroy = function() 1454 1459 rangeMan.DestroyActiveQuery(this.losRangeQuery); 1455 1460 }; 1456 1461 1462 UnitAI.prototype.OnGlobalDestroy = function(msg) 1463 { 1464 var cmpVisual = Engine.QueryInterface(msg.entity, IID_Visual); 1465 if (!cmpVisual) 1466 return; 1467 var proxy = cmpVisual.GetProxyOwner(); 1468 if (proxy == INVALID_ENTITY) 1469 return; 1470 this.OnGlobalEntityRenamed({entity: msg.entity, newentity: proxy}); 1471 } 1472 1457 1473 // Set up a range query for all enemy units within LOS range 1458 1474 // which can be attacked. 1459 1475 // This should be called whenever our ownership changes. … … UnitAI.prototype.OnGlobalEntityRenamed = function(msg) 1699 1715 UnitFsm.ProcessMessage(this, {"type": "EntityRenamed", "entity": msg.entity, "newentity": msg.newentity}); 1700 1716 } 1701 1717 1718 UnitAI.prototype.OnGlobalVisibilityChanged = function(msg) 1719 { 1720 if (msg.source == INVALID_ENTITY) 1721 return; 1722 var cmpVisual = Engine.QueryInterface(msg.proxy, IID_Visual); 1723 var cmpOwner = Engine.QueryInterface(this.entity, IID_Ownership); 1724 if (cmpVisual.GetProxyPlayerTarget() == cmpOwner.GetOwner()) 1725 this.OnGlobalEntityRenamed({entity: msg.source, newentity: msg.proxy}); 1726 } 1727 1702 1728 UnitAI.prototype.OnAttacked = function(msg) 1703 1729 { 1704 1730 UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg}); -
source/network/NetTurnManager.cpp
diff --git a/source/network/NetTurnManager.cpp b/source/network/NetTurnManager.cpp index e80ae74..128b374 100644
a b 32 32 #include "ps/SavedGame.h" 33 33 #include "scriptinterface/ScriptInterface.h" 34 34 #include "simulation2/Simulation2.h" 35 #include "simulation2/system/SimContext.h" 35 36 36 37 #include <sstream> 37 38 #include <fstream> … … void CNetTurnManager::OnSyncError(u32 turn, const std::string& expectedHash) 232 233 bool ok = m_Simulation2.ComputeStateHash(hash, quick); 233 234 ENSURE(ok); 234 235 235 OsPath path = psLogDir()/"oos_dump.txt"; 236 std::stringstream fname; 237 fname << "oos_dump_" << m_Simulation2.GetSimContext().GetCurrentDisplayedPlayer() << ".txt"; 238 OsPath path = psLogDir()/fname.str(); 236 239 std::ofstream file (OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc); 237 240 m_Simulation2.DumpDebugState(file); 238 241 file.close(); -
source/simulation2/MessageTypes.h
diff --git a/source/simulation2/MessageTypes.h b/source/simulation2/MessageTypes.h index 7d4eefe..47233a3 100644
a b 23 23 #include "simulation2/system/Message.h" 24 24 25 25 #include "simulation2/helpers/Position.h" 26 #include "simulation2/helpers/Player.h" 26 27 27 28 #include "simulation2/components/ICmpPathfinder.h" 28 29 … … public: 99 100 fixed turnLength; 100 101 }; 101 102 103 class CMessageUpdate_Visibility : public CMessage 104 { 105 public: 106 DEFAULT_MESSAGE_IMPL(Update_Visibility) 107 108 CMessageUpdate_Visibility() 109 { 110 } 111 }; 112 102 113 /** 103 114 * Final update phase, after all other updates. 104 115 */ … … public: 357 368 ICmpPathfinder::Path path; 358 369 }; 359 370 371 class CMessageVisibilityChanged : public CMessage 372 { 373 public: 374 DEFAULT_MESSAGE_IMPL(VisibilityChanged) 375 376 CMessageVisibilityChanged(entity_id_t source, entity_id_t proxy, player_id_t player) : 377 source(source), proxy(proxy), player(player) 378 { 379 } 380 381 CMessageVisibilityChanged() : 382 source(INVALID_ENTITY), proxy(INVALID_ENTITY), player(INVALID_PLAYER) 383 { 384 } 385 386 entity_id_t source, proxy; 387 player_id_t player; 388 }; 389 360 390 #endif // INCLUDED_MESSAGETYPES -
source/simulation2/Simulation2.cpp
diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index 5586805..b1562bc 100644
a b void CSimulation2Impl::UpdateComponents(CSimContext& simContext, fixed turnLengt 499 499 CMessageUpdate_MotionUnit msgUpdate(turnLengthFixed); 500 500 componentManager.BroadcastMessage(msgUpdate); 501 501 } 502 { 503 CMessageUpdate_Visibility msgUpdate; 504 componentManager.BroadcastMessage(msgUpdate); 505 } 502 506 { 503 507 CMessageUpdate_Final msgUpdate(turnLengthFixed); 504 508 componentManager.BroadcastMessage(msgUpdate); -
source/simulation2/TypeList.h
diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index 696d2e0..fee3182 100644
a b MESSAGE(TurnStart) 34 34 MESSAGE(Update) 35 35 MESSAGE(Update_MotionFormation) 36 36 MESSAGE(Update_MotionUnit) 37 MESSAGE(Update_Visibility) 37 38 MESSAGE(Update_Final) 38 39 MESSAGE(Interpolate) // non-deterministic (use with caution) 39 40 MESSAGE(RenderSubmit) // non-deterministic (use with caution) … … MESSAGE(RangeUpdate) 47 48 MESSAGE(TerrainChanged) 48 49 MESSAGE(TerritoriesChanged) 49 50 MESSAGE(PathResult) 51 MESSAGE(VisibilityChanged) 50 52 51 53 // TemplateManager must come before all other (non-test) components, 52 54 // so that it is the first to be (de)serialized -
source/simulation2/components/CCmpRangeManager.cpp
diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index e9c275b..c003768 100644
a b 18 18 #include "precompiled.h" 19 19 20 20 #include "simulation2/system/Component.h" 21 #include "simulation2/Simulation2.h" 21 22 #include "ICmpRangeManager.h" 22 23 23 24 #include "simulation2/MessageTypes.h" 24 25 #include "simulation2/components/ICmpPosition.h" 25 26 #include "simulation2/components/ICmpTerritoryManager.h" 26 27 #include "simulation2/components/ICmpVision.h" 28 #include "simulation2/components/ICmpVisual.h" 27 29 #include "simulation2/helpers/Render.h" 28 30 #include "simulation2/helpers/Spatial.h" 29 31 … … 34 36 #include "ps/CLogger.h" 35 37 #include "ps/Overlay.h" 36 38 #include "ps/Profile.h" 39 #include "ps/Game.h" 37 40 #include "renderer/Scene.h" 38 41 39 42 #define DEBUG_RANGE_MANAGER_BOUNDS 0 … … public: 164 167 componentManager.SubscribeGloballyToMessageType(MT_Destroy); 165 168 166 169 componentManager.SubscribeToMessageType(MT_Update); 170 componentManager.SubscribeToMessageType(MT_Update_Visibility); 167 171 168 172 componentManager.SubscribeToMessageType(MT_RenderSubmit); // for debug overlays 169 173 } … … public: 186 190 std::map<entity_id_t, EntityData> m_EntityData; 187 191 SpatialSubdivision<entity_id_t> m_Subdivision; // spatial index of m_EntityData 188 192 193 std::set<entity_id_t> m_DirtyVisibility; 189 194 // LOS state: 190 195 191 196 std::map<player_id_t, bool> m_LosRevealAll; … … public: 413 418 ExecuteActiveQueries(); 414 419 break; 415 420 } 421 case MT_Update_Visibility: 422 { 423 CMessageVisibilityChanged msg; 424 for (std::set<entity_id_t>::iterator it = m_DirtyVisibility.begin(); it != m_DirtyVisibility.end(); ++it) 425 { 426 g_Game->GetSimulation2()->PostMessage(*it, msg); 427 } 428 m_DirtyVisibility.clear(); 429 break; 430 } 416 431 case MT_RenderSubmit: 417 432 { 418 433 const CMessageRenderSubmit& msgData = static_cast<const CMessageRenderSubmit&> (msg); … … public: 876 891 { 877 892 // (We can't use m_EntityData since this needs to handle LOCAL entities too) 878 893 894 CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), ent); 895 if (!cmpVisual.null()) 896 { 897 // Proxy entities for other players are never visible 898 player_id_t target = cmpVisual->GetProxyPlayerTarget(); 899 if (target != INVALID_PLAYER && target != player) 900 return VIS_HIDDEN; 901 } 902 879 903 // Entities not with positions in the world are never visible 880 904 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), ent); 881 905 if (cmpPosition.null() || !cmpPosition->IsInWorld()) … … public: 902 926 if (los.IsVisible(i, j)) 903 927 return VIS_VISIBLE; 904 928 929 // If a proxy exists, we should never show this actor 930 if (!cmpVisual.null() && cmpVisual->GetProxyForPlayer(player) != INVALID_ENTITY) 931 { 932 return VIS_HIDDEN; 933 } 934 905 935 // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region 906 936 if (los.IsExplored(i, j)) 907 937 { … … public: 971 1001 m_LosState[i+1 + j*m_TerrainVerticesPerSide] |= (LOS_EXPLORED << (2*(p-1))); 972 1002 m_LosState[i + (j+1)*m_TerrainVerticesPerSide] |= (LOS_EXPLORED << (2*(p-1))); 973 1003 m_LosState[i+1 + (j+1)*m_TerrainVerticesPerSide] |= (LOS_EXPLORED << (2*(p-1))); 1004 1005 CFixedVector2D start(fixed::FromInt(i*CELL_SIZE), fixed::FromInt(j*CELL_SIZE)); 1006 CFixedVector2D end(fixed::FromInt((i+1)*CELL_SIZE), fixed::FromInt((j+1)*CELL_SIZE)); 1007 std::vector<entity_id_t> ents = m_Subdivision.GetInRange(start, end); 1008 m_DirtyVisibility.insert(ents.begin(), ents.end()); 974 1009 } 975 1010 } 976 1011 } … … public: 1025 1060 { 1026 1061 i32 i = i0 + idx - idx0; 1027 1062 if (!LosIsOffWorld(i, j)) 1063 { 1028 1064 m_LosState[idx] |= ((LOS_VISIBLE | LOS_EXPLORED) << (2*(owner-1))); 1065 } 1029 1066 } 1030 1067 1031 1068 ASSERT(counts[idx] < 65535); 1032 1069 counts[idx] = (u16)(counts[idx] + 1); // ignore overflow; the player should never have 64K units 1033 1070 } 1071 1072 CFixedVector2D start(fixed::FromInt(i0*CELL_SIZE), fixed::FromInt(j*CELL_SIZE)); 1073 CFixedVector2D end(fixed::FromInt(i1*CELL_SIZE), fixed::FromInt(j*CELL_SIZE)); 1074 std::vector<entity_id_t> ents = m_Subdivision.GetInRange(start, end); 1075 m_DirtyVisibility.insert(ents.begin(), ents.end()); 1034 1076 } 1035 1077 1036 1078 /** … … public: 1054 1096 { 1055 1097 // (If LosIsOffWorld then this is a no-op, so don't bother doing the check) 1056 1098 m_LosState[idx] &= ~(LOS_VISIBLE << (2*(owner-1))); 1057 1099 } 1058 1100 } 1101 1102 CFixedVector2D start(fixed::FromInt(i0*CELL_SIZE), fixed::FromInt(j*CELL_SIZE)); 1103 CFixedVector2D end(fixed::FromInt(i1*CELL_SIZE), fixed::FromInt(j*CELL_SIZE)); 1104 std::vector<entity_id_t> ents = m_Subdivision.GetInRange(start, end); 1105 m_DirtyVisibility.insert(ents.begin(), ents.end()); 1059 1106 } 1060 1107 1061 1108 /** -
source/simulation2/components/CCmpUnitMotion.cpp
diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index 9175d88..7b0c382 100644
a b bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange 1311 1311 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY); 1312 1312 if (cmpObstructionManager.null()) 1313 1313 return false; 1314 1315 1314 bool hasObstruction = false; 1316 1315 ICmpObstructionManager::ObstructionSquare obstruction; 1317 1316 CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), target); -
source/simulation2/components/CCmpVisualActor.cpp
diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index 4285666..a73d10c 100644
a b 17 17 18 18 #include "precompiled.h" 19 19 20 #include <sstream> 21 22 #include "simulation2/Simulation2.h" 20 23 #include "simulation2/system/Component.h" 21 24 #include "ICmpVisual.h" 22 25 … … 24 27 #include "ICmpPosition.h" 25 28 #include "ICmpRangeManager.h" 26 29 #include "ICmpVision.h" 30 #include "ICmpTemplateManager.h" 27 31 #include "simulation2/MessageTypes.h" 28 32 #include "simulation2/components/ICmpFootprint.h" 33 #include "simulation2/serialization/SerializeTemplates.h" 29 34 30 35 #include "graphics/Frustum.h" 31 36 #include "graphics/Model.h" … … 37 42 #include "maths/Matrix3D.h" 38 43 #include "maths/Vector3D.h" 39 44 #include "ps/CLogger.h" 45 #include "ps/Game.h" 40 46 #include "renderer/Scene.h" 47 #include "lib/utf8.h" 41 48 42 49 class CCmpVisualActor : public ICmpVisual 43 50 { … … public: 48 55 componentManager.SubscribeToMessageType(MT_Interpolate); 49 56 componentManager.SubscribeToMessageType(MT_RenderSubmit); 50 57 componentManager.SubscribeToMessageType(MT_OwnershipChanged); 58 componentManager.SubscribeToMessageType(MT_VisibilityChanged); 51 59 componentManager.SubscribeGloballyToMessageType(MT_TerrainChanged); 52 60 } 53 61 … … public: 59 67 fixed m_R, m_G, m_B; // shading colour 60 68 61 69 ICmpRangeManager::ELosVisibility m_Visibility; // only valid between Interpolate and RenderSubmit 70 ICmpRangeManager::ELosVisibility m_LastVisibility; 71 bool m_FirstVisUpdate; 72 73 typedef std::map<player_id_t, entity_id_t> ProxyEntityMap; 74 ProxyEntityMap m_ProxyEntities; 75 entity_id_t m_ProxiedEntity; 76 player_id_t m_ProxyPlayerTarget; 77 78 int32_t m_ActorSeed; 62 79 63 80 // Current animation state 64 81 fixed m_AnimRunThreshold; // if non-zero this is the special walk/run mode … … public: 138 155 139 156 m_R = m_G = m_B = fixed::FromInt(1); 140 157 158 m_FirstVisUpdate = true; 159 m_LastVisibility = ICmpRangeManager::VIS_VISIBLE; 160 161 m_ProxyPlayerTarget = INVALID_PLAYER; 162 m_ProxiedEntity = INVALID_ENTITY; 163 164 m_ActorSeed = GetEntityId(); 165 141 166 if (!GetSimContext().HasUnitManager()) 142 167 return; // do nothing further if graphics are disabled 143 168 … … public: 148 173 else 149 174 m_ActorName = paramNode.GetChild("Actor").ToString(); 150 175 151 std::set<CStr> selections; 152 m_Unit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, GetActorSeed(), selections); 153 if (m_Unit) 176 ResetUnitSeed(m_ActorSeed); 177 if (m_Unit) 154 178 { 155 u32 modelFlags = 0; 156 if (paramNode.GetChild("SilhouetteDisplay").ToBool()) 157 modelFlags |= MODELFLAG_SILHOUETTE_DISPLAY; 158 if (paramNode.GetChild("SilhouetteOccluder").ToBool()) 159 modelFlags |= MODELFLAG_SILHOUETTE_OCCLUDER; 160 161 CModelAbstract& model = m_Unit->GetModel(); 162 if (model.ToCModel()) 163 model.ToCModel()->AddFlagsRec(modelFlags); 164 165 // Initialize the model's selection shape descriptor. This currently relies on the component initialization order; the 166 // Footprint component must be initialized before this component (VisualActor) to support the ability to use the footprint 167 // shape for the selection box (instead of the default recursive bounding box). See TypeList.h for the order in 168 // which components are initialized; if for whatever reason you need to get rid of this dependency, you can always just 169 // initialize the selection shape descriptor on-demand. 170 InitSelectionShapeDescriptor(model, paramNode); 171 172 m_Unit->SetID(GetEntityId()); 179 u32 modelFlags = 0; 180 if (paramNode.GetChild("SilhouetteDisplay").ToBool()) 181 modelFlags |= MODELFLAG_SILHOUETTE_DISPLAY; 182 if (paramNode.GetChild("SilhouetteOccluder").ToBool()) 183 modelFlags |= MODELFLAG_SILHOUETTE_OCCLUDER; 184 185 CModelAbstract& model = m_Unit->GetModel(); 186 if (model.ToCModel()) 187 model.ToCModel()->AddFlagsRec(modelFlags); 188 189 // Initialize the model's selection shape descriptor. This currently relies on the component initialization order; the 190 // Footprint component must be initialized before this component (VisualActor) to support the ability to use the footprint 191 // shape for the selection box (instead of the default recursive bounding box). See TypeList.h for the order in 192 // which components are initialized; if for whatever reason you need to get rid of this dependency, you can always just 193 // initialize the selection shape descriptor on-demand. 194 InitSelectionShapeDescriptor(model, paramNode); 173 195 } 174 196 175 197 SelectAnimation("idle", false, fixed::FromInt(1), L""); … … public: 206 228 serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync); 207 229 serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime); 208 230 231 serialize.NumberI32_Unbounded("seed", m_ActorSeed); 232 //serialize.Bool("first vis update", m_FirstVisUpdate); 233 /* serialize.NumberU8("last visibility state", *(uint8_t*)&m_LastVisibility, (uint8_t)ICmpRangeManager::VIS_HIDDEN, (uint8_t)ICmpRangeManager::VIS_VISIBLE);*/ 234 serialize.NumberU32_Unbounded("proxied entity", m_ProxiedEntity); 235 serialize.NumberI32_Unbounded("proxy player target", m_ProxyPlayerTarget); 236 SerializeMap<SerializeI32_Unbounded, SerializeU32_Unbounded>()(serialize, "per-player proxy entities", m_ProxyEntities); 209 237 // TODO: store actor variables? 210 238 } 211 239 … … public: 226 254 Init(paramNode); 227 255 228 256 SerializeCommon(deserialize); 229 257 230 258 fixed repeattime = m_AnimSyncRepeatTime; // save because SelectAnimation overwrites it 231 259 232 260 if (m_AnimRunThreshold.IsZero()) … … public: 246 274 247 275 virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) 248 276 { 277 if (msg.GetType() == MT_VisibilityChanged) 278 { 279 const CMessageVisibilityChanged& msgData = static_cast<const CMessageVisibilityChanged&> (msg); 280 if (msgData.source == INVALID_ENTITY) 281 VisibilityChanged(); 282 return; 283 } 284 249 285 // Quick exit for running in non-graphical mode 250 286 if (m_Unit == NULL) 251 287 return; … … public: 456 492 457 493 // TODO: should copy/reset silhouette flags 458 494 } 495 496 virtual entity_id_t GetProxyForPlayer(player_id_t player) 497 { 498 ProxyEntityMap::iterator result = m_ProxyEntities.find(player); 499 if (result != m_ProxyEntities.end()) { 500 return result->second; 501 } 502 return INVALID_ENTITY; 503 } 504 505 virtual entity_id_t GetProxyOwner() 506 { 507 return m_ProxiedEntity; 508 } 509 510 virtual player_id_t GetProxyPlayerTarget() 511 { 512 return m_ProxyPlayerTarget; 513 } 514 515 virtual void SetProxyData(entity_id_t entity, player_id_t player) 516 { 517 m_ProxiedEntity = entity; 518 m_ProxyPlayerTarget = player; 519 } 520 521 virtual void ResetUnitSeed(int32_t seed) 522 { 523 m_ActorSeed = seed; 524 if (!GetSimContext().HasUnitManager()) 525 return; 526 if (m_Unit) 527 GetSimContext().GetUnitManager().DeleteUnit(m_Unit); 459 528 529 std::set<CStr> selections; 530 m_Unit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, GetActorSeed(), selections); 531 if (m_Unit) 532 m_Unit->SetID(GetEntityId()); 533 } 534 460 535 private: 461 536 int32_t GetActorSeed() 462 537 { 463 return GetEntityId();538 return m_ActorSeed; 464 539 } 465 540 466 541 /// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init. … … private: 471 546 void InitSelectionShapeDescriptor(CModelAbstract& model, const CParamNode& paramNode); 472 547 473 548 void Update(fixed turnLength); 549 void VisibilityChanged(); 474 550 void Interpolate(float frameTime, float frameOffset); 475 551 void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling); 476 552 }; … … void CCmpVisualActor::Update(fixed turnLength) 584 660 } 585 661 } 586 662 663 void CCmpVisualActor::VisibilityChanged() 664 { 665 player_id_t player = GetSimContext().GetCurrentDisplayedPlayer(); 666 667 CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); 668 ICmpRangeManager::ELosVisibility vis = cmpRangeManager->GetLosVisibility(GetEntityId(), player); 669 670 bool forceProxy = false; 671 if (m_FirstVisUpdate) 672 { 673 m_LastVisibility = vis; 674 if (vis == ICmpRangeManager::VIS_FOGGED) 675 { 676 forceProxy = true; 677 } 678 m_FirstVisUpdate = false; 679 } 680 681 if (vis != m_LastVisibility || forceProxy) 682 { 683 CSimulation2& simulation = *g_Game->GetSimulation2(); 684 if (vis == ICmpRangeManager::VIS_FOGGED && m_ProxiedEntity == INVALID_ENTITY) 685 { 686 CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY); 687 std::string templ = cmpTemplateManager->GetCurrentTemplateName(GetEntityId()); 688 std::wstring wtempl = wstring_from_utf8(templ); 689 entity_id_t proxy = simulation.AddEntity(wtempl); 690 CmpPtr<ICmpVisual> proxyVis(simulation, proxy); 691 proxyVis->SetProxyData(GetEntityId(), player); 692 proxyVis->ResetUnitSeed(GetActorSeed()); 693 m_ProxyEntities[player] = proxy; 694 695 CMessageVisibilityChanged msg(GetEntityId(), proxy, player); 696 simulation.BroadcastMessage(msg); 697 } 698 else if (vis == ICmpRangeManager::VIS_VISIBLE) 699 { 700 ProxyEntityMap::iterator it = m_ProxyEntities.find(player); 701 if (it != m_ProxyEntities.end()) 702 { 703 simulation.DestroyEntity(it->second); 704 m_ProxyEntities.erase(it); 705 } 706 707 if (m_ProxiedEntity != INVALID_ENTITY) 708 { 709 CmpPtr<ICmpVisual> proxyVis(simulation, m_ProxiedEntity); 710 if (proxyVis.null()) 711 simulation.DestroyEntity(GetEntityId()); 712 } 713 } 714 } 715 716 m_LastVisibility = vis; 717 } 718 587 719 void CCmpVisualActor::Interpolate(float frameTime, float frameOffset) 588 720 { 589 721 if (m_Unit == NULL) -
source/simulation2/components/ICmpVisual.cpp
diff --git a/source/simulation2/components/ICmpVisual.cpp b/source/simulation2/components/ICmpVisual.cpp index 2a6e580..37ab0f2 100644
a b DEFINE_INTERFACE_METHOD_1("SetAnimationSyncRepeat", void, ICmpVisual, SetAnimati 28 28 DEFINE_INTERFACE_METHOD_1("SetAnimationSyncOffset", void, ICmpVisual, SetAnimationSyncOffset, fixed) 29 29 DEFINE_INTERFACE_METHOD_4("SetShadingColour", void, ICmpVisual, SetShadingColour, fixed, fixed, fixed, fixed) 30 30 DEFINE_INTERFACE_METHOD_2("SetVariable", void, ICmpVisual, SetVariable, std::string, float) 31 DEFINE_INTERFACE_METHOD_0("GetProxyPlayerTarget", player_id_t, ICmpVisual, GetProxyPlayerTarget) 32 DEFINE_INTERFACE_METHOD_0("GetProxyOwner", entity_id_t, ICmpVisual, GetProxyOwner) 31 33 END_INTERFACE_WRAPPER(Visual) -
source/simulation2/components/ICmpVisual.h
diff --git a/source/simulation2/components/ICmpVisual.h b/source/simulation2/components/ICmpVisual.h index ade286e..8be583c 100644
a b 19 19 #define INCLUDED_ICMPVISUAL 20 20 21 21 #include "simulation2/system/Interface.h" 22 #include "simulation2/helpers/Player.h" 22 23 23 24 #include "ps/CStr.h" 24 25 #include "maths/BoundingBoxOriented.h" … … public: 138 139 */ 139 140 virtual void Hotload(const VfsPath& name) = 0; 140 141 141 DECLARE_INTERFACE_TYPE(Visual) 142 /** 143 * 144 */ 145 virtual entity_id_t GetProxyForPlayer(player_id_t player) = 0; 146 147 virtual entity_id_t GetProxyOwner() = 0; 148 virtual player_id_t GetProxyPlayerTarget() = 0; 149 virtual void SetProxyData(entity_id_t entity, player_id_t player) = 0; 150 virtual void ResetUnitSeed(int32_t seed) = 0; 151 152 DECLARE_INTERFACE_TYPE(Visual) 142 153 }; 143 154 144 155 // TODO: rename this to VisualActor, because the interface is actor-specific, maybe? -
source/simulation2/scripting/MessageTypeConversions.cpp
diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index d976a09..668a020 100644
a b MESSAGE_1(Update_MotionFormation, fixed, turnLength) 90 90 MESSAGE_1(Update_MotionUnit, fixed, turnLength) 91 91 MESSAGE_1(Update_Final, fixed, turnLength) 92 92 93 jsval CMessageUpdate_Visibility::ToJSVal(ScriptInterface& scriptInterface) const 94 { 95 TOJSVAL_SETUP(); 96 return OBJECT_TO_JSVAL(obj); 97 } 98 99 CMessage* CMessageUpdate_Visibility::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) 100 { 101 return NULL; 102 } 103 93 104 //////////////////////////////// 94 105 95 106 jsval CMessageInterpolate::ToJSVal(ScriptInterface& scriptInterface) const … … CMessage* CMessagePathResult::FromJSVal(ScriptInterface& UNUSED(scriptInterface) 296 307 return NULL; 297 308 } 298 309 310 //////////////////////////////// 311 312 jsval CMessageVisibilityChanged::ToJSVal(ScriptInterface& scriptInterface) const 313 { 314 TOJSVAL_SETUP(); 315 SET_MSG_PROPERTY(source); 316 SET_MSG_PROPERTY(proxy); 317 SET_MSG_PROPERTY(player); 318 return OBJECT_TO_JSVAL(obj); 319 } 320 321 CMessage* CMessageVisibilityChanged::FromJSVal(ScriptInterface& UNUSED(scriptInterface), jsval UNUSED(val)) 322 { 323 LOGWARNING(L"CMessageVisibilityChanged::FromJSVal not implemented"); 324 return NULL; 325 } 326 299 327 //////////////////////////////////////////////////////////////// 300 328 301 329 CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, jsval val)