diff --git a/data/raw/keybindings.json b/data/raw/keybindings.json index ae5082e0a6984..44df0239da8d4 100644 --- a/data/raw/keybindings.json +++ b/data/raw/keybindings.json @@ -1410,6 +1410,13 @@ "name": "Toggle activate/examine", "bindings": [ { "input_method": "keyboard", "key": "!" } ] }, + { + "type": "keybinding", + "id": "TOGGLE_SAFE_FUEL", + "category": "BIONICS", + "name": "Toggle safe fuel mod", + "bindings": [ { "input_method": "keyboard", "key": "s" } ] + }, { "type": "keybinding", "id": "TOGGLE_EXAMINE", diff --git a/src/bionics.cpp b/src/bionics.cpp index 0d8d7852c6dab..f5cf0fb7ed630 100644 --- a/src/bionics.cpp +++ b/src/bionics.cpp @@ -869,8 +869,9 @@ bool Character::burn_fuel( int b, bool start ) current_fuel_stock = std::stoi( get_value( fuel ) ); } - if( get_power_level() + units::from_kilojoule( fuel_energy ) * fuel_efficiency > - get_max_power_level() ) { + if( !bio.has_flag( "SAFE_FUEL_OFF" ) && + get_power_level() + units::from_kilojoule( fuel_energy ) * fuel_efficiency + > get_max_power_level() ) { add_msg_player_or_npc( m_info, _( "Your %s turns off to not waste fuel." ), _( "'s %s turns off to not waste fuel." ), bio.info().name ); @@ -2313,6 +2314,21 @@ void finalize_bionics() } } +void bionic::set_flag( const std::string flag ) +{ + bionic_tags.insert( flag ); +} + +void bionic::remove_flag( const std::string flag ) +{ + bionic_tags.erase( flag ); +} + +bool bionic::has_flag( const std::string flag ) const +{ + return bionic_tags.find( flag ) != bionic_tags.end(); +} + int bionic::get_quality( const quality_id &quality ) const { const auto &i = info(); @@ -2329,6 +2345,18 @@ bool bionic::is_this_fuel_powered( const itype_id &this_fuel ) const return std::find( fuel_op.begin(), fuel_op.end(), this_fuel ) != fuel_op.end(); } +void bionic::toggle_safe_fuel_mod() +{ + if( info().fuel_opts.empty() ) { + return; + } + if( !has_flag( "SAFE_FUEL_OFF" ) ) { + set_flag( "SAFE_FUEL_OFF" ); + } else { + remove_flag( "SAFE_FUEL_OFF" ); + } +} + void bionic::serialize( JsonOut &json ) const { json.start_object(); @@ -2338,6 +2366,7 @@ void bionic::serialize( JsonOut &json ) const json.member( "charge", charge_timer ); json.member( "ammo_loaded", ammo_loaded ); json.member( "ammo_count", ammo_count ); + json.member( "bionic_tags", bionic_tags ); if( incapacitated_time > 0_turns ) { json.member( "incapacitated_time", incapacitated_time ); } @@ -2360,6 +2389,13 @@ void bionic::deserialize( JsonIn &jsin ) if( jo.has_int( "incapacitated_time" ) ) { incapacitated_time = 1_turns * jo.get_int( "incapacitated_time" ); } + if( jo.has_array( "bionic_tags" ) ) { + JsonArray jsar = jo.get_array( "bionic_tags" ); + while( jsar.has_more() ) { + bionic_tags.insert( jsar.next_string() ); + } + } + } void player::introduce_into_anesthesia( const time_duration &duration, player &installer, diff --git a/src/bionics.h b/src/bionics.h index f499e6ad93f9d..0a7b8297f06f0 100644 --- a/src/bionics.h +++ b/src/bionics.h @@ -136,33 +136,39 @@ struct bionic_data { }; struct bionic { - bionic_id id; - int charge_timer = 0; - char invlet = 'a'; - bool powered = false; - /* Ammunition actually loaded in this bionic gun in deactivated state */ - itype_id ammo_loaded = "null"; - /* Ammount of ammo actually held inside by this bionic gun in deactivated state */ - unsigned int ammo_count = 0; - /* An amount of time during which this bionic has been rendered inoperative. */ - time_duration incapacitated_time; - - bionic() - : id( "bio_batteries" ), incapacitated_time( 0_turns ) { - } - bionic( bionic_id pid, char pinvlet ) - : id( std::move( pid ) ), invlet( pinvlet ), incapacitated_time( 0_turns ) { } - - const bionic_data &info() const { - return *id; - } - - int get_quality( const quality_id &quality ) const; - - bool is_this_fuel_powered( const itype_id &this_fuel ) const; - - void serialize( JsonOut &json ) const; - void deserialize( JsonIn &jsin ); + bionic_id id; + int charge_timer = 0; + char invlet = 'a'; + bool powered = false; + /* Ammunition actually loaded in this bionic gun in deactivated state */ + itype_id ammo_loaded = "null"; + /* Ammount of ammo actually held inside by this bionic gun in deactivated state */ + unsigned int ammo_count = 0; + /* An amount of time during which this bionic has been rendered inoperative. */ + time_duration incapacitated_time; + bionic() + : id( "bio_batteries" ), incapacitated_time( 0_turns ) { + } + bionic( bionic_id pid, char pinvlet ) + : id( std::move( pid ) ), invlet( pinvlet ), incapacitated_time( 0_turns ) { } + + const bionic_data &info() const { + return *id; + } + + void set_flag( std::string flag ); + void remove_flag( std::string flag ); + bool has_flag( std::string flag ) const ; + + int get_quality( const quality_id &quality ) const; + + bool is_this_fuel_powered( const itype_id &this_fuel ) const; + void toggle_safe_fuel_mod(); + + void serialize( JsonOut &json ) const; + void deserialize( JsonIn &jsin ); + private: + cata::flat_set bionic_tags; // generic bionic specific flags }; // A simpler wrapper to allow forward declarations of it. std::vector can not diff --git a/src/bionics_ui.cpp b/src/bionics_ui.cpp index f41d7e49576d7..204120267b5df 100644 --- a/src/bionics_ui.cpp +++ b/src/bionics_ui.cpp @@ -63,7 +63,7 @@ static void draw_bionics_titlebar( const catacurses::window &window, player *p, fuel_stream << _( "Available Fuel: " ); for( const bionic &bio : *p->my_bionics ) { for( const itype_id fuel : p->get_fuel_available( bio.id ) ) { - const item temp_fuel( fuel ) ; + const item temp_fuel( fuel ); if( temp_fuel.has_flag( "PERPETUAL" ) ) { continue; } @@ -99,9 +99,9 @@ static void draw_bionics_titlebar( const catacurses::window &window, player *p, if( mode == REASSIGNING ) { desc = _( "Reassigning.\nSelect a bionic to reassign or press SPACE to cancel." ); } else if( mode == ACTIVATING ) { - desc = _( "Activating ! to examine, = to reassign, TAB to switch tabs." ); + desc = _( "Activating ! to examine, = to reassign, TAB to switch tabs, s to toggle fuel saving mode." ); } else if( mode == EXAMINING ) { - desc = _( "Examining ! to activate, = to reassign, TAB to switch tabs." ); + desc = _( "Examining ! to activate, = to reassign, TAB to switch tabs, s to toggle fuel saving mode." ); } int n_pt_y = 0; fold_and_print( window, point( 1, n_pt_y++ ), pwr_str_pos, c_white, desc ); @@ -135,6 +135,9 @@ static std::string build_bionic_poweronly_string( const bionic &bio ) if( bio.incapacitated_time > 0_turns ) { properties.push_back( _( "(incapacitated)" ) ); } + if( !bio.has_flag( "SAFE_FUEL_OFF" ) && !bio.info().fuel_opts.empty() ) { + properties.push_back( _( "(fuel saving mode ON)" ) ); + } return enumerate_as_string( properties, enumeration_conjunction::none ); } @@ -405,6 +408,7 @@ void player::power_bionics() ctxt.register_action( "PREV_TAB" ); ctxt.register_action( "CONFIRM" ); ctxt.register_action( "HELP_KEYBINDINGS" ); + ctxt.register_action( "TOGGLE_SAFE_FUEL" ); bool recalc = false; bool redraw = true; @@ -520,6 +524,7 @@ void player::power_bionics() const int ch = ctxt.get_raw_input().get_first_input(); bionic *tmp = nullptr; bool confirmCheck = false; + bool toggle_safe_fuel = false; if( action == "DOWN" ) { redraw = true; @@ -611,6 +616,8 @@ void player::power_bionics() } else if( action == "TOGGLE_EXAMINE" ) { // switches between activation and examination menu_mode = menu_mode == ACTIVATING ? EXAMINING : ACTIVATING; redraw = true; + } else if( action == "TOGGLE_SAFE_FUEL" ) { + toggle_safe_fuel = true; } else if( action == "HELP_KEYBINDINGS" ) { redraw = true; } else if( action == "CONFIRM" ) { @@ -618,6 +625,21 @@ void player::power_bionics() } else { confirmCheck = true; } + + if( toggle_safe_fuel ) { + auto &bio_list = tab_mode == TAB_ACTIVE ? active : passive; + if( !current_bionic_list->empty() ) { + tmp = bio_list[cursor]; + if( !tmp->info().fuel_opts.empty() ) { + tmp->toggle_safe_fuel_mod(); + g->refresh_all(); + redraw = true; + } else { + popup( _( "You can't toggle fuel saving mode on a non fueled CBM." ) ); + } + + } + } //confirmation either occurred by pressing enter where the bionic cursor is, or the hotkey was selected if( confirmCheck ) { auto &bio_list = tab_mode == TAB_ACTIVE ? active : passive;