diff --git a/src/game.cpp b/src/game.cpp index 2d028619c2dd6..8dffc7e88ce26 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1486,7 +1486,7 @@ bool game::do_turn() if( hostile_critter != nullptr ) { cancel_activity_or_ignore_query( distraction_type::hostile_spotted, string_format( _( "The %s is dangerously close!" ), - hostile_critter->get_name() ) ); + hostile_critter->get_name() ), -1 ); } } @@ -1687,8 +1687,17 @@ static bool cancel_auto_move( player &p, const std::string &text ) return false; } -bool game::cancel_activity_or_ignore_query( const distraction_type type, const std::string &text ) +bool game::cancel_activity_or_ignore_query( const distraction_type type, const std::string &text, + int distance /*=0*/ ) { + if( ( type == distraction_type::noise || type == distraction_type::hostile_spotted ) && + ( distance >= get_option( "AUTOIGNOREDISTANCE" ) ) + && ( get_option( "AUTOIGNOREMODE" ) == "ALWAYS" || + ( get_option( "AUTOIGNOREMODE" ) == "SAFEON" && g->safe_mode ) || + ( get_option( "AUTOIGNOREMODE" ) == "SAFEOFF" && !g->safe_mode ) + ) ) { + return false; + } if( u.has_distant_destination() ) { if( cancel_auto_move( u, text ) ) { return true; @@ -3844,6 +3853,7 @@ void game::mon_info( const catacurses::window &w, int hor_padding ) // @todo change current_turn to time_point const int current_turn = to_turns( calendar::turn - calendar::turn_zero ); const int sm_ignored_turns = get_option( "SAFEMODEIGNORETURNS" ); + int distance = -1; for( auto &c : u.get_visible_creatures( MAPSIZE_X ) ) { const auto m = dynamic_cast( c ); @@ -3913,6 +3923,9 @@ void game::mon_info( const catacurses::window &w, int hor_padding ) const monster_attitude matt = critter.attitude( &u ); const int mon_dist = rl_dist( u.pos(), critter.pos() ); + if( mon_dist < distance || distance == -1 ) { + distance = mon_dist; + } safemode_state = get_safemode().check_monster( critter.name(), critter.attitude_to( u ), mon_dist ); if( ( !safemode_empty && safemode_state == RULE_BLACKLISTED ) || ( safemode_empty && @@ -3949,6 +3962,9 @@ void game::mon_info( const catacurses::window &w, int hor_padding ) //Safe mode NPC check const int npc_dist = rl_dist( u.pos(), p->pos() ); + if( npc_dist < distance || distance == -1 ) { + distance = npc_dist; + } safemode_state = get_safemode().check_monster( get_safemode().npc_type_name(), p->attitude_to( u ), npc_dist ); @@ -3967,7 +3983,7 @@ void game::mon_info( const catacurses::window &w, int hor_padding ) if( !new_seen_mon.empty() ) { monster &critter = *new_seen_mon.back(); cancel_activity_or_ignore_query( distraction_type::hostile_spotted, - string_format( _( "%s spotted!" ), critter.name() ) ); + string_format( _( "%s spotted!" ), critter.name() ), distance ); if( u.has_trait( trait_id( "M_DEFENDER" ) ) && critter.type->in_species( PLANT ) ) { add_msg( m_warning, _( "We have detected a %s - an enemy of the Mycus!" ), critter.name() ); if( !u.has_effect( effect_adrenaline_mycus ) ) { @@ -3982,10 +3998,11 @@ void game::mon_info( const catacurses::window &w, int hor_padding ) } else { //Hostile NPC cancel_activity_or_ignore_query( distraction_type::hostile_spotted, - _( "Hostile survivor spotted!" ) ); + _( "Hostile survivor spotted!" ), distance ); } } else { - cancel_activity_or_ignore_query( distraction_type::hostile_spotted, _( "Monsters spotted!" ) ); + cancel_activity_or_ignore_query( distraction_type::hostile_spotted, _( "Monsters spotted!" ), + distance ); } turnssincelastmon = 0; if( safe_mode == SAFE_MODE_ON ) { diff --git a/src/game.h b/src/game.h index 95fc12ae0d675..e89113b6968d0 100644 --- a/src/game.h +++ b/src/game.h @@ -451,7 +451,8 @@ class game bool cancel_activity_query( const std::string &text ); /** Asks if the player wants to cancel their activity and if so cancels it. Additionally checks * if the player wants to ignore further distractions. */ - bool cancel_activity_or_ignore_query( distraction_type type, const std::string &text ); + bool cancel_activity_or_ignore_query( distraction_type type, const std::string &text, + int distance = 0 ); /** Handles players exiting from moving vehicles. */ void moving_vehicle_dismount( const tripoint &dest_loc ); diff --git a/src/options.cpp b/src/options.cpp index 9ec623a19fa92..10f4cd5b3b67e 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -1174,6 +1174,21 @@ void options_manager::add_options_general() mOptionsSort["general"]++; + add( "AUTOIGNOREMODE", "general", translate_marker( "Auto ignore sounds/hostiles mode" ), + translate_marker( "While auto ignore is active you will not be interrupted by sounds or spotted hostiles. Always: Auto ignore will always be active. SafeOn: Auto ignore will be active while safe mode is on. SafeOff: Auto ignore will be active while safe mode is off. Never: Auto ignore will never be active." ), + { { "ALWAYS", translate_marker( "Always" ) }, { "SAFEON", translate_marker( "SafeOn" ) }, { "SAFEOFF", translate_marker( "SafeOff" ) }, { "NEVER", translate_marker( "Never" ) } }, + "NEVER" + ); + + add( "AUTOIGNOREDISTANCE", "general", translate_marker( "Auto ignore starting distance" ), + translate_marker( "Only sounds/hostiles this distance and further away will be auto ignored. Each z-Level counts as 10 horizontal distance." ), + 0, 30, 5 + ); + + get_option( "AUTOIGNOREDISTANCE" ).setPrerequisites( "AUTOIGNOREMODE", { "ALWAYS", "SAFEON", "SAFEOFF" } ); + + mOptionsSort["general"]++; + add( "TURN_DURATION", "general", translate_marker( "Realtime turn progression" ), translate_marker( "If enabled, monsters will take periodic gameplay turns. This value is the delay between each turn, in seconds. Works best with Safe Mode disabled. 0 = disabled." ), 0.0, 10.0, 0.0, 0.05 diff --git a/src/player_hardcoded_effects.cpp b/src/player_hardcoded_effects.cpp index ac86ee30cd9d7..9d7bc28553d43 100644 --- a/src/player_hardcoded_effects.cpp +++ b/src/player_hardcoded_effects.cpp @@ -571,7 +571,7 @@ void player::hardcoded_effects( effect &it ) g->place_critter_at( spawn_details.name, dest ); if( g->u.sees( dest ) ) { g->cancel_activity_or_ignore_query( distraction_type::hostile_spotted, - _( "A monster appears nearby!" ) ); + _( "A monster appears nearby!" ), -1 ); add_msg_if_player( m_warning, _( "A portal opens nearby, and a monster crawls through!" ) ); } it.mult_duration( .25 ); @@ -671,7 +671,7 @@ void player::hardcoded_effects( effect &it ) g->place_critter_at( spawn_details.name, dest ); if( g->u.sees( dest ) ) { g->cancel_activity_or_ignore_query( distraction_type::hostile_spotted, - _( "A monster appears nearby!" ) ); + _( "A monster appears nearby!" ), -1 ); add_msg( m_warning, _( "A portal opens nearby, and a monster crawls through!" ) ); } if( one_in( 2 ) ) { diff --git a/src/sounds.cpp b/src/sounds.cpp index 86f56dd7083f4..a19e179704b26 100644 --- a/src/sounds.cpp +++ b/src/sounds.cpp @@ -432,7 +432,7 @@ void sounds::process_sound_markers( player *p ) if( !sound.ambient && ( pos != p->pos() ) && !g->m.pl_sees( pos, distance_to_sound ) ) { if( !p->activity.is_distraction_ignored( distraction_type::noise ) ) { const std::string query = string_format( _( "Heard %s!" ), description ); - g->cancel_activity_or_ignore_query( distraction_type::noise, query ); + g->cancel_activity_or_ignore_query( distraction_type::noise, query, distance_to_sound ); } }