Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 557 Lines • ▼ Show 20 Lines | private: | ||||
{ | { | ||||
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 MoveFailed() | void MoveFailed() | ||||
{ | { | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
CMessageMotionChanged msg(true); | CMessageMotionChanged msg(true); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
} | } | ||||
void MoveSucceeded() | void MoveSucceeded() | ||||
{ | { | ||||
CMessageMotionChanged msg(false); | |||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | |||||
} | |||||
/** | |||||
* Update other components on our speed. | |||||
* This doesn't use messages for efficiency. | |||||
* This should only be called when speed changes. | |||||
*/ | |||||
void UpdateMovementState(entity_pos_t speed) | |||||
{ | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | ||||
// Moved last turn, didn't this turn. | |||||
if (speed == fixed::Zero() && m_CurSpeed > fixed::Zero()) | |||||
{ | |||||
if (cmpObstruction) | if (cmpObstruction) | ||||
cmpObstruction->SetMovingFlag(false); | cmpObstruction->SetMovingFlag(false); | ||||
} | |||||
// Moved this turn, didn't last turn | |||||
else if (speed > fixed::Zero() && m_CurSpeed == fixed::Zero()) | |||||
{ | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(true); | |||||
} | |||||
CMessageMotionChanged msg(false); | m_CurSpeed = speed; | ||||
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. | ||||
*/ | */ | ||||
void PathResult(u32 ticket, const WaypointPath& path); | void PathResult(u32 ticket, const WaypointPath& path); | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | private: | ||||
void RenderSubmit(SceneCollector& collector); | void RenderSubmit(SceneCollector& collector); | ||||
}; | }; | ||||
REGISTER_COMPONENT_TYPE(UnitMotion) | REGISTER_COMPONENT_TYPE(UnitMotion) | ||||
void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | ||||
{ | { | ||||
// reset our state for sanity. | |||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
// Ignore obsolete path requests | // Ignore obsolete path requests | ||||
if (ticket != m_ExpectedPathTicket) | if (ticket != m_ExpectedPathTicket) | ||||
return; | return; | ||||
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()); | ||||
Show All 16 Lines | if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) | ||||
// 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 }); | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(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()) | ||||
{ | { | ||||
Show All 30 Lines | if (m_ShortPath.m_Waypoints.empty()) | ||||
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; | ||||
m_PathState = PATHSTATE_FOLLOWING; | m_PathState = PATHSTATE_FOLLOWING; | ||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(true); | |||||
} | } | ||||
else | else | ||||
LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); | LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); | ||||
} | } | ||||
void CCmpUnitMotion::Move(fixed dt) | void CCmpUnitMotion::Move(fixed dt) | ||||
{ | { | ||||
PROFILE("Move"); | PROFILE("Move"); | ||||
if (m_State == STATE_STOPPING) | if (m_State == STATE_STOPPING) | ||||
{ | { | ||||
m_State = STATE_IDLE; | m_State = STATE_IDLE; | ||||
MoveSucceeded(); | MoveSucceeded(); | ||||
m_CurSpeed = fixed::Zero(); | m_CurSpeed = fixed::Zero(); | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
return; | return; | ||||
} | } | ||||
if (m_State == STATE_IDLE) | if (m_State == STATE_IDLE) | ||||
return; | return; | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | while (timeLeft > zero) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 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) | ||||
m_CurSpeed = fixed::Zero(); | UpdateMovementState(fixed::Zero()); | ||||
else | else | ||||
{ | { | ||||
// Update the Position component after our movement (if we actually moved anywhere) | // Update the Position component after our movement (if we actually moved anywhere) | ||||
CFixedVector2D offset = pos - initialPos; | CFixedVector2D offset = pos - initialPos; | ||||
// Face towards the target | // Face towards the target | ||||
entity_angle_t angle = atan2_approx(offset.X, offset.Y); | entity_angle_t angle = atan2_approx(offset.X, offset.Y); | ||||
cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle); | cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle); | ||||
// Calculate the mean speed over this past turn. | // Calculate the mean speed over this past turn. | ||||
m_CurSpeed = cmpPosition->GetDistanceTravelled() / dt; | UpdateMovementState(offset.Length() / dt); | ||||
} | } | ||||
if (wasObstructed) | if (wasObstructed) | ||||
{ | { | ||||
// Oops, we hit something (very likely another unit). | // Oops, we hit something (very likely another unit). | ||||
// This is when we might easily get stuck wrongly. | // This is when we might easily get stuck wrongly. | ||||
// check if we've arrived. | // check if we've arrived. | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty()) | ||||
if (IsFormationMember()) | if (IsFormationMember()) | ||||
{ | { | ||||
// We've reached our assigned position. If the controller | // We've reached our assigned position. If the controller | ||||
// is idle, send a notification in case it should disband, | // is idle, send a notification in case it should disband, | ||||
// otherwise continue following the formation next turn. | // otherwise continue following the formation next turn. | ||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | ||||
if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) | ||||
{ | { | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
CMessageMotionChanged msg(false); | CMessageMotionChanged msg(false); | ||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); | ||||
} | } | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); | ||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity); | ||||
▲ Show 20 Lines • Show All 229 Lines • ▼ Show 20 Lines | |||||
void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) | void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) | ||||
{ | { | ||||
// reset our state for sanity. | // reset our state for sanity. | ||||
m_ExpectedPathTicket = 0; | m_ExpectedPathTicket = 0; | ||||
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); | |||||
if (cmpObstruction) | |||||
cmpObstruction->SetMovingFlag(false); | |||||
m_PathState = PATHSTATE_NONE; | m_PathState = PATHSTATE_NONE; | ||||
#if DISABLE_PATHFINDER | #if DISABLE_PATHFINDER | ||||
{ | { | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); | CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); | ||||
CFixedVector2D goalPos = m_FinalGoal.NearestPointOnGoal(from); | CFixedVector2D goalPos = m_FinalGoal.NearestPointOnGoal(from); | ||||
m_LongPath.m_Waypoints.clear(); | m_LongPath.m_Waypoints.clear(); | ||||
m_ShortPath.m_Waypoints.clear(); | m_ShortPath.m_Waypoints.clear(); | ||||
▲ Show 20 Lines • Show All 383 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator