Unit Motion - Improve handling of obstructed paths.

Units right now try going to their next long waypoint using the
short-range pathfinder. This works, but it tends to leads to units
clumping together when shuttling for example.

By switching to short paths earlier, and by scrapping the long waypoints
when doing so, we can make movement more natural until we have unit
pushing.

Some cleanup in how the short-path domain range gets handled, and
increase the max-range by one tile to improve rare cases.

Differential Revision: https://code.wildfiregames.com/D2095
This was SVN commit r22507.
This commit is contained in:
wraitii 2019-07-18 20:00:38 +00:00
parent b807c39e6a
commit 6fc2114b58

View File

@ -56,7 +56,7 @@ static const entity_pos_t WAYPOINT_ADVANCE_MAX = entity_pos_t::FromInt(TERRAIN_T
* smaller ranges might miss some legitimate routes around large obstacles.)
*/
static const entity_pos_t SHORT_PATH_MIN_SEARCH_RANGE = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*2);
static const entity_pos_t SHORT_PATH_MAX_SEARCH_RANGE = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*9);
static const entity_pos_t SHORT_PATH_MAX_SEARCH_RANGE = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*10);
/**
* Minimum distance to goal for a long path request
@ -703,7 +703,7 @@ void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path)
if (!m_LongPath.m_Waypoints.empty())
{
PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };
RequestShortPath(pos, goal, false);
RequestShortPath(pos, goal, true);
return;
}
}
@ -912,18 +912,29 @@ bool CCmpUnitMotion::HandleObstructedMove()
// Oops, we hit something (very likely another unit).
// If we still have long waypoints, try and compute a short path
if (!m_LongPath.m_Waypoints.empty())
{
PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };
RequestShortPath(pos, goal, false);
return true;
}
// Else, just entirely recompute
PathGoal goal;
if (!ComputeGoal(goal, m_MoveRequest))
return false;
// If close enough, just compute a short path to the goal
if (goal.DistanceToPoint(pos) < LONG_PATH_MIN_DIST)
{
m_LongPath.m_Waypoints.clear();
RequestShortPath(pos, goal, true);
return true;
}
// If we still have long waypoints, try and compute a short path.
// Assume the next waypoint is impassable
if (m_LongPath.m_Waypoints.size() > 1)
m_LongPath.m_Waypoints.pop_back();
if (!m_LongPath.m_Waypoints.empty())
{
PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };
RequestShortPath(pos, goal, true);
return true;
}
// Else, just entirely recompute
BeginPathing(pos, goal);
// potential TODO: We could switch the short-range pathfinder for something else entirely.
@ -1281,12 +1292,7 @@ void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& go
// the check is arbitrary but should be a reasonably small distance.
if (goal.DistanceToPoint(from) < LONG_PATH_MIN_DIST)
{
// add our final goal as a long range waypoint so we don't forget
// where we are going if the short-range pathfinder returns
// an aborted path.
m_LongPath.m_Waypoints.clear();
CFixedVector2D target = goal.NearestPointOnGoal(from);
m_LongPath.m_Waypoints.emplace_back(Waypoint{ target.X, target.Y });
RequestShortPath(from, goal, true);
}
else
@ -1317,8 +1323,6 @@ void CCmpUnitMotion::RequestShortPath(const CFixedVector2D &from, const PathGoal
return;
fixed searchRange = std::max(SHORT_PATH_MIN_SEARCH_RANGE * (m_FailedPathComputations + 1), goal.DistanceToPoint(from));
if (goal.type != PathGoal::POINT && searchRange < goal.hw && searchRange < SHORT_PATH_MIN_SEARCH_RANGE * 2)
searchRange = std::min(goal.hw, SHORT_PATH_MIN_SEARCH_RANGE * 2);
if (searchRange > SHORT_PATH_MAX_SEARCH_RANGE)
searchRange = SHORT_PATH_MAX_SEARCH_RANGE;