diff --git a/data/raw/keybindings.json b/data/raw/keybindings.json index 34b2d8439ec96..2aaf10504f9e2 100644 --- a/data/raw/keybindings.json +++ b/data/raw/keybindings.json @@ -4258,6 +4258,13 @@ "id": "morale", "bindings": [ { "input_method": "keyboard_any", "key": "m" } ] }, + { + "type": "keybinding", + "id": "CHANGE_ARMOR_SPRITE", + "category": "PLAYER_INFO", + "name": "Change sprite of armor.", + "bindings": [ { "input_method": "keyboard_char", "key": "W" }, { "input_method": "keyboard_code", "key": "w", "mod": [ "shift" ] } ] + }, { "type": "keybinding", "category": "WISH_ITEM", diff --git a/src/character_attire.cpp b/src/character_attire.cpp index 1339c94ab7b91..e2ee7d3dd7a21 100644 --- a/src/character_attire.cpp +++ b/src/character_attire.cpp @@ -1791,8 +1791,13 @@ void outfit::get_overlay_ids( std::vector> & if( worn_item.has_flag( json_flag_HIDDEN ) ) { continue; } - const std::string variant = worn_item.has_itype_variant() ? worn_item.itype_variant().id : ""; - overlay_ids.emplace_back( "worn_" + worn_item.typeId().str(), variant ); + if( worn_item.has_var( "sprite_override" ) ) { + overlay_ids.emplace_back( "worn_" + worn_item.get_var( "sprite_override" ), + worn_item.get_var( "sprite_override_variant", "" ) ); + } else { + const std::string variant = worn_item.has_itype_variant() ? worn_item.itype_variant().id : ""; + overlay_ids.emplace_back( "worn_" + worn_item.typeId().str(), variant ); + } } } diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 6e21f5816047e..a010956685fad 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -2545,3 +2545,38 @@ item_location game_menus::inv::install_bionic( Character &you, Character &patien } } + +class change_sprite_inventory_preset: public inventory_selector_preset +{ + public: + explicit change_sprite_inventory_preset( Character &pl ) : + you( pl ) { + append_cell( []( const item_location & loc ) -> std::string { + if( loc->has_var( "sprite_override" ) ) { + const itype_id sprite_override( std::string( loc->get_var( "sprite_override" ) ) ); + const std::string variant = loc->get_var( "sprite_override_variant" ); + if( !item::type_is_defined( sprite_override ) ) { + return _( "Unknown" ); + } + item tmp( sprite_override ); + tmp.set_itype_variant( variant ); + return tmp.tname(); + } + return _( "Default" ); + }, _( "Shown as" ) ); + } + + bool is_shown( const item_location &loc ) const override { + return loc->is_armor(); + } + + protected: + Character &you; +}; + +item_location game_menus::inv::change_sprite( Character &you ) +{ + return inv_internal( you, change_sprite_inventory_preset( you ), + _( "Change appearance of your armor:" ), -1, + _( "You have nothing to wear." ) ); +} diff --git a/src/game_inventory.h b/src/game_inventory.h index e40e2fd12605a..06a74bccb856a 100644 --- a/src/game_inventory.h +++ b/src/game_inventory.h @@ -146,6 +146,8 @@ item_location repair( Character &you, const repair_item_actor *actor, const item item_location install_bionic( Character &you, Character &patient, bool surgeon = false ); /**Autoclave sterilize menu*/ item_location sterilize_cbm( Character &you ); +/** Change sprite menu. */ +item_location change_sprite( Character &you ); /*@}*/ } // namespace inv diff --git a/src/player_display.cpp b/src/player_display.cpp index 2798906bc15a0..befd61f01b5ef 100644 --- a/src/player_display.cpp +++ b/src/player_display.cpp @@ -25,7 +25,9 @@ #include "flag.h" #include "enum_conversions.h" #include "game.h" +#include "game_inventory.h" #include "input.h" +#include "itype.h" #include "localized_comparator.h" #include "mutation.h" #include "options.h" @@ -1178,6 +1180,46 @@ static void on_customize_character( Character &you ) } } +static void change_armor_sprite( avatar &you ) +{ + item_location target_loc; + target_loc = game_menus::inv::change_sprite( you ); + if( target_loc && target_loc.get_item() ) { + item *target_item = target_loc.get_item(); + + uilist menu; + menu.title = _( "Change sprite" ); + menu.addentry( 0, true, MENU_AUTOASSIGN, _( "Select sprite from items" ) ); + menu.addentry( 1, true, MENU_AUTOASSIGN, _( "Restore default sprite" ) ); + menu.addentry( 2, true, MENU_AUTOASSIGN, _( "Cancel" ) ); + + menu.query(); + if( menu.ret == 0 ) { + item_location sprite_loc; + avatar *you = get_player_character().as_avatar(); + auto armor_filter = [&]( const item & i ) { + return i.is_armor(); + }; + if( you != nullptr ) { + sprite_loc = game_menus::inv::titled_filter_menu( armor_filter, + *you, + _( "Select appearance of this armor:" ), + -1, + _( "You have nothing to wear." ) ); + } + if( sprite_loc && sprite_loc.get_item() ) { + const item *sprite_item = sprite_loc.get_item(); + const std::string variant = sprite_item->has_itype_variant() ? sprite_item->itype_variant().id : ""; + target_item->set_var( "sprite_override", sprite_item->typeId().str() ); + target_item->set_var( "sprite_override_variant", variant ); + } + } else if( menu.ret == 1 ) { + target_item->erase_var( "sprite_override" ); + target_item->erase_var( "sprite_override_variant" ); + } + } +} + static int get_line_count( player_display_tab curtab, Character &you, const std::vector &speedlist, @@ -1433,6 +1475,10 @@ static bool handle_player_display_action( Character &you, unsigned int &line, if( you.is_avatar() ) { you.as_avatar()->disp_medical(); } + } else if( action == "CHANGE_ARMOR_SPRITE" ) { + if( you.as_avatar() ) { + change_armor_sprite( *you.as_avatar() ); + } } return done; } @@ -1644,6 +1690,7 @@ void Character::disp_info( bool customize_character ) ctxt.register_action( "SELECT_TRAIT_VARIANT" ); ctxt.register_action( "HELP_KEYBINDINGS" ); ctxt.register_action( "MEDICAL_MENU" ); + ctxt.register_action( "CHANGE_ARMOR_SPRITE" ); std::map speed_effects; for( auto &elem : *effects ) {