Index: source/simulation2/components/CCmpUnitMotion.cpp =================================================================== --- source/simulation2/components/CCmpUnitMotion.cpp +++ source/simulation2/components/CCmpUnitMotion.cpp @@ -201,8 +201,6 @@ // Motion planning u8 m_Tries; // how many tries we've done to get to our current Final Goal. - PathGoal m_FinalGoal; - static std::string GetSchema() { return @@ -259,8 +257,6 @@ m_Tries = 0; - m_FinalGoal.type = PathGoal::POINT; - m_DebugOverlayEnabled = false; } @@ -294,8 +290,6 @@ SerializeVector()(serialize, "long path", m_LongPath.m_Waypoints); SerializeVector()(serialize, "short path", m_ShortPath.m_Waypoints); - - SerializeGoal()(serialize, "goal", m_FinalGoal); } virtual void Serialize(ISerializer& serialize) @@ -459,7 +453,11 @@ { CmpPtr cmpPosition(GetEntityHandle()); if (cmpPosition && cmpPosition->IsInWorld()) - FaceTowardsPointFromPos(cmpPosition->GetPosition2D(), m_FinalGoal.x, m_FinalGoal.z); + { + CFixedVector2D targetPos; + if (ComputeTargetPosition(targetPos)) + FaceTowardsPointFromPos(cmpPosition->GetPosition2D(), targetPos.X, targetPos.Y); + } } m_MoveRequest = MoveRequest(); @@ -542,8 +540,6 @@ m_CurSpeed = speed; } - bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target); - /** * Handle the result of an asynchronous path query. */ @@ -582,7 +578,11 @@ * Computes the current location of our target entity (plus offset). * Returns false if no target entity or no valid position. */ - bool ComputeTargetPosition(CFixedVector2D& out) const; + bool ComputeTargetPosition(CFixedVector2D& out, const MoveRequest& moveRequest) const; + bool ComputeTargetPosition(CFixedVector2D& out) const + { + return ComputeTargetPosition(out, m_MoveRequest); + } /** * Attempts to replace the current path with a straight line to the goal, @@ -599,7 +599,7 @@ /** * Returns whether our we need to recompute a path to reach our target. */ - bool PathingUpdateNeeded(const CFixedVector2D& from); + bool PathingUpdateNeeded() const; /** * Returns whether we are close enough to the target to assume it's a good enough @@ -689,7 +689,11 @@ // (via the short pathfinder), so if we're stuck and the user clicks // close enough to the unit then we can probably get unstuck if (m_LongPath.m_Waypoints.empty()) - m_LongPath.m_Waypoints.emplace_back(Waypoint{ m_FinalGoal.x, m_FinalGoal.z }); + { + CFixedVector2D targetPos; + if (ComputeTargetPosition(targetPos)) + m_LongPath.m_Waypoints.emplace_back(Waypoint{ targetPos.X, targetPos.Y }); + } m_PathState = PATHSTATE_FOLLOWING; } @@ -728,8 +732,9 @@ return; } - ComputeGoal(m_FinalGoal, m_MoveRequest); - RequestLongPath(pos, m_FinalGoal); + PathGoal goal; + ComputeGoal(goal, m_MoveRequest); + RequestLongPath(pos, goal); m_PathState = PATHSTATE_WAITING_REQUESTING_LONG; return; } @@ -806,7 +811,13 @@ { // We may need to recompute our path sometimes (e.g. if our target moves). // Since we request paths asynchronously anyways, this does not need to be done before moving. - PathingUpdateNeeded(pos); + if (PathingUpdateNeeded()) + { + PathGoal goal; + ComputeGoal(goal, m_MoveRequest); + RequestLongPath(pos, goal); + m_PathState = PATHSTATE_FOLLOWING_REQUESTING_LONG; + } } } @@ -950,7 +961,6 @@ } // If we still have long waypoints, try and compute a short path - // This will get us around units, amongst others. if (!m_LongPath.m_Waypoints.empty()) { PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z }; @@ -958,31 +968,33 @@ m_PathState = PATHSTATE_WAITING_REQUESTING_SHORT; return true; } + // Else, just entirely recompute - ComputeGoal(m_FinalGoal, m_MoveRequest); - BeginPathing(pos, m_FinalGoal); + PathGoal goal; + ComputeGoal(goal, m_MoveRequest); + BeginPathing(pos, goal); // potential TODO: We could switch the short-range pathfinder for something else entirely. return true; } -bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const +bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out, const MoveRequest& moveRequest) const { - if (m_MoveRequest.m_Type == MoveRequest::POINT) + if (moveRequest.m_Type == MoveRequest::POINT) { - out = CFixedVector2D(m_MoveRequest.m_Position.X, m_MoveRequest.m_Position.Y); + out = moveRequest.m_Position; return true; } - CmpPtr cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); + CmpPtr cmpPosition(GetSimContext(), moveRequest.m_Entity); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; - if (m_MoveRequest.m_Type == MoveRequest::OFFSET) + if (moveRequest.m_Type == MoveRequest::OFFSET) { // There is an offset, so compute it relative to orientation entity_angle_t angle = cmpPosition->GetRotation().Y; - CFixedVector2D offset = m_MoveRequest.GetOffset().Rotate(angle); + CFixedVector2D offset = moveRequest.GetOffset().Rotate(angle); out = cmpPosition->GetPosition2D() + offset; } else @@ -997,7 +1009,8 @@ return false; // Fail if the goal is too far away - CFixedVector2D goalPos(m_FinalGoal.x, m_FinalGoal.z); + CFixedVector2D goalPos; + ComputeTargetPosition(goalPos); if ((goalPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) return false; @@ -1032,7 +1045,8 @@ return false; // Move the goal to match the target entity's new position - PathGoal goal = m_FinalGoal; + PathGoal goal; + ComputeGoal(goal, m_MoveRequest); goal.x = targetPos.X; goal.z = targetPos.Y; // (we ignore changes to the target's rotation, since only buildings are @@ -1046,7 +1060,6 @@ return false; // That route is okay, so update our path - m_FinalGoal = goal; m_LongPath.m_Waypoints.clear(); m_ShortPath.m_Waypoints.clear(); m_ShortPath.m_Waypoints.emplace_back(Waypoint{ goalPos.X, goalPos.Y }); @@ -1054,7 +1067,7 @@ return true; } -bool CCmpUnitMotion::PathingUpdateNeeded(const CFixedVector2D& from) +bool CCmpUnitMotion::PathingUpdateNeeded() const { if (m_MoveRequest.m_Type == MoveRequest::NONE) return false; @@ -1103,19 +1116,19 @@ if (distance >= m_MoveRequest.m_MinRange && (distance <= m_MoveRequest.m_MaxRange || m_MoveRequest.m_MaxRange < fixed::Zero())) return false; - // We won't be in-range when we reach our final waypoint : recompute our path. - m_FinalGoal.x = estimatedTargetShape.x; - m_FinalGoal.z = estimatedTargetShape.z; - RequestLongPath(from, m_FinalGoal); - m_PathState = PATHSTATE_FOLLOWING_REQUESTING_LONG; - + return true; } bool CCmpUnitMotion::CloseEnoughFromDestinationToStop(const CFixedVector2D& from) const { - if (m_MoveRequest.m_Type != MoveRequest::POINT || m_FinalGoal.DistanceToPoint(from) > SHORT_PATH_GOAL_RADIUS) + if (m_MoveRequest.m_Type != MoveRequest::POINT) return false; - return true; + + CFixedVector2D targetPos; + if (!ComputeTargetPosition(targetPos)) + return true; // We failed to compute a position so we'll stop anyways. + + return (from - targetPos).CompareLength(SHORT_PATH_GOAL_RADIUS) <= 0; } bool CCmpUnitMotion::PathIsShort(const WaypointPath& path, const CFixedVector2D& from, entity_pos_t minDistance) const @@ -1193,7 +1206,7 @@ CFixedVector2D pos = cmpPosition->GetPosition2D(); CFixedVector2D targetPosition; - if (!ComputeTargetPosition(targetPosition)) + if (!ComputeTargetPosition(targetPosition, moveRequest)) return false; ICmpObstructionManager::ObstructionSquare targetObstruction; @@ -1291,7 +1304,6 @@ void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) { - // reset our state for sanity. m_ExpectedPathTicket = 0; m_PathState = PATHSTATE_NONE; @@ -1336,7 +1348,7 @@ // where we are going if the short-range pathfinder returns // an aborted path. m_LongPath.m_Waypoints.clear(); - CFixedVector2D target = m_FinalGoal.NearestPointOnGoal(from); + CFixedVector2D target = goal.NearestPointOnGoal(from); m_LongPath.m_Waypoints.emplace_back(Waypoint{ target.X, target.Y }); m_PathState = PATHSTATE_WAITING_REQUESTING_SHORT; RequestShortPath(from, goal, true); @@ -1381,23 +1393,23 @@ } bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) -{ - return MoveToPointRange(x, z, minRange, maxRange, INVALID_ENTITY); -} - -bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target) { PROFILE("MoveToPointRange"); + MoveRequest moveRequest(CFixedVector2D(x, z), minRange, maxRange); + + PathGoal goal; + if (!ComputeGoal(goal, moveRequest)) + return false; + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; - m_MoveRequest = MoveRequest(CFixedVector2D(x, z), minRange, maxRange); - ComputeGoal(m_FinalGoal, m_MoveRequest); + m_MoveRequest = moveRequest; m_Tries = 0; - BeginPathing(cmpPosition->GetPosition2D(), m_FinalGoal); + BeginPathing(cmpPosition->GetPosition2D(), goal); return true; } @@ -1406,36 +1418,45 @@ { PROFILE("MoveToTargetRange"); + MoveRequest moveRequest(target, minRange, maxRange); + + PathGoal goal; + + if (!ComputeGoal(goal, moveRequest)) + return false; + CmpPtr cmpPosition(GetEntityHandle()); if (!cmpPosition || !cmpPosition->IsInWorld()) return false; - m_MoveRequest = MoveRequest(target, minRange, maxRange); - ComputeGoal(m_FinalGoal, m_MoveRequest); + m_MoveRequest = moveRequest; m_Tries = 0; - BeginPathing(cmpPosition->GetPosition2D(), m_FinalGoal); + BeginPathing(cmpPosition->GetPosition2D(), goal); return true; } void CCmpUnitMotion::MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) { + MoveRequest moveRequest(target, CFixedVector2D(x, z)); + + PathGoal goal; + if (!ComputeGoal(goal, moveRequest)) + return; + CmpPtr cmpPosition(GetSimContext(), target); if (!cmpPosition || !cmpPosition->IsInWorld()) return; - m_MoveRequest = MoveRequest(target, CFixedVector2D(x, z)); - ComputeGoal(m_FinalGoal, m_MoveRequest); + m_MoveRequest = moveRequest; m_Tries = 0; - BeginPathing(cmpPosition->GetPosition2D(), m_FinalGoal); + BeginPathing(cmpPosition->GetPosition2D(), goal); } - - void CCmpUnitMotion::RenderPath(const WaypointPath& path, std::vector& lines, CColor color) { bool floating = false;