1
0
forked from 0ad/0ad

Drop an indentation level in UnitMotion.

This will simplify later changes.

Differential Revision: https://code.wildfiregames.com/D1893
This was SVN commit r22360.
This commit is contained in:
wraitii 2019-06-10 17:15:27 +00:00
parent eee977fd7d
commit 017cb504ee

View File

@ -792,24 +792,25 @@ void CCmpUnitMotion::Move(fixed dt)
if (m_State == STATE_IDLE)
return;
switch (m_PathState)
{
case PATHSTATE_NONE:
{
// If we're not pathing, do nothing
if (m_PathState == PATHSTATE_NONE ||
m_PathState == PATHSTATE_WAITING_REQUESTING_LONG ||
m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT)
return;
}
case PATHSTATE_WAITING_REQUESTING_LONG:
case PATHSTATE_WAITING_REQUESTING_SHORT:
{
// If we're waiting for a path and don't have one yet, do nothing
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return;
}
case PATHSTATE_FOLLOWING:
case PATHSTATE_FOLLOWING_REQUESTING_SHORT:
case PATHSTATE_FOLLOWING_REQUESTING_LONG:
CFixedVector2D initialPos = cmpPosition->GetPosition2D();
// Keep track of the current unit's position during the update
CFixedVector2D pos = initialPos;
bool wasObstructed = false;
if (m_PathState == PATHSTATE_FOLLOWING ||
m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT ||
m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG)
{
// TODO: there's some asymmetry here when units look at other
// units' positions - the result will depend on the order of execution.
@ -820,21 +821,12 @@ void CCmpUnitMotion::Move(fixed dt)
if (!cmpPathfinder)
return;
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
if (!cmpPosition || !cmpPosition->IsInWorld())
return;
CFixedVector2D initialPos = cmpPosition->GetPosition2D();
// 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
// to it, then throw away our current path and go straight to it
if (m_PathState == PATHSTATE_FOLLOWING)
TryGoingStraightToTargetEntity(initialPos);
// Keep track of the current unit's position during the update
CFixedVector2D pos = initialPos;
fixed basicSpeed = m_Speed;
// If in formation, run to keep up; otherwise just walk
if (IsFormationMember())
@ -848,8 +840,6 @@ void CCmpUnitMotion::Move(fixed dt)
fixed maxSpeed = basicSpeed.Multiply(terrainSpeed);
bool wasObstructed = false;
// We want to move (at most) maxSpeed*dt units from pos towards the next waypoint
fixed timeLeft = dt;
@ -911,133 +901,132 @@ void CCmpUnitMotion::Move(fixed dt)
break;
}
}
}
// Update the Position component after our movement (if we actually moved anywhere)
if (pos != initialPos)
// Update the Position component after our movement (if we actually moved anywhere)
if (pos != initialPos)
{
CFixedVector2D offset = pos - initialPos;
// Face towards the target
entity_angle_t angle = atan2_approx(offset.X, offset.Y);
cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle);
// Calculate the mean speed over this past turn.
m_CurSpeed = cmpPosition->GetDistanceTravelled() / dt;
}
if (wasObstructed)
{
// Oops, we hit something (very likely another unit).
// This is when we might easily get stuck wrongly.
// check if we've arrived.
if (CloseEnoughFromDestinationToStop(pos))
{
CFixedVector2D offset = pos - initialPos;
MoveSucceeded();
// Face towards the target
entity_angle_t angle = atan2_approx(offset.X, offset.Y);
cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle);
// Calculate the mean speed over this past turn.
m_CurSpeed = cmpPosition->GetDistanceTravelled() / dt;
}
if (wasObstructed)
{
// Oops, we hit something (very likely another unit).
// This is when we might easily get stuck wrongly.
// check if we've arrived.
if (CloseEnoughFromDestinationToStop(pos))
{
MoveSucceeded();
return;
}
// If we still have long waypoints, try and compute a short path
// This will get us around units, amongst others.
// However in some cases a long waypoint will be in located in the obstruction of
// an idle unit. In that case, we need to scrap that waypoint or we might never be able to reach it.
// I am not sure why this happens but the following code seems to work.
if (!m_LongPath.m_Waypoints.empty())
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (cmpObstructionManager)
{
// create a fake obstruction to represent our waypoint.
ICmpObstructionManager::ObstructionSquare square;
square.hh = m_Clearance;
square.hw = m_Clearance;
square.u = CFixedVector2D(entity_pos_t::FromInt(1),entity_pos_t::FromInt(0));
square.v = CFixedVector2D(entity_pos_t::FromInt(0),entity_pos_t::FromInt(1));
square.x = m_LongPath.m_Waypoints.back().x;
square.z = m_LongPath.m_Waypoints.back().z;
std::vector<entity_id_t> unitOnGoal;
// don't ignore moving units as those might be units like us, ie not really moving.
cmpObstructionManager->GetUnitsOnObstruction(square, unitOnGoal, GetObstructionFilter(), true);
if (!unitOnGoal.empty())
m_LongPath.m_Waypoints.pop_back();
}
if (!m_LongPath.m_Waypoints.empty())
{
PathGoal goal;
if (m_LongPath.m_Waypoints.size() > 1 || m_FinalGoal.DistanceToPoint(pos) > LONG_PATH_MIN_DIST)
goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };
else
{
UpdateFinalGoal();
goal = m_FinalGoal;
m_LongPath.m_Waypoints.clear();
CFixedVector2D target = goal.NearestPointOnGoal(pos);
m_LongPath.m_Waypoints.emplace_back(Waypoint{ target.X, target.Y });
}
RequestShortPath(pos, goal, true);
m_PathState = PATHSTATE_WAITING_REQUESTING_SHORT;
return;
}
}
// Else, just entirely recompute
UpdateFinalGoal();
BeginPathing(pos, m_FinalGoal);
// potential TODO: We could switch the short-range pathfinder for something else entirely.
return;
}
// We successfully moved along our path, until running out of
// waypoints or time.
if (m_PathState == PATHSTATE_FOLLOWING)
// If we still have long waypoints, try and compute a short path
// This will get us around units, amongst others.
// However in some cases a long waypoint will be in located in the obstruction of
// an idle unit. In that case, we need to scrap that waypoint or we might never be able to reach it.
// I am not sure why this happens but the following code seems to work.
if (!m_LongPath.m_Waypoints.empty())
{
// If we're not currently computing any new paths:
if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty())
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
if (cmpObstructionManager)
{
if (IsFormationMember())
{
// We've reached our assigned position. If the controller
// is idle, send a notification in case it should disband,
// otherwise continue following the formation next turn.
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
if (cmpUnitMotion && !cmpUnitMotion->IsMoving())
{
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
if (cmpObstruction)
cmpObstruction->SetMovingFlag(false);
CMessageMotionChanged msg(false);
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
return;
}
}
// create a fake obstruction to represent our waypoint.
ICmpObstructionManager::ObstructionSquare square;
square.hh = m_Clearance;
square.hw = m_Clearance;
square.u = CFixedVector2D(entity_pos_t::FromInt(1),entity_pos_t::FromInt(0));
square.v = CFixedVector2D(entity_pos_t::FromInt(0),entity_pos_t::FromInt(1));
square.x = m_LongPath.m_Waypoints.back().x;
square.z = m_LongPath.m_Waypoints.back().z;
std::vector<entity_id_t> unitOnGoal;
// don't ignore moving units as those might be units like us, ie not really moving.
cmpObstructionManager->GetUnitsOnObstruction(square, unitOnGoal, GetObstructionFilter(), true);
if (!unitOnGoal.empty())
m_LongPath.m_Waypoints.pop_back();
}
if (!m_LongPath.m_Waypoints.empty())
{
PathGoal goal;
if (m_LongPath.m_Waypoints.size() > 1 || m_FinalGoal.DistanceToPoint(pos) > LONG_PATH_MIN_DIST)
goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };
else
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
if (!cmpUnitMotion || cmpObstructionManager->IsInTargetRange(GetEntityId(), m_MoveRequest.m_Entity, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false))
{
m_State = STATE_IDLE;
MoveSucceeded();
UpdateFinalGoal();
goal = m_FinalGoal;
m_LongPath.m_Waypoints.clear();
CFixedVector2D target = goal.NearestPointOnGoal(pos);
m_LongPath.m_Waypoints.emplace_back(Waypoint{ target.X, target.Y });
}
RequestShortPath(pos, goal, true);
m_PathState = PATHSTATE_WAITING_REQUESTING_SHORT;
return;
}
}
// Else, just entirely recompute
UpdateFinalGoal();
BeginPathing(pos, m_FinalGoal);
if (m_FacePointAfterMove)
FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z);
// TODO: if the goal was a square building, we ought to point towards the
// nearest point on the square, not towards its center
}
// potential TODO: We could switch the short-range pathfinder for something else entirely.
return;
}
// We successfully moved along our path, until running out of
// waypoints or time.
if (m_PathState == PATHSTATE_FOLLOWING)
{
// If we're not currently computing any new paths:
if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty())
{
if (IsFormationMember())
{
// We've reached our assigned position. If the controller
// is idle, send a notification in case it should disband,
// otherwise continue following the formation next turn.
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
if (cmpUnitMotion && !cmpUnitMotion->IsMoving())
{
CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());
if (cmpObstruction)
cmpObstruction->SetMovingFlag(false);
CMessageMotionChanged msg(false);
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
}
}
// If we have a target entity, and we're not miles away from the end of
// our current path, and the target moved enough, then recompute our
// whole path
if (IsFormationMember())
CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA_FORMATION);
else
CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA);
{
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
if (!cmpUnitMotion || cmpObstructionManager->IsInTargetRange(GetEntityId(), m_MoveRequest.m_Entity, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false))
{
m_State = STATE_IDLE;
MoveSucceeded();
if (m_FacePointAfterMove)
FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z);
// TODO: if the goal was a square building, we ought to point towards the
// nearest point on the square, not towards its center
}
}
}
}
// If we have a target entity, and we're not miles away from the end of
// our current path, and the target moved enough, then recompute our
// whole path
if (IsFormationMember())
CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA_FORMATION);
else
CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA);
}
}