Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 641 Lines • ▼ Show 20 Lines | private: | ||||
/** | /** | ||||
* Computes the current location of our target entity (plus offset). | * Computes the current location of our target entity (plus offset). | ||||
* Returns false if no target entity or no valid position. | * Returns false if no target entity or no valid position. | ||||
*/ | */ | ||||
bool ComputeTargetPosition(CFixedVector2D& out) const; | bool ComputeTargetPosition(CFixedVector2D& out) const; | ||||
/** | /** | ||||
* Attempts to replace the current path with a straight line to the goal, | * Attempts to replace the current path with a straight line to the target, | ||||
* if this goal is a point, is close enough and the route is not obstructed. | * if it's close enough and the route is not obstructed. | ||||
*/ | */ | ||||
bool TryGoingStraightToGoalPoint(const CFixedVector2D& from); | bool TryGoingStraightToTarget(const CFixedVector2D& from); | ||||
/** | |||||
* Attempts to replace the current path with a straight line to the target | |||||
* entity, if it's close enough and the route is not obstructed. | |||||
*/ | |||||
bool TryGoingStraightToTargetEntity(const CFixedVector2D& from); | |||||
/** | /** | ||||
* Returns whether the target entity has moved more than minDelta since our | * Returns whether the target entity has moved more than minDelta since our | ||||
* last path computations, and we're close enough to it to care. | * last path computations, and we're close enough to it to care. | ||||
*/ | */ | ||||
bool CheckTargetMovement(const CFixedVector2D& from, entity_pos_t minDelta); | bool CheckTargetMovement(const CFixedVector2D& from, entity_pos_t minDelta); | ||||
/** | /** | ||||
Show All 15 Lines | private: | ||||
/** | /** | ||||
* Rotate to face towards the target point, given the current pos | * Rotate to face towards the target point, given the current pos | ||||
*/ | */ | ||||
void FaceTowardsPointFromPos(const CFixedVector2D& pos, entity_pos_t x, entity_pos_t z); | void FaceTowardsPointFromPos(const CFixedVector2D& pos, entity_pos_t x, entity_pos_t z); | ||||
/** | /** | ||||
* Returns an appropriate obstruction filter for use with path requests. | * Returns an appropriate obstruction filter for use with path requests. | ||||
* noTarget is true only when used inside tryGoingStraightToTargetEntity, | * noTarget is true only when used inside TryGoingStraightToTarget, | ||||
* in which case we do not want the target obstruction otherwise it would always fail | * in which case we do not want the target obstruction otherwise it would always fail | ||||
*/ | */ | ||||
ControlGroupMovementObstructionFilter GetObstructionFilter(bool noTarget = false) const; | ControlGroupMovementObstructionFilter GetObstructionFilter(bool noTarget = false) const; | ||||
/** | /** | ||||
* Start moving to the given goal, from our current position 'from'. | * Start moving to the given goal, from our current position 'from'. | ||||
* Might go in a straight line immediately, or might start an asynchronous | * Might go in a straight line immediately, or might start an asynchronous | ||||
* path request. | * path request. | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | void CCmpUnitMotion::Move(fixed dt) | ||||
CFixedVector2D pos = initialPos; | CFixedVector2D pos = initialPos; | ||||
// If we're chasing a potentially-moving unit and are currently close | // If we're chasing a potentially-moving unit and are currently close | ||||
// enough to its current position, and we can head in a straight line | // enough to its current position, and we can head in a straight line | ||||
// to it, then throw away our current path and go straight to it | // to it, then throw away our current path and go straight to it | ||||
if (m_PathState == PATHSTATE_FOLLOWING || | if (m_PathState == PATHSTATE_FOLLOWING || | ||||
m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT || | m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT || | ||||
m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | ||||
TryGoingStraightToTargetEntity(initialPos); | TryGoingStraightToTarget(initialPos); | ||||
bool wasObstructed = PerformMove(dt, m_ShortPath, m_LongPath, pos); | bool wasObstructed = PerformMove(dt, m_ShortPath, m_LongPath, pos); | ||||
// Update our speed over this turn so that the visual actor shows the correct animation. | // Update our speed over this turn so that the visual actor shows the correct animation. | ||||
if (pos == initialPos) | if (pos == initialPos) | ||||
UpdateMovementState(fixed::Zero()); | UpdateMovementState(fixed::Zero()); | ||||
else | else | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 217 Lines • ▼ Show 20 Lines | if (m_MoveRequest.m_Type != MoveRequest::ENTITY) | ||||
return true; | return true; | ||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); | CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); | ||||
return cmpPosition && cmpPosition->IsInWorld(); | return cmpPosition && cmpPosition->IsInWorld(); | ||||
} | } | ||||
bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const | bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) const | ||||
{ | { | ||||
if (m_MoveRequest.m_Entity == INVALID_ENTITY) | if (m_MoveRequest.m_Type == MoveRequest::POINT) | ||||
return false; | { | ||||
out = CFixedVector2D(m_MoveRequest.m_Position.X, m_MoveRequest.m_Position.Y); | |||||
return true; | |||||
} | |||||
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); | CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_MoveRequest.m_Entity); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
return false; | return false; | ||||
if (m_MoveRequest.m_Type == MoveRequest::OFFSET) | if (m_MoveRequest.m_Type == MoveRequest::OFFSET) | ||||
{ | { | ||||
// There is an offset, so compute it relative to orientation | // There is an offset, so compute it relative to orientation | ||||
entity_angle_t angle = cmpPosition->GetRotation().Y; | entity_angle_t angle = cmpPosition->GetRotation().Y; | ||||
CFixedVector2D offset = m_MoveRequest.GetOffset().Rotate(angle); | CFixedVector2D offset = m_MoveRequest.GetOffset().Rotate(angle); | ||||
out = cmpPosition->GetPosition2D() + offset; | out = cmpPosition->GetPosition2D() + offset; | ||||
} | } | ||||
else | else | ||||
out = cmpPosition->GetPosition2D(); | out = cmpPosition->GetPosition2D(); | ||||
return true; | return true; | ||||
} | } | ||||
bool CCmpUnitMotion::TryGoingStraightToGoalPoint(const CFixedVector2D& from) | bool CCmpUnitMotion::TryGoingStraightToTarget(const CFixedVector2D& from) | ||||
{ | |||||
// Make sure the goal is a point (and not a point-like target like a formation controller) | |||||
if (m_MoveRequest.m_Type != MoveRequest::POINT || | |||||
m_MoveRequest.m_MinRange > fixed::Zero()) | |||||
return false; | |||||
// Fail if the goal is too far away | |||||
CFixedVector2D goalPos(m_FinalGoal.x, m_FinalGoal.z); | |||||
if ((goalPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) | |||||
return false; | |||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | |||||
if (!cmpPathfinder) | |||||
return false; | |||||
// Check if there's any collisions on that route | |||||
if (!cmpPathfinder->CheckMovement(GetObstructionFilter(), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass)) | |||||
return false; | |||||
// That route is okay, so update our path | |||||
m_LongPath.m_Waypoints.clear(); | |||||
m_ShortPath.m_Waypoints.clear(); | |||||
m_ShortPath.m_Waypoints.emplace_back(Waypoint{ goalPos.X, goalPos.Y }); | |||||
return true; | |||||
} | |||||
bool CCmpUnitMotion::TryGoingStraightToTargetEntity(const CFixedVector2D& from) | |||||
{ | { | ||||
CFixedVector2D targetPos; | CFixedVector2D targetPos; | ||||
if (!ComputeTargetPosition(targetPos)) | if (!ComputeTargetPosition(targetPos)) | ||||
return false; | return false; | ||||
// Fail if the target is too far away | // Fail if the target is too far away | ||||
if ((targetPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) | if ((targetPos - from).CompareLength(DIRECT_PATH_RANGE) > 0) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | #if DISABLE_PATHFINDER | ||||
m_LongPath.m_Waypoints.clear(); | m_LongPath.m_Waypoints.clear(); | ||||
m_ShortPath.m_Waypoints.clear(); | m_ShortPath.m_Waypoints.clear(); | ||||
m_ShortPath.m_Waypoints.emplace_back(Waypoint{ goalPos.X, goalPos.Y }); | m_ShortPath.m_Waypoints.emplace_back(Waypoint{ goalPos.X, goalPos.Y }); | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
return; | return; | ||||
} | } | ||||
#endif | #endif | ||||
// If we're aiming at a target entity and it's close and we can reach | // If the target is close and we can reach it in a straight line, | ||||
// it in a straight line, then we'll just go along the straight line | // then we'll just go along the straight line instead of computing a path. | ||||
// instead of computing a path. | if (TryGoingStraightToTarget(from)) | ||||
if (TryGoingStraightToTargetEntity(from)) | |||||
{ | |||||
m_PathState = PATHSTATE_FOLLOWING; | |||||
return; | |||||
} | |||||
// Same thing applies to non-entity points | |||||
if (TryGoingStraightToGoalPoint(from)) | |||||
{ | { | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
return; | return; | ||||
} | } | ||||
// Otherwise we need to compute a path. | // Otherwise we need to compute a path. | ||||
// If it's close then just do a short path, not a long path | // If it's close then just do a short path, not a long path | ||||
▲ Show 20 Lines • Show All 363 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator