Index: source/simulation2/components/CCmpUnitMotion.cpp =================================================================== --- source/simulation2/components/CCmpUnitMotion.cpp +++ source/simulation2/components/CCmpUnitMotion.cpp @@ -172,7 +172,8 @@ NONE, POINT, ENTITY, - OFFSET + OFFSET, + ROTATE } m_Type = NONE; entity_id_t m_Entity = INVALID_ENTITY; CFixedVector2D m_Position; @@ -185,6 +186,7 @@ MoveRequest(CFixedVector2D pos, entity_pos_t minRange, entity_pos_t maxRange) : m_Type(POINT), m_Position(pos), m_MinRange(minRange), m_MaxRange(maxRange) {}; MoveRequest(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) : m_Type(ENTITY), m_Entity(target), m_MinRange(minRange), m_MaxRange(maxRange) {}; MoveRequest(entity_id_t target, CFixedVector2D offset) : m_Type(OFFSET), m_Entity(target), m_Position(offset) {}; + MoveRequest(CFixedVector2D pos) : m_Type(ROTATE), m_Position(pos) {}; } m_MoveRequest; // If the entity moves, it will do so at m_WalkSpeed * m_SpeedMultiplier. @@ -371,7 +373,7 @@ virtual bool IsMoveRequested() const { - return m_MoveRequest.m_Type != MoveRequest::NONE; + return m_MoveRequest.m_Type != MoveRequest::NONE && m_MoveRequest.m_Type != MoveRequest::ROTATE; } virtual fixed GetSpeedMultiplier() const @@ -465,21 +467,20 @@ */ virtual void StopMoving() { - if (m_FacePointAfterMove) - { - CmpPtr cmpPosition(GetEntityHandle()); - if (cmpPosition && cmpPosition->IsInWorld()) - { - CFixedVector2D targetPos; - if (ComputeTargetPosition(targetPos)) - FaceTowardsPointFromPos(cmpPosition->GetPosition2D(), targetPos.X, targetPos.Y); - } - } - + // Store the old moveRequest so we can compute a rotation target. + MoveRequest moveRequest = m_MoveRequest; m_MoveRequest = MoveRequest(); + m_ExpectedPathTicket.clear(); m_LongPath.m_Waypoints.clear(); m_ShortPath.m_Waypoints.clear(); + + if (m_FacePointAfterMove) + { + CFixedVector2D targetPos; + if (ComputeTargetPosition(targetPos, moveRequest)) + FaceTowardsPoint(targetPos.X, targetPos.Y); + } } virtual entity_pos_t GetUnitClearance() const @@ -623,7 +624,7 @@ * This does not send actually change the position. * @returns true if the move was obstructed. */ - bool PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const; + bool PerformMove(fixed dt, const fixed& turnRate, MoveRequest moveRequest, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const; /** * Update other components on our speed. @@ -671,11 +672,6 @@ bool PathingUpdateNeeded(const CFixedVector2D& from) const; /** - * Rotate to face towards the target point, given the current pos - */ - void FaceTowardsPointFromPos(const CFixedVector2D& pos, entity_pos_t x, entity_pos_t z); - - /** * Returns an appropriate obstruction filter for use with path requests. */ ControlGroupMovementObstructionFilter GetObstructionFilter() const; @@ -738,7 +734,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) { // Ignore obsolete path requests - if (ticket != m_ExpectedPathTicket.m_Ticket || m_MoveRequest.m_Type == MoveRequest::NONE) + if (ticket != m_ExpectedPathTicket.m_Ticket || m_MoveRequest.m_Type == MoveRequest::NONE || m_MoveRequest.m_Type == MoveRequest::ROTATE) return; Ticket::Type ticketType = m_ExpectedPathTicket.m_Type; @@ -866,7 +862,7 @@ // to it, then throw away our current path and go straight to it bool wentStraight = TryGoingStraightToTarget(initialPos); - bool wasObstructed = PerformMove(dt, cmpPosition->GetTurnRate(), m_ShortPath, m_LongPath, pos, angle); + bool wasObstructed = PerformMove(dt, cmpPosition->GetTurnRate(), m_MoveRequest, m_ShortPath, m_LongPath, pos, angle); // Update our speed over this turn so that the visual actor shows the correct animation. if (pos == initialPos) @@ -909,6 +905,9 @@ if (m_MoveRequest.m_Type == MoveRequest::NONE) return false; + if (m_MoveRequest.m_Type == MoveRequest::ROTATE) + return true; + CmpPtr cmpObstructionManager(GetSystemEntity()); ENSURE(cmpObstructionManager); @@ -930,10 +929,10 @@ return false; } -bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const +bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, MoveRequest moveRequest, WaypointPath& shortPath, WaypointPath& longPath, CFixedVector2D& pos, entity_angle_t& angle) const { // If there are no waypoint, behave as though we were obstructed and let HandleObstructedMove handle it. - if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty()) + if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty() && moveRequest.m_Type != MoveRequest::ROTATE) return true; // Wrap the angle to (-Pi, Pi]. @@ -969,17 +968,20 @@ while (timeLeft > zero) { // If we ran out of path, we have to stop. - if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty()) + if (shortPath.m_Waypoints.empty() && longPath.m_Waypoints.empty() && moveRequest.m_Type != MoveRequest::ROTATE) break; CFixedVector2D target; - if (shortPath.m_Waypoints.empty()) + if (!shortPath.m_Waypoints.empty()) + target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z); + else if (!longPath.m_Waypoints.empty()) target = CFixedVector2D(longPath.m_Waypoints.back().x, longPath.m_Waypoints.back().z); else - target = CFixedVector2D(shortPath.m_Waypoints.back().x, shortPath.m_Waypoints.back().z); + target = m_MoveRequest.m_Position; + CFixedVector2D offset = target - pos; - if (turnRate > zero) + if (turnRate > zero && !offset.IsZero()) { fixed maxRotation = turnRate.Multiply(timeLeft); fixed angleDiff = angle - atan2_approx(offset.X, offset.Y); @@ -1006,6 +1008,13 @@ } } + // We are done rotating. + if (moveRequest.m_Type == MoveRequest::ROTATE) + { + moveRequest = MoveRequest(); + break; + } + // Work out how far we can travel in timeLeft. fixed maxdist = maxSpeed.Multiply(timeLeft); @@ -1154,7 +1163,10 @@ bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out, const MoveRequest& moveRequest) const { - if (moveRequest.m_Type == MoveRequest::POINT) + if (moveRequest.m_Type == MoveRequest::NONE) + return false; + + if (moveRequest.m_Type == MoveRequest::POINT || moveRequest.m_Type == MoveRequest::ROTATE) { out = moveRequest.m_Position; return true; @@ -1200,6 +1212,9 @@ bool CCmpUnitMotion::TryGoingStraightToTarget(const CFixedVector2D& from) { + if (m_MoveRequest.m_Type == MoveRequest::ROTATE) + return false; + CFixedVector2D targetPos; if (!ComputeTargetPosition(targetPos)) return false; @@ -1252,7 +1267,7 @@ bool CCmpUnitMotion::PathingUpdateNeeded(const CFixedVector2D& from) const { - if (m_MoveRequest.m_Type == MoveRequest::NONE) + if (m_MoveRequest.m_Type == MoveRequest::NONE || m_MoveRequest.m_Type == MoveRequest::ROTATE) return false; CFixedVector2D targetPos; @@ -1316,27 +1331,8 @@ void CCmpUnitMotion::FaceTowardsPoint(entity_pos_t x, entity_pos_t z) { - CmpPtr cmpPosition(GetEntityHandle()); - if (!cmpPosition || !cmpPosition->IsInWorld()) - return; - - CFixedVector2D pos = cmpPosition->GetPosition2D(); - FaceTowardsPointFromPos(pos, x, z); -} - -void CCmpUnitMotion::FaceTowardsPointFromPos(const CFixedVector2D& pos, entity_pos_t x, entity_pos_t z) -{ CFixedVector2D target(x, z); - CFixedVector2D offset = target - pos; - if (!offset.IsZero()) - { - entity_angle_t angle = atan2_approx(offset.X, offset.Y); - - CmpPtr cmpPosition(GetEntityHandle()); - if (!cmpPosition) - return; - cmpPosition->TurnTo(angle); - } + m_MoveRequest = MoveRequest(target); } ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter() const @@ -1359,7 +1355,7 @@ bool CCmpUnitMotion::ComputeGoal(PathGoal& out, const MoveRequest& moveRequest) const { - if (moveRequest.m_Type == MoveRequest::NONE) + if (moveRequest.m_Type == MoveRequest::NONE || moveRequest.m_Type == MoveRequest::ROTATE) return false; CmpPtr cmpPosition(GetEntityHandle()); @@ -1544,6 +1540,8 @@ bool CCmpUnitMotion::MoveTo(MoveRequest request) { PROFILE("MoveTo"); + if (request.m_Type == MoveRequest::ROTATE) + return true; if (request.m_MinRange == request.m_MaxRange && !request.m_MinRange.IsZero()) LOGWARNING("MaxRange must be larger than MinRange; See CCmpUnitMotion.cpp for more information");