Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 540 Lines • ▼ Show 20 Lines | private: | ||||
bool HasValidPath() const | bool HasValidPath() const | ||||
{ | { | ||||
return m_PathState == PATHSTATE_FOLLOWING | return m_PathState == PATHSTATE_FOLLOWING | ||||
|| m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG | || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG | ||||
|| m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT; | || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT; | ||||
} | } | ||||
void StartFailed() | |||||
{ | |||||
StopMoving(); | |||||
m_State = STATE_IDLE; // don't go through the STOPPING state since we never even started | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
CMessageMotionChanged msg(true, true); | |||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | |||||
} | |||||
void MoveFailed() | void MoveFailed() | ||||
{ | { | ||||
StopMoving(); | StopMoving(); | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
CMessageMotionChanged msg(false, true); | CMessageMotionChanged msg(true); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | |||||
} | |||||
void StartSucceeded() | |||||
{ | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(true); | |||||
m_Moving = true; | |||||
CMessageMotionChanged msg(true, false); | |||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
} | } | ||||
void MoveSucceeded() | void MoveSucceeded() | ||||
{ | { | ||||
m_Moving = false; | m_Moving = false; | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
// No longer moving, so speed is 0. | // No longer moving, so speed is 0. | ||||
m_CurSpeed = fixed::Zero(); | m_CurSpeed = fixed::Zero(); | ||||
CMessageMotionChanged msg(false, false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
} | } | ||||
bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target); | 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. | * Handle the result of an asynchronous path query. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | ||||
m_ExpectedPathTicket = 0; // we don't expect to get this result again | m_ExpectedPathTicket = 0; // we don't expect to get this result again | ||||
// Check that we are still able to do something with that path | // Check that we are still able to do something with that path | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
{ | { | ||||
if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT) | if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT) | ||||
StartFailed(); | MoveFailed(); | ||||
else if (m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | else if (m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | ||||
StopMoving(); | StopMoving(); | ||||
return; | return; | ||||
} | } | ||||
if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | ||||
{ | { | ||||
m_LongPath = path; | m_LongPath = path; | ||||
// If we are following a path, leave the old m_ShortPath so we can carry on following it | // If we are following a path, leave the old m_ShortPath so we can carry on following it | ||||
// until a new short path has been computed | // until a new short path has been computed | ||||
if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG) | if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG) | ||||
m_ShortPath.m_Waypoints.clear(); | m_ShortPath.m_Waypoints.clear(); | ||||
// If there's no waypoints then we couldn't get near the target. | // If there's no waypoints then we couldn't get near the target. | ||||
// Sort of hack: Just try going directly to the goal point instead | // Sort of hack: Just try going directly to the goal point instead | ||||
// (via the short pathfinder), so if we're stuck and the user clicks | // (via the short pathfinder), so if we're stuck and the user clicks | ||||
// close enough to the unit then we can probably get unstuck | // close enough to the unit then we can probably get unstuck | ||||
if (m_LongPath.m_Waypoints.empty()) | if (m_LongPath.m_Waypoints.empty()) | ||||
m_LongPath.m_Waypoints.emplace_back(Waypoint{ m_FinalGoal.x, m_FinalGoal.z }); | m_LongPath.m_Waypoints.emplace_back(Waypoint{ m_FinalGoal.x, m_FinalGoal.z }); | ||||
if (!HasValidPath()) | |||||
StartSucceeded(); | |||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(true); | cmpObstruction->SetMovingFlag(true); | ||||
m_Moving = true; | m_Moving = true; | ||||
} | } | ||||
else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) | ||||
{ | { | ||||
m_ShortPath = path; | m_ShortPath = path; | ||||
// If there's no waypoints then we couldn't get near the target | // If there's no waypoints then we couldn't get near the target | ||||
if (m_ShortPath.m_Waypoints.empty()) | if (m_ShortPath.m_Waypoints.empty()) | ||||
{ | { | ||||
// If we're globally following a long path, try to remove the next waypoint, it might be obstructed | // If we're globally following a long path, try to remove the next waypoint, it might be obstructed | ||||
// If not, and we are not in a formation, retry | // If not, and we are not in a formation, retry | ||||
// unless we are close to our target and we don't have a target entity. | // unless we are close to our target and we don't have a target entity. | ||||
// This makes sure that units don't clump too much when they are not in a formation and tasked to move. | // This makes sure that units don't clump too much when they are not in a formation and tasked to move. | ||||
if (m_LongPath.m_Waypoints.size() > 1) | if (m_LongPath.m_Waypoints.size() > 1) | ||||
m_LongPath.m_Waypoints.pop_back(); | m_LongPath.m_Waypoints.pop_back(); | ||||
else if (IsFormationMember()) | else if (IsFormationMember()) | ||||
{ | { | ||||
m_Moving = false; | m_Moving = false; | ||||
CMessageMotionChanged msg(true, true); | CMessageMotionChanged msg(true); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
return; | return; | ||||
} | } | ||||
CMessageMotionChanged msg(false, false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
return; | return; | ||||
CFixedVector2D pos = cmpPosition->GetPosition2D(); | CFixedVector2D pos = cmpPosition->GetPosition2D(); | ||||
Show All 11 Lines | if (m_ShortPath.m_Waypoints.empty()) | ||||
RequestLongPath(pos, m_FinalGoal); | RequestLongPath(pos, m_FinalGoal); | ||||
m_PathState = PATHSTATE_WAITING_REQUESTING_LONG; | m_PathState = PATHSTATE_WAITING_REQUESTING_LONG; | ||||
return; | return; | ||||
} | } | ||||
// else we could, so reset our number of tries. | // else we could, so reset our number of tries. | ||||
m_Tries = 0; | m_Tries = 0; | ||||
// Now we've got a short path that we can follow | |||||
if (!HasValidPath()) | |||||
StartSucceeded(); | |||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(true); | cmpObstruction->SetMovingFlag(true); | ||||
m_Moving = true; | m_Moving = true; | ||||
} | } | ||||
else | else | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | if (m_PathState == PATHSTATE_FOLLOWING) | ||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity); | CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity); | ||||
if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | ||||
{ | { | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
m_Moving = false; | m_Moving = false; | ||||
CMessageMotionChanged msg(false, false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// check if target was reached in case of a moving target | // check if target was reached in case of a moving target | ||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | ||||
▲ Show 20 Lines • Show All 262 Lines • ▼ Show 20 Lines | #if DISABLE_PATHFINDER | ||||
} | } | ||||
#endif | #endif | ||||
// If we're aiming at a target entity and it's close and we can reach | // If we're aiming at a target entity and it's close and we can reach | ||||
// it in a straight line, then we'll just go along the straight line | // it in a straight line, then we'll just go along the straight line | ||||
// instead of computing a path. | // instead of computing a path. | ||||
if (TryGoingStraightToTargetEntity(from)) | if (TryGoingStraightToTargetEntity(from)) | ||||
{ | { | ||||
if (!HasValidPath()) | |||||
StartSucceeded(); | |||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
return; | return; | ||||
} | } | ||||
// Same thing applies to non-entity points | // Same thing applies to non-entity points | ||||
if (TryGoingStraightToGoalPoint(from)) | if (TryGoingStraightToGoalPoint(from)) | ||||
{ | { | ||||
if (!HasValidPath()) | |||||
StartSucceeded(); | |||||
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 | ||||
// TODO: If it's close on the opposite side of a river then we really | // TODO: If it's close on the opposite side of a river then we really | ||||
▲ Show 20 Lines • Show All 366 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator