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 ¢er ) { 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 ¢er ) { 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 ¢er ) { // 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; }
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); }
int city_reference::get_distance_from_bounds() const { assert( city != nullptr ); return distance - omt_to_sm_copy( city->size ); }