Index: binaries/data/mods/public/simulation/components/Foundation.js =================================================================== --- binaries/data/mods/public/simulation/components/Foundation.js +++ binaries/data/mods/public/simulation/components/Foundation.js @@ -276,7 +276,7 @@ for (let ent of cmpObstruction.GetEntitiesDeletedUponConstruction()) Engine.DestroyEntity(ent); - let collisions = cmpObstruction.GetEntitiesBlockingConstruction(); + let collisions = cmpObstruction.GetUnitsBlockingMovement(); if (collisions.length) { for (var ent of collisions) Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js =================================================================== --- binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -241,14 +241,6 @@ this.entities.splice(entityIndex, 1); - let cmpEntUnitAI = Engine.QueryInterface(entity, IID_UnitAI); - if (cmpEntUnitAI) - cmpEntUnitAI.Ungarrison(); - - let cmpEntProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); - if (cmpEntProductionQueue) - cmpEntProductionQueue.UnpauseProduction(); - let cmpEntAura = Engine.QueryInterface(entity, IID_Auras); if (cmpEntAura && cmpEntAura.HasGarrisonAura()) cmpEntAura.RemoveGarrisonAura(this.entity); @@ -270,6 +262,15 @@ "renamed": renamed }); + // These should be called after the unit has been moved back into the world. + let cmpEntUnitAI = Engine.QueryInterface(entity, IID_UnitAI); + if (cmpEntUnitAI) + cmpEntUnitAI.Ungarrison(); + + let cmpEntProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); + if (cmpEntProductionQueue) + cmpEntProductionQueue.UnpauseProduction(); + return true; }; Index: binaries/data/mods/public/simulation/components/Gate.js =================================================================== --- binaries/data/mods/public/simulation/components/Gate.js +++ binaries/data/mods/public/simulation/components/Gate.js @@ -250,13 +250,13 @@ if (!cmpObstruction) return; - // The gate can't be closed if there are entities colliding with it. - // NB: because walls are overlapping, they requires special care to not break - // in particular, walls do not block construction, so walls from skirmish maps - // do not appear in this check even if they have different control groups from the gate. - // This no longer works if gates are made to check for entities blocking movement. - // Fixing that would let us change this code, but it sounds decidedly non-trivial. - let collisions = cmpObstruction.GetEntitiesBlockingConstruction(); + // The gate can't be closed if there are units colliding with it. + // This doesn't consider static entities, as it is assumed either: + // - the gate couldn't be built in the first place + // - the gate was put there by some higher power (e.g. skirmish replacements, atlas). + // In either case we probably don't want to account for them. + // TODO: this precludes some "gate blocker" from existing. + let collisions = cmpObstruction.GetUnitsBlockingMovement(); if (collisions.length) { if (!this.timer) Index: binaries/data/mods/public/simulation/components/TurretHolder.js =================================================================== --- binaries/data/mods/public/simulation/components/TurretHolder.js +++ binaries/data/mods/public/simulation/components/TurretHolder.js @@ -111,7 +111,7 @@ // Remove the unit's obstruction to avoid interfering with pathing. let cmpObstruction = Engine.QueryInterface(entity, IID_Obstruction); if (cmpObstruction) - cmpObstruction.SetActive(false); + cmpObstruction.SetDisableBlockMovementPathfinding(true, true, -1); Engine.PostMessage(this.entity, MT_TurretsChanged, { "added": [entity], @@ -168,7 +168,7 @@ // Reset the obstruction flags to template defaults. let cmpObstruction = Engine.QueryInterface(entity, IID_Obstruction); if (cmpObstruction) - cmpObstruction.SetActive(true); + cmpObstruction.SetDisableBlockMovementPathfinding(false, false, -1); Engine.PostMessage(this.entity, MT_TurretsChanged, { "added": [], Index: binaries/data/mods/public/simulation/components/UnitAI.js =================================================================== --- binaries/data/mods/public/simulation/components/UnitAI.js +++ binaries/data/mods/public/simulation/components/UnitAI.js @@ -635,6 +635,7 @@ "Order.Ungarrison": function() { this.FinishOrder(); this.isGarrisoned = false; + this.SetImmobile(false); }, "Order.Cheer": function(msg) { @@ -5386,10 +5387,7 @@ UnitAI.prototype.Ungarrison = function() { if (this.IsGarrisoned()) - { - this.SetImmobile(false); this.AddOrder("Ungarrison", null, false); - } }; /** Index: binaries/data/mods/public/simulation/helpers/Transform.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Transform.js +++ binaries/data/mods/public/simulation/helpers/Transform.js @@ -230,7 +230,7 @@ for (let ent of cmpNewObstruction.GetEntitiesDeletedUponConstruction()) Engine.DestroyEntity(ent); - let collisions = cmpNewObstruction.GetEntitiesBlockingConstruction(); + let collisions = cmpNewObstruction.GetUnitsBlockingMovement(); if (collisions.length) return DeleteEntityAndReturn(previewEntity, cmpPosition, pos, angle, cmpNewPosition, true); } Index: binaries/data/mods/public/simulation/templates/special/filter/corpse.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/corpse.xml +++ binaries/data/mods/public/simulation/templates/special/filter/corpse.xml @@ -14,7 +14,8 @@ - false + true + true Index: binaries/data/mods/public/simulation/templates/special/filter/mirage.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/mirage.xml +++ binaries/data/mods/public/simulation/templates/special/filter/mirage.xml @@ -18,7 +18,6 @@ false false false - false false Index: binaries/data/mods/public/simulation/templates/special/filter/preview.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/preview.xml +++ binaries/data/mods/public/simulation/templates/special/filter/preview.xml @@ -12,7 +12,9 @@ - false + false + true + true false Index: binaries/data/mods/public/simulation/templates/special/filter/resource.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/resource.xml +++ binaries/data/mods/public/simulation/templates/special/filter/resource.xml @@ -10,11 +10,9 @@ TODO: this should probably be generalized as a parameter on entity death or something. --> - true false false false - true true false false Index: binaries/data/mods/public/simulation/templates/template_formation.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_formation.xml +++ binaries/data/mods/public/simulation/templates/template_formation.xml @@ -39,11 +39,9 @@ - true false false false - false false false false Index: binaries/data/mods/public/simulation/templates/template_gaia.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_gaia.xml +++ binaries/data/mods/public/simulation/templates/template_gaia.xml @@ -8,11 +8,9 @@ true - true true true true - true false false false Index: binaries/data/mods/public/simulation/templates/template_structure.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_structure.xml +++ binaries/data/mods/public/simulation/templates/template_structure.xml @@ -60,11 +60,9 @@ structure - true true true true - false false false false Index: binaries/data/mods/public/simulation/templates/template_unit.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit.xml +++ binaries/data/mods/public/simulation/templates/template_unit.xml @@ -55,11 +55,9 @@ - true true false false - true false false false Index: source/simulation2/components/CCmpObstruction.cpp =================================================================== --- source/simulation2/components/CCmpObstruction.cpp +++ source/simulation2/components/CCmpObstruction.cpp @@ -66,8 +66,6 @@ // Dynamic state: - /// Whether the obstruction is actively obstructing or just an inactive placeholder. - bool m_Active; /// Whether the entity associated with this obstruction is currently moving. Only applicable for /// UNIT-type obstructions. bool m_Moving; @@ -149,19 +147,13 @@ "" "" "" - "" - "" - "" "" "" "" "" "" "" - "" - "" - "" - "" + "" "" "" "" @@ -192,8 +184,6 @@ m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_PATHFINDING; if (paramNode.GetChild("BlockFoundation").ToBool()) m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_FOUNDATION; - if (paramNode.GetChild("BlockConstruction").ToBool()) - m_TemplateFlags |= ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION; if (paramNode.GetChild("DeleteUponConstruction").ToBool()) m_TemplateFlags |= ICmpObstructionManager::FLAG_DELETE_UPON_CONSTRUCTION; @@ -246,7 +236,6 @@ m_Size1 = fixed::FromInt(2).Multiply(std::max(max.Y, -min.Y)); } - m_Active = paramNode.GetChild("Active").ToBool(); m_ControlPersist = paramNode.GetChild("ControlPersist").IsOk(); m_Tag = tag_t(); @@ -273,7 +262,6 @@ template void SerializeCommon(S& serialize) { - serialize.Bool("active", m_Active); serialize.Bool("moving", m_Moving); serialize.NumberU32_Unbounded("control group", m_ControlGroup); serialize.NumberU32_Unbounded("control group 2", m_ControlGroup2); @@ -303,9 +291,6 @@ { case MT_PositionChanged: { - if (!m_Active) - break; - const CMessagePositionChanged& data = static_cast (msg); if (!data.inWorld && !m_Tag.valid()) @@ -360,7 +345,6 @@ break; // error // Deactivate the obstruction in case PositionChanged messages are sent after this. - m_Active = false; cmpObstructionManager->RemoveShape(m_Tag); m_Tag = tag_t(); if(m_Type == CLUSTER) @@ -371,56 +355,39 @@ } } - virtual void SetActive(bool active) + void ResetShape() { - if (active && !m_Active) - { - m_Active = true; - - // Construct the obstruction shape - - CmpPtr cmpObstructionManager(GetSystemEntity()); - if (!cmpObstructionManager) - return; // error - - CmpPtr cmpPosition(GetEntityHandle()); - if (!cmpPosition) - return; // error - - if (!cmpPosition->IsInWorld()) - return; // don't need an obstruction + // Delete the obstruction shape + // TODO: code duplication from message handlers + CmpPtr cmpObstructionManager(GetSystemEntity()); + if (!cmpObstructionManager) + return; // error - // TODO: code duplication from message handlers - CFixedVector2D pos = cmpPosition->GetPosition2D(); - if (m_Type == STATIC) - m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(), - pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2); - else if (m_Type == UNIT) - m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(), - pos.X, pos.Y, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup); - else - AddClusterShapes(pos.X, pos.Y, cmpPosition->GetRotation().Y); - } - else if (!active && m_Active) + if (m_Tag.valid()) { - m_Active = false; - - // Delete the obstruction shape - - // TODO: code duplication from message handlers - if (m_Tag.valid()) - { - CmpPtr cmpObstructionManager(GetSystemEntity()); - if (!cmpObstructionManager) - return; // error - - cmpObstructionManager->RemoveShape(m_Tag); - m_Tag = tag_t(); - if (m_Type == CLUSTER) - RemoveClusterShapes(); - } + cmpObstructionManager->RemoveShape(m_Tag); + m_Tag = tag_t(); + if (m_Type == CLUSTER) + RemoveClusterShapes(); } - // else we didn't change the active status + + // Construct the obstruction shape + CmpPtr cmpPosition(GetEntityHandle()); + if (!cmpPosition) + return; // + + if (!cmpPosition->IsInWorld()) + return; // don't need an obstruction + + CFixedVector2D pos = cmpPosition->GetPosition2D(); + if (m_Type == STATIC) + m_Tag = cmpObstructionManager->AddStaticShape(GetEntityId(), + pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, m_Flags, m_ControlGroup, m_ControlGroup2); + else if (m_Type == UNIT) + m_Tag = cmpObstructionManager->AddUnitShape(GetEntityId(), + pos.X, pos.Y, m_Clearance, (flags_t)(m_Flags | (m_Moving ? ICmpObstructionManager::FLAG_MOVING : 0)), m_ControlGroup); + else + AddClusterShapes(pos.X, pos.Y, cmpPosition->GetRotation().Y); } virtual void SetDisableBlockMovementPathfinding(bool movementDisabled, bool pathfindingDisabled, int32_t shape) @@ -446,11 +413,7 @@ // Reset the shape with the new flags (kind of inefficiently - we // should have a ICmpObstructionManager::SetFlags function or something) - if (m_Active) - { - SetActive(false); - SetActive(true); - } + ResetShape(); } virtual bool GetBlockMovementFlag() const @@ -621,6 +584,11 @@ } virtual std::vector GetEntitiesByFlags(flags_t flags) const + { + return GetEntitiesByFlags(flags, true, true); + } + + virtual std::vector GetEntitiesByFlags(flags_t flags, bool unitShapes, bool staticShapes) const { std::vector ret; @@ -637,20 +605,17 @@ if (!GetObstructionSquare(square)) return ret; // error - cmpObstructionManager->GetUnitsOnObstruction(square, ret, filter, false); - cmpObstructionManager->GetStaticObstructionsOnObstruction(square, ret, filter); + if (unitShapes) + cmpObstructionManager->GetUnitsOnObstruction(square, ret, filter, false); + if (staticShapes) + cmpObstructionManager->GetStaticObstructionsOnObstruction(square, ret, filter); return ret; } - virtual std::vector GetEntitiesBlockingMovement() const + virtual std::vector GetUnitsBlockingMovement() const { - return GetEntitiesByFlags(ICmpObstructionManager::FLAG_BLOCK_MOVEMENT); - } - - virtual std::vector GetEntitiesBlockingConstruction() const - { - return GetEntitiesByFlags(ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION); + return GetEntitiesByFlags(ICmpObstructionManager::FLAG_BLOCK_MOVEMENT, true, false); } virtual std::vector GetEntitiesDeletedUponConstruction() const Index: source/simulation2/components/ICmpObstruction.h =================================================================== --- source/simulation2/components/ICmpObstruction.h +++ source/simulation2/components/ICmpObstruction.h @@ -109,16 +109,10 @@ virtual std::vector GetEntitiesByFlags(ICmpObstructionManager::flags_t flags) const = 0; /** - * Returns a list of entities that are blocking movement. + * Returns a list of unit shapes that are blocking movement. * @return vector of blocking entities */ - virtual std::vector GetEntitiesBlockingMovement() const = 0; - - /** - * Returns a list of entities that are blocking construction of a foundation. - * @return vector of blocking entities - */ - virtual std::vector GetEntitiesBlockingConstruction() const = 0; + virtual std::vector GetUnitsBlockingMovement() const = 0; /** * Returns a list of entities that shall be deleted when a construction on this obstruction starts, @@ -132,8 +126,6 @@ */ virtual void ResolveFoundationCollisions() const = 0; - virtual void SetActive(bool active) = 0; - virtual void SetMovingFlag(bool enabled) = 0; virtual void SetDisableBlockMovementPathfinding(bool movementDisabled, bool pathfindingDisabled, int32_t shape) = 0; Index: source/simulation2/components/ICmpObstruction.cpp =================================================================== --- source/simulation2/components/ICmpObstruction.cpp +++ source/simulation2/components/ICmpObstruction.cpp @@ -50,10 +50,8 @@ DEFINE_INTERFACE_METHOD_CONST_0("CheckShorePlacement", bool, ICmpObstruction, CheckShorePlacement) DEFINE_INTERFACE_METHOD_CONST_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool) DEFINE_INTERFACE_METHOD_CONST_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) -DEFINE_INTERFACE_METHOD_CONST_0("GetEntitiesBlockingMovement", std::vector, ICmpObstruction, GetEntitiesBlockingMovement) -DEFINE_INTERFACE_METHOD_CONST_0("GetEntitiesBlockingConstruction", std::vector, ICmpObstruction, GetEntitiesBlockingConstruction) +DEFINE_INTERFACE_METHOD_CONST_0("GetUnitsBlockingMovement", std::vector, ICmpObstruction, GetUnitsBlockingMovement) DEFINE_INTERFACE_METHOD_CONST_0("GetEntitiesDeletedUponConstruction", std::vector, ICmpObstruction, GetEntitiesDeletedUponConstruction) -DEFINE_INTERFACE_METHOD_1("SetActive", void, ICmpObstruction, SetActive, bool) DEFINE_INTERFACE_METHOD_3("SetDisableBlockMovementPathfinding", void, ICmpObstruction, SetDisableBlockMovementPathfinding, bool, bool, int32_t) DEFINE_INTERFACE_METHOD_CONST_0("GetBlockMovementFlag", bool, ICmpObstruction, GetBlockMovementFlag) DEFINE_INTERFACE_METHOD_1("SetControlGroup", void, ICmpObstruction, SetControlGroup, entity_id_t) Index: source/simulation2/components/ICmpObstructionManager.h =================================================================== --- source/simulation2/components/ICmpObstructionManager.h +++ source/simulation2/components/ICmpObstructionManager.h @@ -90,10 +90,9 @@ { FLAG_BLOCK_MOVEMENT = (1 << 0), // prevents units moving through this shape FLAG_BLOCK_FOUNDATION = (1 << 1), // prevents foundations being placed on this shape - FLAG_BLOCK_CONSTRUCTION = (1 << 2), // prevents buildings being constructed on this shape - FLAG_BLOCK_PATHFINDING = (1 << 3), // prevents the tile pathfinder choosing paths through this shape - FLAG_MOVING = (1 << 4), // indicates this unit is currently moving - FLAG_DELETE_UPON_CONSTRUCTION = (1 << 5) // this entity is deleted when construction of a building placed on top of this entity starts + FLAG_BLOCK_PATHFINDING = (1 << 2), // prevents the tile pathfinder choosing paths through this shape + FLAG_MOVING = (1 << 3), // indicates this unit is currently moving + FLAG_DELETE_UPON_CONSTRUCTION = (1 << 4) // this entity is deleted when construction of a building placed on top of this entity starts }; /** Index: source/simulation2/components/tests/test_ObstructionManager.h =================================================================== --- source/simulation2/components/tests/test_ObstructionManager.h +++ source/simulation2/components/tests/test_ObstructionManager.h @@ -40,11 +40,9 @@ virtual std::string CheckFoundation_wrapper(const std::string& UNUSED(className), bool UNUSED(onlyCenterPoint)) const { return std::string(); } virtual bool CheckDuplicateFoundation() const { return true; } virtual std::vector GetEntitiesByFlags(ICmpObstructionManager::flags_t UNUSED(flags)) const { return std::vector(); } - virtual std::vector GetEntitiesBlockingMovement() const { return std::vector(); } - virtual std::vector GetEntitiesBlockingConstruction() const { return std::vector(); } + virtual std::vector GetUnitsBlockingMovement() const { return std::vector(); } virtual std::vector GetEntitiesDeletedUponConstruction() const { return std::vector(); } virtual void ResolveFoundationCollisions() const { } - virtual void SetActive(bool UNUSED(active)) { } virtual void SetMovingFlag(bool UNUSED(enabled)) { } virtual void SetDisableBlockMovementPathfinding(bool UNUSED(movementDisabled), bool UNUSED(pathfindingDisabled), int32_t UNUSED(shape)) { } virtual bool GetBlockMovementFlag() const { return true; } @@ -108,12 +106,10 @@ cmp->SetBounds(fixed::FromInt(0), fixed::FromInt(0), fixed::FromInt(1000), fixed::FromInt(1000)); shape1 = cmp->AddStaticShape(ent1, ent1x, ent1z, ent1a, ent1w, ent1h, - ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION | ICmpObstructionManager::FLAG_BLOCK_MOVEMENT | ICmpObstructionManager::FLAG_MOVING, ent1g1, ent1g2); shape2 = cmp->AddUnitShape(ent2, ent2x, ent2z, ent2c, - ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION | ICmpObstructionManager::FLAG_BLOCK_FOUNDATION, ent2g); shape3 = cmp->AddUnitShape(ent3, ent3x, ent3z, ent3c, @@ -312,13 +308,12 @@ std::vector out; // Collision-test a shape that overlaps the entire scene, but ignoring shapes from shape1's control group - // (which also includes shape 2), and requiring that either the BLOCK_FOUNDATION or the - // BLOCK_CONSTRUCTION flag is set, or both. Since shape 1 and shape 2 both belong to shape 1's control - // group, and shape 3 has the BLOCK_FOUNDATION flag (but not BLOCK_CONSTRUCTION), we should find only - // shape 3 in the result. + // (which also includes shape 2), and requiring that either the BLOCK_FOUNDATION flag is set. + // Since shape 1 and shape 2 both belong to shape 1's control group, + // and shape 3 has the BLOCK_FOUNDATION flag, we should find only shape 3 in the result. SkipControlGroupsRequireFlagObstructionFilter skipGroup1ReqFoundConstr(ent1g1, INVALID_ENTITY, - ICmpObstructionManager::FLAG_BLOCK_FOUNDATION | ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION); + ICmpObstructionManager::FLAG_BLOCK_FOUNDATION); cmp->TestUnitShape(skipGroup1ReqFoundConstr, ent1x, ent1z, fixed::FromInt(10), &out); TS_ASSERT_EQUALS(1U, out.size()); @@ -335,7 +330,7 @@ // yielding an empty result set. SkipControlGroupsRequireFlagObstructionFilter skipGroup1And3ReqFoundConstr(ent1g1, ent3g, - ICmpObstructionManager::FLAG_BLOCK_FOUNDATION | ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION); + ICmpObstructionManager::FLAG_BLOCK_FOUNDATION); cmp->TestUnitShape(skipGroup1And3ReqFoundConstr, ent1x, ent1z, fixed::FromInt(10), &out); TS_ASSERT_EQUALS(0U, out.size()); @@ -535,12 +530,10 @@ ent5z = ent1z; tag_t shape4 = cmp->AddStaticShape(ent4, ent4x, ent4z, ent4a, ent4w, ent4h, - ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION | ICmpObstructionManager::FLAG_BLOCK_MOVEMENT | ICmpObstructionManager::FLAG_MOVING, ent4g1, ent4g2); tag_t shape5 = cmp->AddStaticShape(ent5, ent5x, ent5z, ent5a, ent5w, ent5h, - ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION | ICmpObstructionManager::FLAG_BLOCK_MOVEMENT | ICmpObstructionManager::FLAG_MOVING, ent5g1, ent5g2); Index: source/simulation2/components/tests/test_RangeManager.h =================================================================== --- source/simulation2/components/tests/test_RangeManager.h +++ source/simulation2/components/tests/test_RangeManager.h @@ -94,11 +94,9 @@ virtual std::string CheckFoundation_wrapper(const std::string&, bool) const { return {}; }; virtual bool CheckDuplicateFoundation() const { return {}; }; virtual std::vector GetEntitiesByFlags(ICmpObstructionManager::flags_t) const { return {}; }; - virtual std::vector GetEntitiesBlockingMovement() const { return {}; }; - virtual std::vector GetEntitiesBlockingConstruction() const { return {}; }; + virtual std::vector GetUnitsBlockingMovement() const { return {}; }; virtual std::vector GetEntitiesDeletedUponConstruction() const { return {}; }; virtual void ResolveFoundationCollisions() const {}; - virtual void SetActive(bool) {}; virtual void SetMovingFlag(bool) {}; virtual void SetDisableBlockMovementPathfinding(bool, bool, int32_t) {}; virtual bool GetBlockMovementFlag() const { return {}; };