Ticket #1551: gate-close-3.patch
File gate-close-3.patch, 12.9 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/simulation/components/Foundation.js
109 109 // Otherwise enable this obstruction so it blocks any further 110 110 // units, and continue building. 111 111 112 var collisions = cmpObstruction.Get ConstructionCollisions();112 var collisions = cmpObstruction.GetEntityCollisions(true, true); 113 113 if (collisions.length) 114 114 { 115 115 for each (var ent in collisions) -
binaries/data/mods/public/simulation/components/Gate.js
14 14 */ 15 15 Gate.prototype.Init = function() 16 16 { 17 this. units = [];17 this.allies = []; 18 18 this.opened = false; 19 19 this.locked = false; 20 20 }; … … 39 39 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 40 40 if (this.unitsQuery) 41 41 cmpRangeManager.DestroyActiveQuery(this.unitsQuery); 42 43 // Cancel the closing-blocked timer if it's running. 44 if (this.timer) 45 { 46 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 47 cmpTimer.CancelTimer(this.timer); 48 this.timer = undefined; 49 } 42 50 }; 43 51 44 52 /** … … 48 56 { 49 57 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 50 58 var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); 59 var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player); 51 60 if (this.unitsQuery) 52 61 cmpRangeManager.DestroyActiveQuery(this.unitsQuery); 53 var players = []54 62 55 var numPlayers = cmpPlayerManager.GetNumPlayers(); 63 // Only allied units can make the gate open. 64 var players = []; 65 for (var i = 0; i < cmpPlayer.GetDiplomacy().length; ++i) 66 if (cmpPlayer.IsAlly(i)) 67 players.push(i); 56 68 57 // Ignore gaia units58 for (var i = 1; i < numPlayers; ++i)59 players.push(i);60 61 69 var range = this.GetPassRange(); 62 70 if (range > 0) 63 71 { … … 77 85 78 86 if (msg.added.length > 0) 79 87 for each (var entity in msg.added) 80 this. units.push(entity);88 this.allies.push(entity); 81 89 82 90 if (msg.removed.length > 0) 83 91 for each (var entity in msg.removed) 84 this. units.splice(this.units.indexOf(entity), 1);92 this.allies.splice(this.allies.indexOf(entity), 1); 85 93 86 94 this.OperateGate(); 87 95 }; … … 96 104 97 105 /** 98 106 * Attempt to open or close the gate. 99 * An ally unit must be in range to open the gate, but there must be100 * no units (including enemies) in range to close it again.107 * An ally must be in range to open the gate, but an unlocked gate will only close 108 * if there are no allies in range and no units are inside the gate's obstruction. 101 109 */ 102 110 Gate.prototype.OperateGate = function() 103 111 { 104 if (this.opened == true ) 112 // Cancel the closing-blocked timer if it's running. 113 if (this.timer) 105 114 { 106 // If no units are in range, close the gate107 if (this.units.length == 0)108 this.CloseGate();115 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 116 cmpTimer.CancelTimer(this.timer); 117 this.timer = undefined; 109 118 } 110 else 111 { 112 // If one units in range is owned by an ally, open the gate 113 for each (var ent in this.units) 114 { 115 if (IsOwnedByAllyOfEntity(this.entity, ent)) 116 { 117 this.OpenGate(); 118 break; 119 } 120 } 121 } 119 120 if (this.opened && (this.allies.length == 0 || this.locked)) 121 this.CloseGate(); 122 else if (!this.opened && this.allies.length) 123 this.OpenGate(); 122 124 }; 123 125 124 126 Gate.prototype.IsLocked = function() … … 141 143 return; 142 144 cmpObstruction.SetDisableBlockMovementPathfinding(false, false, 0); 143 145 } 146 else 147 this.OperateGate(); 144 148 145 149 // TODO: Possibly move the lock/unlock sounds to UI? Needs testing 146 150 PlaySound("gate_locked", this.entity); … … 157 161 return; 158 162 159 163 // Disable 'block pathfinding' 160 cmpObstruction.SetDisableBlockMovementPathfinding( false, true, 0);164 cmpObstruction.SetDisableBlockMovementPathfinding(this.opened, true, 0); 161 165 this.locked = false; 162 166 163 167 // TODO: Possibly move the lock/unlock sounds to UI? Needs testing … … 194 198 195 199 /** 196 200 * Close the gate, with sound and animation. 201 * 202 * The gate may fail to close due to unit obstruction. If this occurs, the 203 * gate will start a timer and attempt to close on each simulation update. 197 204 */ 198 205 Gate.prototype.CloseGate = function() 199 206 { … … 201 208 if (!cmpObstruction) 202 209 return; 203 210 211 // The gate can't be closed if there are entities colliding with it. 212 var collisions = cmpObstruction.GetEntityCollisions(false, true); 213 if (collisions.length) 214 { 215 if (!this.timer) 216 { 217 // Set an "instant" timer which will run on the next simulation turn. 218 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 219 this.timer = cmpTimer.SetTimeout(this.entity, IID_Gate, "OperateGate", 0, {}); 220 } 221 return; 222 } 223 204 224 // If we ordered the gate to be locked, enable 'block movement' and 'block pathfinding' 205 225 if (this.locked) 206 226 cmpObstruction.SetDisableBlockMovementPathfinding(false, false, 0); -
source/simulation2/components/CCmpObstruction.cpp
549 549 return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL); 550 550 } 551 551 552 virtual std::vector<entity_id_t> Get ConstructionCollisions()552 virtual std::vector<entity_id_t> GetEntityCollisions(bool checkStructures, bool checkUnits) 553 553 { 554 554 std::vector<entity_id_t> ret; 555 555 … … 569 569 // required precondition to use SkipControlGroupsRequireFlagObstructionFilter 570 570 if (m_ControlGroup == INVALID_ENTITY) 571 571 { 572 LOGERROR(L"[CmpObstruction] Cannot test for constructionobstructions; primary control group must be valid");572 LOGERROR(L"[CmpObstruction] Cannot test for unit or structure obstructions; primary control group must be valid"); 573 573 return ret; 574 574 } 575 575 576 // Ignore collisions within the same control group, or with other non-construction-blocking shapes. 576 flags_t flags = 0; 577 bool invertMatch = false; 578 579 // There are four 'block' flags: construction, foundation, movement, 580 // and pathfinding. Structures have all of these flags, while units 581 // block only movement and construction. 582 583 // The 'block construction' flag is common to both units and structures. 584 if (checkStructures && checkUnits) 585 flags = ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION; 586 // The 'block foundation' flag is exclusive to structures. 587 else if (checkStructures) 588 flags = ICmpObstructionManager::FLAG_BLOCK_FOUNDATION; 589 else if (checkUnits) 590 { 591 // As structures block a superset of what units do, matching units 592 // but not structures means excluding entities that contain any of 593 // the structure-specific flags (foundation and pathfinding). 594 invertMatch = true; 595 flags = ICmpObstructionManager::FLAG_BLOCK_FOUNDATION | ICmpObstructionManager::FLAG_BLOCK_PATHFINDING; 596 } 597 598 // Ignore collisions within the same control group, or with other shapes that don't match the filter. 577 599 // Note that, since the control group for each entity defaults to the entity's ID, this is typically 578 // equivalent to only ignoring the entity's own shape and other non-construction-blocking shapes.579 SkipControlGroupsRequireFlagObstructionFilter filter( m_ControlGroup, m_ControlGroup2,580 ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION);600 // equivalent to only ignoring the entity's own shape and other shapes that don't match the filter. 601 SkipControlGroupsRequireFlagObstructionFilter filter(invertMatch, 602 m_ControlGroup, m_ControlGroup2, flags); 581 603 582 604 if (m_Type == STATIC) 583 605 cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, &ret); -
source/simulation2/components/ICmpObstruction.h
59 59 virtual bool CheckDuplicateFoundation() = 0; 60 60 61 61 /** 62 * Returns a list of entities that are colliding with this entity, and that63 * are set to block construction.62 * Returns a list of entities that are colliding with this entity, 63 * filtered depending on type of entities that are requested. 64 64 * @return vector of blocking entities 65 65 */ 66 virtual std::vector<entity_id_t> Get ConstructionCollisions() = 0;66 virtual std::vector<entity_id_t> GetEntityCollisions(bool checkStructures, bool checkUnits) = 0; 67 67 68 68 /** 69 69 * Detects collisions between foundation-blocking entities and -
source/simulation2/components/ICmpObstruction.cpp
25 25 DEFINE_INTERFACE_METHOD_0("GetUnitRadius", entity_pos_t, ICmpObstruction, GetUnitRadius) 26 26 DEFINE_INTERFACE_METHOD_1("CheckFoundation", bool, ICmpObstruction, CheckFoundation, std::string) 27 27 DEFINE_INTERFACE_METHOD_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) 28 DEFINE_INTERFACE_METHOD_ 0("GetConstructionCollisions", std::vector<entity_id_t>, ICmpObstruction, GetConstructionCollisions)28 DEFINE_INTERFACE_METHOD_2("GetEntityCollisions", std::vector<entity_id_t>, ICmpObstruction, GetEntityCollisions, bool, bool) 29 29 DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool) 30 30 DEFINE_INTERFACE_METHOD_3("SetDisableBlockMovementPathfinding", void, ICmpObstruction, SetDisableBlockMovementPathfinding, bool, bool, int32_t) 31 31 DEFINE_INTERFACE_METHOD_0("GetBlockMovementFlag", bool, ICmpObstruction, GetBlockMovementFlag) -
source/simulation2/components/ICmpObstructionManager.h
355 355 /** 356 356 * Obstruction test filter that will test only against shapes that: 357 357 * - are part of neither one of the specified control groups 358 * - AND have at least one of the specified flags set. 358 * - AND, depending on the value of the 'exclude' argument: 359 * - have at least one of the specified flags set. 360 * - OR have none of the specified flags set. 359 361 * 360 362 * The first (primary) control group to reject shapes from must be specified and valid. The secondary 361 363 * control group to reject entities from may be set to INVALID_ENTITY to not use it. … … 365 367 */ 366 368 class SkipControlGroupsRequireFlagObstructionFilter : public IObstructionTestFilter 367 369 { 370 bool m_Exclude; 368 371 entity_id_t m_Group; 369 372 entity_id_t m_Group2; 370 373 flags_t m_Mask; 371 374 372 375 public: 376 SkipControlGroupsRequireFlagObstructionFilter(bool exclude, entity_id_t group1, entity_id_t group2, flags_t mask) : 377 m_Exclude(exclude), m_Group(group1), m_Group2(group2), m_Mask(mask) 378 { 379 Init(); 380 } 381 373 382 SkipControlGroupsRequireFlagObstructionFilter(entity_id_t group1, entity_id_t group2, flags_t mask) : 374 m_ Group(group1), m_Group2(group2), m_Mask(mask)383 m_Exclude(false), m_Group(group1), m_Group2(group2), m_Mask(mask) 375 384 { 385 Init(); 386 } 387 388 virtual bool TestShape(tag_t UNUSED(tag), flags_t flags, entity_id_t group, entity_id_t group2) const 389 { 390 // Don't test shapes that share one or more of our control groups. 391 if (group == m_Group || group == m_Group2 || (group2 != INVALID_ENTITY && 392 (group2 == m_Group || group2 == m_Group2))) 393 return false; 394 395 // If m_Exclude is true, don't test against shapes that have any of the 396 // obstruction flags specified in m_Mask. 397 if (m_Exclude) 398 return (flags & m_Mask) == 0; 399 400 // Otherwise, only include shapes that match at least one flag in m_Mask. 401 return (flags & m_Mask) != 0; 402 } 403 private: 404 void Init() 405 { 376 406 // the primary control group to filter out must be valid 377 407 ENSURE(m_Group != INVALID_ENTITY); 378 408 … … 381 411 if (m_Group2 == INVALID_ENTITY) 382 412 m_Group2 = m_Group; 383 413 } 384 385 virtual bool TestShape(tag_t UNUSED(tag), flags_t flags, entity_id_t group, entity_id_t group2) const386 {387 // To be included in the testing, a shape must have at least one of the flags in m_Mask set, and its388 // primary control group must be valid and must equal neither our primary nor secondary control group.389 bool includeInTesting = ((flags & m_Mask) != 0 && group != m_Group && group != m_Group2);390 391 // If the shape being tested has a valid secondary control group, exclude it from testing if it392 // matches either our primary or secondary control group.393 if (group2 != INVALID_ENTITY)394 includeInTesting = (includeInTesting && group2 != m_Group && group2 != m_Group2);395 396 return includeInTesting;397 }398 414 }; 399 415 400 416 /**