bool overmapbuffer::reveal_route( const tripoint &source, const tripoint &dest, int radius ) { static const int RADIUS = 4; // Maximal radius of search (in overmaps) static const int OX = RADIUS * OMAPX; // half-width of the area to search in static const int OY = RADIUS * OMAPY; // half-height of the area to search in const tripoint start( OX, OY, source.z ); // Local source - center of the local area const tripoint base( source - start ); // To convert local coordinates to global ones const tripoint finish( dest - base ); // Local destination - relative to source const auto estimate = [ this, &base, &finish ]( const pf::node &, const pf::node &cur ) { int res = 0; int omx = base.x + cur.x; int omy = base.y + cur.y; const auto &oter = get_om_global( omx, omy ).get_ter( omx, omy, base.z ); if( !is_ot_type( "road", oter ) && !is_ot_type ( "bridge", oter ) && !is_ot_type( "hiway", oter ) ) { if( is_river( oter ) ) { return -1; // Can't walk on water } // Allow going slightly off-road to overcome small obstacles (e.g. craters), // but heavily penalize that to make roads preferable res += 250; } res += std::abs( finish.x - cur.x ) + std::abs( finish.y - cur.y ); return res; }; const auto path = pf::find_path( start, finish, 2*OX, 2*OY, estimate ); if( path.empty() ) { return false; } for( const auto &node : path ) { reveal( base + tripoint( node.x, node.y, base.z ), radius ); } return true; }
bool overmapbuffer::reveal_route( const tripoint &source, const tripoint &dest, int radius, bool road_only ) { static const int RADIUS = 4; // Maximal radius of search (in overmaps) static const int OX = RADIUS * OMAPX; // half-width of the area to search in static const int OY = RADIUS * OMAPY; // half-height of the area to search in if( source == overmap::invalid_tripoint || dest == overmap::invalid_tripoint ) { return false; } const tripoint start( OX, OY, source.z ); // Local source - center of the local area const tripoint base( source - start ); // To convert local coordinates to global ones const tripoint finish( dest - base ); // Local destination - relative to source const auto get_ter_at = [&]( int x, int y ) { x += base.x; y += base.y; const overmap &om = get_om_global( x, y ); return om.get_ter( x, y, source.z ); }; const auto oter = get_ter_at( start.x, start.y ) ; const auto connection = overmap_connections::guess_for( oter ); if( !connection ) { return false; } const auto estimate = [&]( const pf::node & cur, const pf::node * ) { int res = 0; const auto oter = get_ter_at( cur.x, cur.y ); if( !connection->has( oter ) ) { if( road_only ) { return pf::rejected; } if( is_river( oter ) ) { return pf::rejected; // Can't walk on water } // Allow going slightly off-road to overcome small obstacles (e.g. craters), // but heavily penalize that to make roads preferable res += 250; } res += std::abs( finish.x - cur.x ) + std::abs( finish.y - cur.y ); return res; }; const auto path = pf::find_path( point( start.x, start.y ), point( finish.x, finish.y ), 2 * OX, 2 * OY, estimate ); for( const auto &node : path.nodes ) { reveal( base + tripoint( node.x, node.y, base.z ), radius ); } return !path.nodes.empty(); }