From 8ace8034a246be26451bdf7cbcfbd7683b23159d Mon Sep 17 00:00:00 2001 From: elexis Date: Mon, 26 Mar 2018 15:18:53 +0000 Subject: [PATCH] Fix mirages (and any other entity that blocks something but not BlockConstruction) blocking foundation construction following 29492badb7 / D21. Clean the code by removing the animal hardcoding in the Foundation component and adding a flag DeleteUponConstruction to the Obstruction component. Have locked gates and upgraded entities equally delete entities when transforming. Add a workaround for trees inside walls on random maps. Reviewed by: temple Differential Revision: https://code.wildfiregames.com/D1415 Refs #4268 This was SVN commit r21624. --- .../public/maps/random/rmgen-common/player.js | 3 ++ .../simulation/components/Foundation.js | 19 +++------ .../mods/public/simulation/components/Gate.js | 15 ++++--- .../components/tests/test_Foundation.js | 3 +- .../public/simulation/helpers/Transform.js | 6 ++- .../templates/special/filter/mirage.xml | 1 + .../templates/special/filter/preview.xml | 1 + .../templates/special/filter/resource.xml | 3 +- .../simulation/templates/template_gaia.xml | 1 + .../templates/template_gaia_flora.xml | 2 + .../templates/template_structure.xml | 1 + .../simulation/templates/template_unit.xml | 1 + .../components/CCmpObstruction.cpp | 42 +++++++------------ .../components/ICmpObstruction.cpp | 4 +- .../simulation2/components/ICmpObstruction.h | 19 +++++---- .../components/ICmpObstructionManager.h | 11 ++--- 16 files changed, 70 insertions(+), 62 deletions(-) diff --git a/binaries/data/mods/public/maps/random/rmgen-common/player.js b/binaries/data/mods/public/maps/random/rmgen-common/player.js index e1abd27040..959d427035 100644 --- a/binaries/data/mods/public/maps/random/rmgen-common/player.js +++ b/binaries/data/mods/public/maps/random/rmgen-common/player.js @@ -122,6 +122,9 @@ function placeStartingWalls(position, playerID, wallType, orientation = BUILDING if (civ != "iber" || g_Map.getSize() <= 128) return; + // TODO: should prevent trees inside walls + // When fixing, remove the DeleteUponConstruction flag from template_gaia_flora.xml + if (wallType == "towers") placePolygonalWall(position, 15, ["entry"], "tower", civ, playerID, orientation, 7); else if (wallType) diff --git a/binaries/data/mods/public/simulation/components/Foundation.js b/binaries/data/mods/public/simulation/components/Foundation.js index 5658d03325..277786c139 100644 --- a/binaries/data/mods/public/simulation/components/Foundation.js +++ b/binaries/data/mods/public/simulation/components/Foundation.js @@ -191,31 +191,22 @@ Foundation.prototype.Build = function(builderEnt, work) if (this.GetBuildProgress() == 1.0) return; - // If there's any units in the way, ask them to move away - // and return early from this method. var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); + // If there are any units in the way, ask them to move away and return early from this method. if (cmpObstruction && cmpObstruction.GetBlockMovementFlag()) { - // Remove all obstructions at the new entity, especially animal corpses - let collisions = cmpObstruction.GetEntityCollisions(); + // Remove animal corpses + for (let ent of cmpObstruction.GetEntitiesDeletedUponConstruction()) + Engine.DestroyEntity(ent); + let collisions = cmpObstruction.GetEntitiesBlockingConstruction(); if (collisions.length) { - var cmpFoundationOwnership = Engine.QueryInterface(this.entity, IID_Ownership); for (var ent of collisions) { var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); if (cmpUnitAI) cmpUnitAI.LeaveFoundation(this.entity); - else - { - // If obstructing fauna is gaia or our own but doesn't have UnitAI, just destroy it - var cmpOwnership = Engine.QueryInterface(ent, IID_Ownership); - var cmpIdentity = Engine.QueryInterface(ent, IID_Identity); - if (cmpOwnership && cmpIdentity && cmpIdentity.HasClass("Animal") - && (cmpOwnership.GetOwner() == 0 || cmpFoundationOwnership && cmpOwnership.GetOwner() == cmpFoundationOwnership.GetOwner())) - Engine.DestroyEntity(ent); - } // TODO: What if an obstruction has no UnitAI? } diff --git a/binaries/data/mods/public/simulation/components/Gate.js b/binaries/data/mods/public/simulation/components/Gate.js index a3aa510839..8d8d0a2eb8 100644 --- a/binaries/data/mods/public/simulation/components/Gate.js +++ b/binaries/data/mods/public/simulation/components/Gate.js @@ -140,14 +140,19 @@ Gate.prototype.IsLocked = function() Gate.prototype.LockGate = function() { this.locked = true; + + // Delete animal corpses to prevent units trying to gather the unreachable entity + let cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); + if (cmpObstruction && cmpObstruction.GetBlockMovementFlag()) + for (let ent of cmpObstruction.GetEntitiesDeletedUponConstruction()) + Engine.DestroyEntity(ent); + // If the door is closed, enable 'block pathfinding' // Else 'block pathfinding' will be enabled the next time the gate close if (!this.opened) { - var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); - if (!cmpObstruction) - return; - cmpObstruction.SetDisableBlockMovementPathfinding(false, false, 0); + if (cmpObstruction) + cmpObstruction.SetDisableBlockMovementPathfinding(false, false, 0); } else this.OperateGate(); @@ -215,7 +220,7 @@ Gate.prototype.CloseGate = function() return; // The gate can't be closed if there are entities colliding with it. - var collisions = cmpObstruction.GetUnitCollisions(); + var collisions = cmpObstruction.GetEntitiesBlockingConstruction(); if (collisions.length) { if (!this.timer) diff --git a/binaries/data/mods/public/simulation/components/tests/test_Foundation.js b/binaries/data/mods/public/simulation/components/tests/test_Foundation.js index 58f5728e13..a5b902d4fe 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_Foundation.js +++ b/binaries/data/mods/public/simulation/components/tests/test_Foundation.js @@ -62,7 +62,8 @@ function testFoundation(...mocks) AddMock(foundationEnt, IID_Obstruction, { "GetBlockMovementFlag": () => true, - "GetEntityCollisions": () => [], + "GetEntitiesBlockingConstruction": () => [], + "GetEntitiesDeletedUponConstruction": () => [], "SetDisableBlockMovementPathfinding": () => {}, }); diff --git a/binaries/data/mods/public/simulation/helpers/Transform.js b/binaries/data/mods/public/simulation/helpers/Transform.js index 05105cabae..c526cf129d 100644 --- a/binaries/data/mods/public/simulation/helpers/Transform.js +++ b/binaries/data/mods/public/simulation/helpers/Transform.js @@ -190,7 +190,11 @@ function ObstructionsBlockingTemplateChange(ent, templateArg) var cmpNewObstruction = Engine.QueryInterface(previewEntity, IID_Obstruction); if (cmpNewObstruction && cmpNewObstruction.GetBlockMovementFlag()) { - let collisions = cmpNewObstruction.GetEntityCollisions(); + // Remove all obstructions at the new entity, especially animal corpses + for (let ent of cmpNewObstruction.GetEntitiesDeletedUponConstruction()) + Engine.DestroyEntity(ent); + + let collisions = cmpNewObstruction.GetEntitiesBlockingConstruction(); if (collisions.length) return DeleteEntityAndReturn(previewEntity, cmpPosition, pos, angle, cmpNewPosition, true); } diff --git a/binaries/data/mods/public/simulation/templates/special/filter/mirage.xml b/binaries/data/mods/public/simulation/templates/special/filter/mirage.xml index 282a96e5dc..ad328e0503 100644 --- a/binaries/data/mods/public/simulation/templates/special/filter/mirage.xml +++ b/binaries/data/mods/public/simulation/templates/special/filter/mirage.xml @@ -17,6 +17,7 @@ false false false + false diff --git a/binaries/data/mods/public/simulation/templates/special/filter/preview.xml b/binaries/data/mods/public/simulation/templates/special/filter/preview.xml index 0c39862255..679f222ea2 100644 --- a/binaries/data/mods/public/simulation/templates/special/filter/preview.xml +++ b/binaries/data/mods/public/simulation/templates/special/filter/preview.xml @@ -13,6 +13,7 @@ (but can still be used for testing this entity for collisions against others) --> false + false diff --git a/binaries/data/mods/public/simulation/templates/special/filter/resource.xml b/binaries/data/mods/public/simulation/templates/special/filter/resource.xml index ee627484e1..5d1353c0b4 100644 --- a/binaries/data/mods/public/simulation/templates/special/filter/resource.xml +++ b/binaries/data/mods/public/simulation/templates/special/filter/resource.xml @@ -14,7 +14,8 @@ false false false - false + true + true false false diff --git a/binaries/data/mods/public/simulation/templates/template_gaia.xml b/binaries/data/mods/public/simulation/templates/template_gaia.xml index 050ceff6d7..8e59f473b3 100644 --- a/binaries/data/mods/public/simulation/templates/template_gaia.xml +++ b/binaries/data/mods/public/simulation/templates/template_gaia.xml @@ -14,6 +14,7 @@ true false false + false diff --git a/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml b/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml index ad62a050fd..a368a826d3 100644 --- a/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml +++ b/binaries/data/mods/public/simulation/templates/template_gaia_flora.xml @@ -10,6 +10,8 @@ + + true false diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml index 21add38784..2ec7a22303 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure.xml @@ -78,6 +78,7 @@ true false false + false diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index 9c29b99f55..dbd5f0d07b 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit.xml @@ -63,6 +63,7 @@ true false false + false diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp index 5bd4334160..2522248a3c 100644 --- a/source/simulation2/components/CCmpObstruction.cpp +++ b/source/simulation2/components/CCmpObstruction.cpp @@ -168,6 +168,9 @@ public: "" "" "" + "" + "" + "" "" "" "" @@ -195,6 +198,8 @@ public: 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; m_Flags = m_TemplateFlags; if (paramNode.GetChild("DisableBlockMovement").ToBool()) @@ -615,7 +620,7 @@ public: return !cmpObstructionManager->TestStaticShape(filter, pos.X, pos.Y, cmpPosition->GetRotation().Y, m_Size0, m_Size1, NULL ); } - virtual std::vector GetUnitCollisions() const + virtual std::vector GetEntitiesByFlags(flags_t flags) const { std::vector ret; @@ -623,36 +628,11 @@ public: if (!cmpObstructionManager) return ret; // error - // There are four 'block' flags: construction, foundation, movement, - // and pathfinding. Structures have all of these flags, while most units - // block only movement and construction. - flags_t flags = ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION; - // Ignore collisions within the same control group, or with other shapes that don't match the filter. // Note that, since the control group for each entity defaults to the entity's ID, this is typically // equivalent to only ignoring the entity's own shape and other shapes that don't match the filter. SkipControlGroupsRequireFlagObstructionFilter filter(false, m_ControlGroup, m_ControlGroup2, flags); - ICmpObstructionManager::ObstructionSquare square; - if (!GetObstructionSquare(square)) - return ret; // error - - cmpObstructionManager->GetUnitsOnObstruction(square, ret, filter); - - return ret; - } - - virtual std::vector GetEntityCollisions() const - { - std::vector ret; - - CmpPtr cmpObstructionManager(GetSystemEntity()); - if (!cmpObstructionManager) - return ret; // error - - // Ignore collisions within the same control group. - SkipControlGroupsRequireFlagObstructionFilter filter(true, m_ControlGroup, m_ControlGroup2, 0); - ICmpObstructionManager::ObstructionSquare square; if (!GetObstructionSquare(square)) return ret; // error @@ -663,6 +643,16 @@ public: return ret; } + virtual std::vector GetEntitiesBlockingConstruction() const + { + return GetEntitiesByFlags(ICmpObstructionManager::FLAG_BLOCK_CONSTRUCTION); + } + + virtual std::vector GetEntitiesDeletedUponConstruction() const + { + return GetEntitiesByFlags(ICmpObstructionManager::FLAG_DELETE_UPON_CONSTRUCTION); + } + virtual void SetMovingFlag(bool enabled) { m_Moving = enabled; diff --git a/source/simulation2/components/ICmpObstruction.cpp b/source/simulation2/components/ICmpObstruction.cpp index b63a355b5c..2e8fceab11 100644 --- a/source/simulation2/components/ICmpObstruction.cpp +++ b/source/simulation2/components/ICmpObstruction.cpp @@ -50,8 +50,8 @@ DEFINE_INTERFACE_METHOD_CONST_0("GetUnitRadius", entity_pos_t, ICmpObstruction, 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("GetUnitCollisions", std::vector, ICmpObstruction, GetUnitCollisions) -DEFINE_INTERFACE_METHOD_CONST_0("GetEntityCollisions", std::vector, ICmpObstruction, GetEntityCollisions) +DEFINE_INTERFACE_METHOD_CONST_0("GetEntitiesBlockingConstruction", std::vector, ICmpObstruction, GetEntitiesBlockingConstruction) +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) diff --git a/source/simulation2/components/ICmpObstruction.h b/source/simulation2/components/ICmpObstruction.h index 12fb0a19a1..3b197e144e 100644 --- a/source/simulation2/components/ICmpObstruction.h +++ b/source/simulation2/components/ICmpObstruction.h @@ -89,17 +89,22 @@ public: virtual bool CheckDuplicateFoundation() const = 0; /** - * Returns a list of units that are colliding with this entity. - * @return vector of blocking units + * Returns a list of entities that have an obstruction matching the given flag and intersect the current obstruction. + * @return vector of blocking entities */ - virtual std::vector GetUnitCollisions() const = 0; + virtual std::vector GetEntitiesByFlags(ICmpObstructionManager::flags_t flags) const = 0; /** - * Returns a list of entities that are colliding with this entity (excluding self). - * This can be used to retrieve units with static obstructions, such as animal corpses. - * @return vector of blocking units + * Returns a list of entities that are blocking construction of a foundation. + * @return vector of blocking entities */ - virtual std::vector GetEntityCollisions() const = 0; + virtual std::vector GetEntitiesBlockingConstruction() const = 0; + + /** + * Returns a list of entities that shall be deleted when a construction on this obstruction starts, + * for example sheep carcasses. + */ + virtual std::vector GetEntitiesDeletedUponConstruction() const = 0; /** * Detects collisions between foundation-blocking entities and diff --git a/source/simulation2/components/ICmpObstructionManager.h b/source/simulation2/components/ICmpObstructionManager.h index b6b7bcdba1..ad51d585d8 100644 --- a/source/simulation2/components/ICmpObstructionManager.h +++ b/source/simulation2/components/ICmpObstructionManager.h @@ -71,11 +71,12 @@ public: */ enum EFlags { - 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_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 }; /**