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:
parent
eee977fd7d
commit
017cb504ee
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user