Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static const entity_pos_t WAYPOINT_ADVANCE_MAX = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*8); | static const entity_pos_t WAYPOINT_ADVANCE_MAX = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*8); | ||||
/** | /** | ||||
* Min/Max range to restrict short path queries to. (Larger ranges are slower, | * Min/Max range to restrict short path queries to. (Larger ranges are slower, | ||||
* smaller ranges might miss some legitimate routes around large obstacles.) | * 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_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 | * Minimum distance to goal for a long path request | ||||
*/ | */ | ||||
static const entity_pos_t LONG_PATH_MIN_DIST = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*4); | static const entity_pos_t LONG_PATH_MIN_DIST = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*4); | ||||
/** | /** | ||||
* If we are this close to our target entity/point, then think about heading | * If we are this close to our target entity/point, then think about heading | ||||
▲ Show 20 Lines • Show All 630 Lines • ▼ Show 20 Lines | void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) | ||||
// If we're globally following a long path, try to remove the next waypoint, | // If we're globally following a long path, try to remove the next waypoint, | ||||
// it might be obstructed (e.g. by idle entities which the long-range pathfinder doesn't see). | // it might be obstructed (e.g. by idle entities which the long-range pathfinder doesn't see). | ||||
if (!m_LongPath.m_Waypoints.empty()) | if (!m_LongPath.m_Waypoints.empty()) | ||||
{ | { | ||||
m_LongPath.m_Waypoints.pop_back(); | m_LongPath.m_Waypoints.pop_back(); | ||||
if (!m_LongPath.m_Waypoints.empty()) | if (!m_LongPath.m_Waypoints.empty()) | ||||
{ | { | ||||
PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z }; | 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; | return; | ||||
} | } | ||||
} | } | ||||
PathGoal goal; | PathGoal goal; | ||||
// If we can't compute a goal, we'll fail in the next Move() call so do nothing special. | // If we can't compute a goal, we'll fail in the next Move() call so do nothing special. | ||||
if (!ComputeGoal(goal, m_MoveRequest)) | if (!ComputeGoal(goal, m_MoveRequest)) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | bool CCmpUnitMotion::HandleObstructedMove() | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
return false; | return false; | ||||
CFixedVector2D pos = cmpPosition->GetPosition2D(); | CFixedVector2D pos = cmpPosition->GetPosition2D(); | ||||
// Oops, we hit something (very likely another unit). | // Oops, we hit something (very likely another unit). | ||||
// If we still have long waypoints, try and compute a short path | 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()) | if (!m_LongPath.m_Waypoints.empty()) | ||||
{ | { | ||||
PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z }; | 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 true; | return true; | ||||
} | } | ||||
// Else, just entirely recompute | // Else, just entirely recompute | ||||
PathGoal goal; | |||||
if (!ComputeGoal(goal, m_MoveRequest)) | |||||
return false; | |||||
BeginPathing(pos, goal); | BeginPathing(pos, goal); | ||||
// potential TODO: We could switch the short-range pathfinder for something else entirely. | // potential TODO: We could switch the short-range pathfinder for something else entirely. | ||||
return true; | return true; | ||||
} | } | ||||
bool CCmpUnitMotion::TargetHasValidPosition(const MoveRequest& moveRequest) const | bool CCmpUnitMotion::TargetHasValidPosition(const MoveRequest& moveRequest) const | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 341 Lines • ▼ Show 20 Lines | #endif | ||||
// 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 | ||||
// need a long path, so we shouldn't simply check linear distance | // need a long path, so we shouldn't simply check linear distance | ||||
// the check is arbitrary but should be a reasonably small distance. | // the check is arbitrary but should be a reasonably small distance. | ||||
if (goal.DistanceToPoint(from) < LONG_PATH_MIN_DIST) | 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(); | 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); | RequestShortPath(from, goal, true); | ||||
} | } | ||||
else | else | ||||
RequestLongPath(from, goal); | RequestLongPath(from, goal); | ||||
} | } | ||||
void CCmpUnitMotion::RequestLongPath(const CFixedVector2D& from, const PathGoal& goal) | void CCmpUnitMotion::RequestLongPath(const CFixedVector2D& from, const PathGoal& goal) | ||||
{ | { | ||||
Show All 14 Lines | |||||
void CCmpUnitMotion::RequestShortPath(const CFixedVector2D &from, const PathGoal& goal, bool avoidMovingUnits) | void CCmpUnitMotion::RequestShortPath(const CFixedVector2D &from, const PathGoal& goal, bool avoidMovingUnits) | ||||
{ | { | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | ||||
if (!cmpPathfinder) | if (!cmpPathfinder) | ||||
return; | return; | ||||
fixed searchRange = std::max(SHORT_PATH_MIN_SEARCH_RANGE * (m_FailedPathComputations + 1), goal.DistanceToPoint(from)); | 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) | if (searchRange > SHORT_PATH_MAX_SEARCH_RANGE) | ||||
searchRange = SHORT_PATH_MAX_SEARCH_RANGE; | searchRange = SHORT_PATH_MAX_SEARCH_RANGE; | ||||
m_ExpectedPathTicket.m_Type = Ticket::SHORT_PATH; | m_ExpectedPathTicket.m_Type = Ticket::SHORT_PATH; | ||||
m_ExpectedPathTicket.m_Ticket = cmpPathfinder->ComputeShortPathAsync(from.X, from.Y, m_Clearance, searchRange, goal, m_PassClass, avoidMovingUnits, GetGroup(), GetEntityId()); | m_ExpectedPathTicket.m_Ticket = cmpPathfinder->ComputeShortPathAsync(from.X, from.Y, m_Clearance, searchRange, goal, m_PassClass, avoidMovingUnits, GetGroup(), GetEntityId()); | ||||
} | } | ||||
bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) | bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) | ||||
▲ Show 20 Lines • Show All 108 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator