Index: source/simulation2/components/CCmpUnitMotion.cpp =================================================================== --- source/simulation2/components/CCmpUnitMotion.cpp +++ source/simulation2/components/CCmpUnitMotion.cpp @@ -717,7 +717,17 @@ /** * Returns an appropriate obstruction filter for use with path requests. */ - ControlGroupMovementObstructionFilter GetObstructionFilter() const; + ControlGroupMovementObstructionFilter GetObstructionFilter() const + { + return ControlGroupMovementObstructionFilter(ShouldAvoidMovingUnits(), GetGroup()); + } + /** + * Filter a specific tag on top of the existing control groups. + */ + SkipTagAndControlGroupObstructionFilter GetObstructionFilter(const ICmpObstructionManager::tag_t& tag) const + { + return SkipTagAndControlGroupObstructionFilter(tag, GetGroup()); + } /** * Decide whether to approximate the given range from a square target as a circle, @@ -1009,6 +1019,14 @@ fixed timeLeft = dt; fixed zero = fixed::Zero(); + ICmpObstructionManager::tag_t specificIgnore; + if (m_MoveRequest.m_Type == MoveRequest::ENTITY) + { + CmpPtr cmpTargetObstruction(GetSimContext(), m_MoveRequest.m_Entity); + if (cmpTargetObstruction) + specificIgnore = cmpTargetObstruction->GetObstruction(); + } + while (timeLeft > zero) { // If we ran out of path, we have to stop. @@ -1057,7 +1075,7 @@ fixed offsetLength = offset.Length(); if (offsetLength <= maxdist) { - if (cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) + if (cmpPathfinder->CheckMovement(GetObstructionFilter(specificIgnore), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) { pos = target; @@ -1083,7 +1101,7 @@ offset.Normalize(maxdist); target = pos + offset; - if (cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) + if (cmpPathfinder->CheckMovement(GetObstructionFilter(specificIgnore), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) pos = target; else return true; @@ -1236,6 +1254,11 @@ if ((out - cmpPosition->GetPosition2D()).RelativeOrientation(tempPos - cmpPosition->GetPosition2D()) >= 0) out = tempPos; } + else if (cmpUnitMotion && cmpUnitMotion->IsMoveRequested() && GetEntityId() > moveRequest.m_Entity) + { + // TODO before merging ideally: need to try and fix fleeing units cf above. Unlikely to be a problem for the alpha + // because animals tend to have lower IDs + } } return true; } @@ -1381,11 +1404,6 @@ } } -ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter() const -{ - return ControlGroupMovementObstructionFilter(ShouldAvoidMovingUnits(), GetGroup()); -} - // The pathfinder cannot go to "rounded rectangles" goals, which are what happens with square targets and a non-null range. // Depending on what the best approximation is, we either pretend the target is a circle or a square. // One needs to be careful that the approximated geometry will be in the range. Index: source/simulation2/components/ICmpObstructionManager.h =================================================================== --- source/simulation2/components/ICmpObstructionManager.h +++ source/simulation2/components/ICmpObstructionManager.h @@ -529,6 +529,33 @@ } }; +/** + * Obstruction test filter that reject shapes in a given control group or with the given tag, + * and rejects shapes that don't block unit movement. + */ +class SkipTagAndControlGroupObstructionFilter : public IObstructionTestFilter +{ + entity_id_t m_Group; + tag_t m_Tag; + +public: + SkipTagAndControlGroupObstructionFilter(tag_t tag, entity_id_t group) : + m_Tag(tag), m_Group(group) + {} + + virtual bool TestShape(tag_t tag, flags_t flags, entity_id_t group, entity_id_t group2) const + { + if (tag.n == m_Tag.n || group == m_Group || (group2 != INVALID_ENTITY && group2 == m_Group)) + return false; + + if (!(flags & ICmpObstructionManager::FLAG_BLOCK_MOVEMENT)) + return false; + + return true; + } +}; + + /** * Obstruction test filter that will test only against shapes that: * - do not have the specified tag