bool HierarchicalPathfinder::MakeGoalReachable(u16 i0, u16 j0, PathGoal& goal, pass_class_t passClass) { RegionID source = Get(i0, j0, passClass); // Find everywhere that's reachable std::set<RegionID> reachableRegions; FindReachableRegions(source, reachableRegions, passClass); // Check whether any reachable region contains the goal for (const RegionID& region : reachableRegions) { // Skip region if its chunk doesn't contain the goal area entity_pos_t x0 = Pathfinding::NAVCELL_SIZE * (region.ci * CHUNK_SIZE); entity_pos_t z0 = Pathfinding::NAVCELL_SIZE * (region.cj * CHUNK_SIZE); entity_pos_t x1 = x0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; entity_pos_t z1 = z0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; if (!goal.RectContainsGoal(x0, z0, x1, z1)) continue; // If the region contains the goal area, the goal is reachable // and we don't need to move it if (GetChunk(region.ci, region.cj, passClass).RegionContainsGoal(region.r, goal)) return false; } // The goal area wasn't reachable, // so find the navcell that's nearest to the goal's center u16 iGoal, jGoal; Pathfinding::NearestNavcell(goal.x, goal.z, iGoal, jGoal, m_W, m_H); FindNearestNavcellInRegions(reachableRegions, iGoal, jGoal, passClass); // Construct a new point goal at the nearest reachable navcell PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(iGoal, jGoal, newGoal.x, newGoal.z); goal = newGoal; return true; }
void HierarchicalPathfinder::MakeGoalReachable(u16 i0, u16 j0, PathGoal& goal, pass_class_t passClass) { PROFILE2("MakeGoalReachable"); RegionID source = Get(i0, j0, passClass); // Find everywhere that's reachable std::set<RegionID> reachableRegions; FindReachableRegions(source, reachableRegions, passClass); // Check whether any reachable region contains the goal // And get the navcell that's the closest to the point u16 bestI = 0; u16 bestJ = 0; u32 dist2Best = std::numeric_limits<u32>::max(); for (const RegionID& region : reachableRegions) { // Skip region if its chunk doesn't contain the goal area entity_pos_t x0 = Pathfinding::NAVCELL_SIZE * (region.ci * CHUNK_SIZE); entity_pos_t z0 = Pathfinding::NAVCELL_SIZE * (region.cj * CHUNK_SIZE); entity_pos_t x1 = x0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; entity_pos_t z1 = z0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; if (!goal.RectContainsGoal(x0, z0, x1, z1)) continue; u16 i,j; u32 dist2; // If the region contains the goal area, the goal is reachable // Remember the best point for optimization. if (GetChunk(region.ci, region.cj, passClass).RegionNearestNavcellInGoal(region.r, i0, j0, goal, i, j, dist2)) { // If it's a point, no need to move it, we're done if (goal.type == PathGoal::POINT) return; if (dist2 < dist2Best) { bestI = i; bestJ = j; dist2Best = dist2; } } } // If the goal area wasn't reachable, // find the navcell that's nearest to the goal's center if (dist2Best == std::numeric_limits<u32>::max()) { u16 iGoal, jGoal; Pathfinding::NearestNavcell(goal.x, goal.z, iGoal, jGoal, m_W, m_H); FindNearestNavcellInRegions(reachableRegions, iGoal, jGoal, passClass); // Construct a new point goal at the nearest reachable navcell PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(iGoal, jGoal, newGoal.x, newGoal.z); goal = newGoal; return; } ENSURE(dist2Best != std::numeric_limits<u32>::max()); PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(bestI, bestJ, newGoal.x, newGoal.z); goal = newGoal; }
void HierarchicalPathfinder::MakeGoalReachable(u16 i0, u16 j0, PathGoal& goal, pass_class_t passClass) { RegionID source = Get(i0, j0, passClass); // Find everywhere that's reachable std::set<RegionID> reachableRegions; FindReachableRegions(source, reachableRegions, passClass); // Check whether any reachable region contains the goal std::set<RegionID> reachableContainingGoal; for (const RegionID& region : reachableRegions) { // Skip region if its chunk doesn't contain the goal area entity_pos_t x0 = Pathfinding::NAVCELL_SIZE * (region.ci * CHUNK_SIZE); entity_pos_t z0 = Pathfinding::NAVCELL_SIZE * (region.cj * CHUNK_SIZE); entity_pos_t x1 = x0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; entity_pos_t z1 = z0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; if (!goal.RectContainsGoal(x0, z0, x1, z1)) continue; // If the region contains the goal area, the goal is reachable if (GetChunk(region.ci, region.cj, passClass).RegionContainsGoal(region.r, goal)) { // If it's a point, no need to move it, we're done if (goal.type == PathGoal::POINT) return; // Else remember this region reachableContainingGoal.insert(region); } } // If the goal area wasn't reachable, // find the navcell that's nearest to the goal's center if (reachableContainingGoal.empty()) { u16 iGoal, jGoal; Pathfinding::NearestNavcell(goal.x, goal.z, iGoal, jGoal, m_W, m_H); FindNearestNavcellInRegions(reachableRegions, iGoal, jGoal, passClass); // Construct a new point goal at the nearest reachable navcell PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(iGoal, jGoal, newGoal.x, newGoal.z); goal = newGoal; return; } // Non-point goals: // For each region, find the closest navcell to (i0,j0) which is also in the goal, // and use the best of all regions ENSURE(goal.type != PathGoal::POINT); u16 bestI, bestJ; u32 dist2Best = std::numeric_limits<u32>::max(); for (const RegionID& region : reachableContainingGoal) { u16 i, j; u32 dist2; GetChunk(region.ci, region.cj, passClass).RegionNearestNavcellInGoal(region.r, i0, j0, goal, i, j, dist2); if (dist2 < dist2Best) { bestI = i; bestJ = j; dist2Best = dist2; } } PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(bestI, bestJ, newGoal.x, newGoal.z); goal = newGoal; }