From 69d3e76fd2bc207d3906735ca0f193b715f52530 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sun, 30 Jun 2019 19:00:27 +0000 Subject: [PATCH] Unit Motion - Stop when targets have an invalid position. Previously, unitMotion had no code that checked particularly if the target was still in the world. When the target moved out of the world, unitMotion would follow the path to its last known position, then send a "MoveSucceeded" message once there. Following 98f609df1d, this message was no longer sent. Thus unit would follow their path to its last waypoint and stay there, unable to carry on or finish the order. UnitMotion now explcitly sends a "MoveFailed" message. This still changes behaviour from A23, requiring further revisions to UnitAI (see D1992 for one such case). Minohaka tested an earlier version of this change (which incorporated D1992) and accepted it. Differential Revision: https://code.wildfiregames.com/D1979 This was SVN commit r22415. --- .../simulation2/components/CCmpUnitMotion.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index 492d4a8662..169d584d55 100644 --- a/source/simulation2/components/CCmpUnitMotion.cpp +++ b/source/simulation2/components/CCmpUnitMotion.cpp @@ -633,6 +633,13 @@ private: */ bool ShouldTreatTargetAsCircle(entity_pos_t range, entity_pos_t circleRadius) const; + /** + * Returns true if the target position is valid. False otherwise. + * (this may indicate that the target is e.g. out of the world/dead). + * NB: for code-writing convenience, if we have no target, this returns true. + */ + bool TargetHasValidPosition() const; + /** * Computes the current location of our target entity (plus offset). * Returns false if no target entity or no valid position. @@ -818,6 +825,18 @@ void CCmpUnitMotion::Move(fixed dt) if (PossiblyAtDestination()) MoveSucceeded(); + else if (!TargetHasValidPosition()) + { + // Scrap waypoints - we don't know where to go. + // If the move request remains unchanged and the target again has a valid position later on, + // moving will be resumed. + // Units may want to move to move to the target's last known position, + // but that should be decided by UnitAI (handling MoveFailed), not UnitMotion. + m_LongPath.m_Waypoints.clear(); + m_ShortPath.m_Waypoints.clear(); + + MoveFailed(); + } CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) @@ -1057,6 +1076,15 @@ bool CCmpUnitMotion::HandleObstructedMove() return true; } +bool CCmpUnitMotion::TargetHasValidPosition() const +{ + if (m_MoveRequest.m_Type != MoveRequest::ENTITY) + return true; + + CmpPtr cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); + return cmpPosition && cmpPosition->IsInWorld(); +} + bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const { if (m_MoveRequest.m_Entity == INVALID_ENTITY)