void start_location::burn( const tripoint &omtstart,
                           const size_t count, const int rad ) const
{
    const tripoint player_location = omt_to_sm_copy( omtstart );
    tinymap m;
    m.load( player_location.x, player_location.y, player_location.z, false );
    m.build_outside_cache( m.get_abs_sub().z );
    const int ux = g->u.posx() % ( SEEX * int( MAPSIZE / 2 ) );
    const int uy = g->u.posy() % ( SEEY * int( MAPSIZE / 2 ) );
    std::vector<tripoint> valid;
    tripoint p = player_location;
    int &x = p.x;
    int &y = p.y;
    for( x = 0; x < m.getmapsize() * SEEX; x++ ) {
        for( y = 0; y < m.getmapsize() * SEEY; y++ ) {
            if( !( m.has_flag_ter( "DOOR", p ) ||
                   m.has_flag_ter( "OPENCLOSE_INSIDE", p ) ||
                   m.is_outside( p ) ||
                   ( x >= ux - rad && x <= ux + rad && y >= uy - rad && y <= uy + rad ) ) ) {
                if( m.has_flag( "FLAMMABLE", p ) || m.has_flag( "FLAMMABLE_ASH", p ) ) {
                    valid.push_back( p );
                }
            }
        }
    }
    random_shuffle( valid.begin(), valid.end() );
    for( size_t i = 0; i < std::min( count, valid.size() ); i++ ) {
        m.add_field( valid[i], fd_fire, 3, 0 );
    }
    m.save();
}
void start_location::prepare_map( const tripoint &omtstart ) const
{
    // Now prepare the initial map (change terrain etc.)
    const point player_location = omt_to_sm_copy( omtstart.x, omtstart.y );
    tinymap player_start;
    player_start.load( player_location.x, player_location.y, omtstart.z, false );
    prepare_map( player_start );
    player_start.save();
}
city_reference overmapbuffer::closest_city( const tripoint &center )
{
    const auto cities = get_cities_near( center, omt_to_sm_copy( OMAPX ) );

    if( !cities.empty() ) {
        return cities.front();
    }

    return city_reference::invalid;
}
static void add_monsters( const tripoint &omtstart, const mongroup_id &type, float expected_points )
{
    const tripoint spawn_location = omt_to_sm_copy( omtstart );
    tinymap m;
    m.load( spawn_location.x, spawn_location.y, spawn_location.z, false );
    // map::place_spawns internally multiplies density by rng(10, 50)
    float density = expected_points / ( ( 10 + 50 ) / 2 );
    m.place_spawns( type, 1, 0, 0, SEEX * 2 - 1, SEEY * 2 - 1, density );
    m.save();
}
bool tutorial_game::init()
{
    // TODO: clean up old tutorial

    calendar::turn = HOURS( 12 ); // Start at noon
    for( auto &elem : tutorials_seen ) {
        elem = false;
    }
    g->scent.reset();
    g->temperature = 65;
    // We use a Z-factor of 10 so that we don't plop down tutorial rooms in the
    // middle of the "real" game world
    g->u.normalize();
    g->u.str_cur = g->u.str_max;
    g->u.per_cur = g->u.per_max;
    g->u.int_cur = g->u.int_max;
    g->u.dex_cur = g->u.dex_max;

    for( int i = 0; i < num_hp_parts; i++ ) {
        g->u.hp_cur[i] = g->u.hp_max[i];
    }

    const oter_id rock( "rock" );
    //~ default name for the tutorial
    g->u.name = _( "John Smith" );
    g->u.prof = profession::generic();
    // overmap terrain coordinates
    const int lx = 50;
    const int ly = 50;
    auto &starting_om = overmap_buffer.get( 0, 0 );
    for( int i = 0; i < OMAPX; i++ ) {
        for( int j = 0; j < OMAPY; j++ ) {
            starting_om.ter( i, j, -1 ) = rock;
            // Start with the overmap revealed
            starting_om.seen( i, j, 0 ) = true;
        }
    }
    starting_om.ter( lx, ly, 0 ) = oter_id( "tutorial" );
    starting_om.ter( lx, ly, -1 ) = oter_id( "tutorial" );
    starting_om.clear_mon_groups();

    g->u.toggle_trait( trait_id( "QUICK" ) );
    item lighter( "lighter", 0 );
    lighter.invlet = 'e';
    g->u.inv.add_item( lighter, true, false );
    g->u.set_skill_level( skill_id( "gun" ), 5 );
    g->u.set_skill_level( skill_id( "melee" ), 5 );
    g->load_map( omt_to_sm_copy( tripoint( lx, ly, 0 ) ) );
    g->u.setx( 2 );
    g->u.sety( 4 );

    // This shifts the view to center the players pos
    g->update_map( g->u );
    return true;
}
void start_location::add_map_special( const tripoint &omtstart,
                                      const std::string &map_special ) const
{
    const tripoint player_location = omt_to_sm_copy( omtstart );
    tinymap m;
    m.load( player_location.x, player_location.y, player_location.z, false );

    const auto ptr = MapExtras::get_function( map_special );
    ptr( m, player_location );

    m.save();
}
std::string overmapbuffer::get_description_at( const tripoint &where )
{
    const std::string ter_name = ter( sm_to_omt_copy( where ) )->get_name();

    if( where.z != 0 ) {
        return ter_name;
    }

    const auto closest_cref = closest_known_city( where );

    if( !closest_cref ) {
        return ter_name;
    }

    const auto &closest_city = *closest_cref.city;
    const direction dir = direction_from( closest_cref.abs_sm_pos, where );
    const std::string dir_name = direction_name( dir );

    const int sm_size = omt_to_sm_copy( closest_cref.city->size );
    const int sm_dist = closest_cref.distance;

    if( sm_dist <= 3 * sm_size / 4 ) {
        if( sm_size >= 16 ) {
            // The city is big enough to be split in districts.
            if( sm_dist <= sm_size / 4 ) {
                //~ First parameter is a terrain name, second parameter is a city name.
                return string_format( _( "%1$s in central %2$s" ), ter_name.c_str(), closest_city.name.c_str() );
            } else {
                //~ First parameter is a terrain name, second parameter is a direction, and third parameter is a city name.
                return string_format( _( "%1$s in %2$s %3$s" ), ter_name.c_str(), dir_name.c_str(),
                                      closest_city.name.c_str() );
            }
        } else {
            //~ First parameter is a terrain name, second parameter is a city name.
            return string_format( _( "%1$s in %2$s" ), ter_name.c_str(), closest_city.name.c_str() );
        }
    } else if( sm_dist <= sm_size ) {
        if( sm_size >= 8 ) {
            // The city is big enough to have outskirts.
            //~ First parameter is a terrain name, second parameter is a direction, and third parameter is a city name.
            return string_format( _( "%1$s on the %2$s outskirts of %3$s" ), ter_name.c_str(), dir_name.c_str(),
                                  closest_city.name.c_str() );
        } else {
            //~ First parameter is a terrain name, second parameter is a city name.
            return string_format( _( "%1$s in %2$s" ), ter_name.c_str(), closest_city.name.c_str() );
        }
    }

    //~ First parameter is a terrain name, second parameter is a direction, and third parameter is a city name.
    return string_format( _( "%1$s %2$s from %3$s" ), ter_name.c_str(), dir_name.c_str(),
                          closest_city.name.c_str() );
}
city_reference overmapbuffer::closest_known_city( const tripoint &center )
{
    const auto cities = get_cities_near( center, omt_to_sm_copy( OMAPX ) );
    const auto it = std::find_if( cities.begin(), cities.end(),
    [this]( const city_reference & elem ) {
        const tripoint p = sm_to_omt_copy( elem.abs_sm_pos );
        return seen( p.x, p.y, p.z );
    } );

    if( it != cities.end() ) {
        return *it;
    }

    return city_reference::invalid;
}
// If z == INT_MIN, allow all z-levels
std::vector<std::shared_ptr<npc>> overmapbuffer::get_npcs_near_omt( int x, int y, int z,
                               int radius )
{
    std::vector<std::shared_ptr<npc>> result;
    for( auto &it : get_overmaps_near( omt_to_sm_copy( x, y ), radius ) ) {
        auto temp = it->get_npcs( [&]( const npc & guy ) {
            // Global position of NPC, in submap coordinates
            tripoint pos = guy.global_omt_location();
            if( z != INT_MIN && pos.z != z ) {
                return false;
            }
            return square_dist( x, y, pos.x, pos.y ) <= radius;
        } );
        result.insert( result.end(), temp.begin(), temp.end() );
    }
    return result;
}
// If z == INT_MIN, allow all z-levels
std::vector<npc*> overmapbuffer::get_npcs_near_omt(int x, int y, int z, int radius)
{
    std::vector<npc*> result;
    for( auto &it : get_overmaps_near( omt_to_sm_copy( x, y ), radius ) ) {
        for( auto &np : it->npcs ) {
            // Global position of NPC, in submap coordiantes
            tripoint pos = np->global_omt_location();
            if( z != INT_MIN && pos.z != z) {
                continue;
            }
            const int npc_offset = square_dist( x, y, pos.x, pos.y );
            if (npc_offset <= radius) {
                result.push_back(np);
            }
        }
    }
    return result;
}
city_reference overmapbuffer::closest_city( const tripoint &center )
{
    // a whole overmap (because it's in submap coordinates, OMAPX is overmap terrain coordinates)
    auto const radius = OMAPX * 2;
    // Starting with distance = INT_MAX, so the first city is already closer
    city_reference result{ nullptr, nullptr, tripoint( 0, 0, 0 ), INT_MAX };
    for( auto &om : get_overmaps_near( center, radius ) ) {
        const auto abs_pos_om = om_to_sm_copy( om->pos() );
        for( auto &city : om->cities ) {
            const auto rel_pos_city = omt_to_sm_copy( point( city.x, city.y ) );
            // TODO: Z-level cities. This 0 has to be here until mapgen understands non-0 zlev cities
            const auto abs_pos_city = tripoint( abs_pos_om + rel_pos_city, 0 );
            const auto distance = rl_dist( abs_pos_city, center );
            const city_reference cr{ om, &city, abs_pos_city, distance };
            if( distance < result.distance ) {
                result = cr;
            } else if( distance == result.distance && result.city->s < city.s ) {
                result = cr;
            }
        }
    }
    return result;
}
Beispiel #12
0
std::vector<city_reference> overmapbuffer::get_cities_near( const tripoint &location, int radius )
{
    std::vector<city_reference> result;

    for( const auto om : get_overmaps_near( location, radius ) ) {
        const auto abs_pos_om = om_to_sm_copy( om->pos() );
        result.reserve( result.size() + om->cities.size() );
        std::transform( om->cities.begin(), om->cities.end(), std::back_inserter( result ),
        [&]( city & element ) {
            const auto rel_pos_city = omt_to_sm_copy( element.pos );
            const auto abs_pos_city = tripoint( rel_pos_city + abs_pos_om, 0 );
            const auto distance = rl_dist( abs_pos_city, location );

            return city_reference{ &element, abs_pos_city, distance };
        } );
    }

    std::sort( result.begin(), result.end(), []( const city_reference & lhs,
    const city_reference & rhs ) {
        return lhs.get_distance_from_bounds() < rhs.get_distance_from_bounds();
    } );

    return result;
}
std::vector<mongroup*> overmapbuffer::monsters_at(int x, int y, int z)
{
    const overmap* om = overmap_buffer.get_existing_om_global(x, y);
    point p = omt_to_sm_copy(x, y);
    return const_cast<overmap*>(om)->monsters_at(p.x, p.y, z);
}
Beispiel #14
0
int city_reference::get_distance_from_bounds() const
{
    assert( city != nullptr );
    return distance - omt_to_sm_copy( city->size );
}