Index: source/simulation2/components/CCmpUnitMotion.cpp =================================================================== --- source/simulation2/components/CCmpUnitMotion.cpp +++ source/simulation2/components/CCmpUnitMotion.cpp @@ -1416,21 +1416,27 @@ { // Ranged movement: + CmpPtr cmpObstruction(GetEntityHandle()); + ENSURE(cmpObstruction); + // Distance checks are nearest edge to nearest edge, so we need to account for our clearance + // and we must make sure diagonals also fit so multiply by slightly more than sqrt(2) + entity_pos_t goalDelta = cmpObstruction->GetUnitRadius() * 3 /2; + entity_pos_t distance = (pos - CFixedVector2D(x, z)).Length(); if (distance < minRange) { // Too close to target - move outwards to a circle - // that's slightly larger than the min range + // that's slightly larger than the min range. goal.type = PathGoal::INVERTED_CIRCLE; - goal.hw = minRange + Pathfinding::GOAL_DELTA; + goal.hw = minRange + goalDelta; } else if (maxRange >= entity_pos_t::Zero() && distance > maxRange) { // Too far from target - move inwards to a circle // that's slightly smaller than the max range goal.type = PathGoal::CIRCLE; - goal.hw = maxRange - Pathfinding::GOAL_DELTA; + goal.hw = maxRange - goalDelta; // If maxRange was abnormally small, // collapse the circle into a point @@ -1502,7 +1508,7 @@ /* * If we're starting outside the maxRange, we need to move closer in. * If we're starting inside the minRange, we need to move further out. - * These ranges are measured from the center of this entity to the edge of the target; + * These ranges are measured from the edge of this entity to the edge of the target; * we add the goal range onto the size of the target shape to get the goal shape. * (Then we extend it outwards/inwards by a little bit to be sure we'll end up * within the right range, in case of minor numerical inaccuracies.) @@ -1536,6 +1542,12 @@ cmpObstruction->GetPreviousObstructionSquare(previousObstruction); entity_pos_t previousDistance = Geometry::DistanceToSquare(pos - CFixedVector2D(previousObstruction.x, previousObstruction.z), obstruction.u, obstruction.v, halfSize, true); + CmpPtr cmpThisObstruction(GetEntityHandle()); + ENSURE(cmpThisObstruction); + // Distance checks are nearest edge to nearest edge, so we need to account for our clearance + // and we must make sure diagonals also fit so multiply by slightly more than sqrt(2) + entity_pos_t goalDelta = cmpThisObstruction->GetUnitRadius() * 3 /2; + bool inside = distance.IsZero() && !Geometry::DistanceToSquare(pos - CFixedVector2D(obstruction.x, obstruction.z), obstruction.u, obstruction.v, halfSize).IsZero(); if ((distance < minRange && previousDistance < minRange) || inside) { @@ -1544,7 +1556,7 @@ // Circumscribe the square entity_pos_t circleRadius = halfSize.Length(); - entity_pos_t goalDistance = minRange + Pathfinding::GOAL_DELTA; + entity_pos_t goalDistance = minRange + goalDelta; if (ShouldTreatTargetAsCircle(minRange, circleRadius)) { @@ -1592,7 +1604,7 @@ return true; } - entity_pos_t goalDistance = maxRange - Pathfinding::GOAL_DELTA; + entity_pos_t goalDistance = maxRange - goalDelta; goal.type = PathGoal::CIRCLE; goal.hw = circleRadius + goalDistance; @@ -1602,12 +1614,12 @@ // The target is large relative to our range, so treat it as a square and // get close enough that the diagonals come within range - entity_pos_t goalDistance = (maxRange - Pathfinding::GOAL_DELTA)*2 / 3; // multiply by slightly less than 1/sqrt(2) + entity_pos_t goalDistance = (maxRange - goalDelta) * 2 / 3; // multiply by slightly less than 1/sqrt(2) goal.type = PathGoal::SQUARE; goal.u = obstruction.u; goal.v = obstruction.v; - entity_pos_t delta = std::max(goalDistance, m_Clearance + entity_pos_t::FromInt(TERRAIN_TILE_SIZE)/16); // ensure it's far enough to not intersect the building itself + entity_pos_t delta = std::max(goalDistance, goalDelta + entity_pos_t::FromInt(TERRAIN_TILE_SIZE)/16); // ensure it's far enough to not intersect the building itself goal.hw = obstruction.hw + delta; goal.hh = obstruction.hh + delta; } Index: source/simulation2/helpers/Pathfinding.h =================================================================== --- source/simulation2/helpers/Pathfinding.h +++ source/simulation2/helpers/Pathfinding.h @@ -148,15 +148,6 @@ const int NAVCELL_SIZE_INT = 1; const int NAVCELL_SIZE_LOG2 = 0; - /** - * For extending the goal outwards/inwards a little bit - * NOTE: keep next to the definition of NAVCELL_SIZE to avoid init order problems - * between translation units. - * TODO: figure out whether this is actually needed. It was added back in r8751 (in 2010) for unclear reasons - * and it does not seem to really improve behavior today - */ - const entity_pos_t GOAL_DELTA = NAVCELL_SIZE/8; - /** * To make sure the long-range pathfinder is more strict than the short-range one, * we need to slightly over-rasterize. So we extend the clearance radius by 1.