diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 7bc6b7605700a..8594c832bdde4 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -2566,13 +2566,21 @@ int holster_actor::use( player &p, item &it, bool, const tripoint & ) const return string_format( _( "Draw %s" ), elem.display_name() ); } ); + item *internal_item = nullptr; if( opts.size() > 1 ) { - const int ret = uilist( string_format( _( "Use %s" ), it.tname() ), opts ); + int ret = uilist( string_format( _( "Use %s" ), it.tname() ), opts ); if( ret < 0 ) { pos = -2; } else { pos += ret; + if( opts.size() != it.contents.size() ) { + ret--; + } + auto iter = std::next( it.contents.begin(), ret ); + internal_item = &*iter; } + } else { + internal_item = &it.contents.front(); } if( pos < -1 ) { @@ -2583,13 +2591,13 @@ int holster_actor::use( player &p, item &it, bool, const tripoint & ) const if( pos >= 0 ) { // worn holsters ignore penalty effects (e.g. GRABBED) when determining number of moves to consume if( p.is_worn( it ) ) { - p.wield_contents( it, pos, false, draw_cost ); + p.wield_contents( it, internal_item, false, draw_cost ); } else { - p.wield_contents( it, pos ); + p.wield_contents( it, internal_item ); } } else { - auto loc = game_menus::inv::holster( p, it ); + item_location loc = game_menus::inv::holster( p, it ); if( !loc ) { p.add_msg_if_player( _( "Never mind." ) ); diff --git a/src/player.cpp b/src/player.cpp index b197d4d7a293c..f4442dbf39833 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -6300,32 +6300,35 @@ std::string player::weapname( unsigned int truncate ) const } } -bool player::wield_contents( item &container, int pos, bool penalties, int base_cost ) +bool player::wield_contents( item &container, item *internal_item, bool penalties, int base_cost ) { // if index not specified and container has multiple items then ask the player to choose one - if( pos < 0 ) { + if( internal_item == nullptr ) { std::vector opts; std::transform( container.contents.begin(), container.contents.end(), std::back_inserter( opts ), []( const item & elem ) { return elem.display_name(); } ); if( opts.size() > 1 ) { - pos = uilist( _( "Wield what?" ), opts ); + int pos = uilist( _( "Wield what?" ), opts ); if( pos < 0 ) { return false; } } else { - pos = 0; + internal_item = &container.contents.front(); } } - if( pos >= static_cast( container.contents.size() ) ) { + const bool has = std::any_of( container.contents.begin(), + container.contents.end(), [internal_item]( const item & it ) { + return internal_item == ⁢ + } ); + if( !has ) { debugmsg( "Tried to wield non-existent item from container (player::wield_contents)" ); return false; } - auto target = std::next( container.contents.begin(), pos ); - const auto ret = can_wield( *target ); + const ret_val ret = can_wield( *internal_item ); if( !ret.success() ) { add_msg_if_player( m_info, "%s", ret.c_str() ); return false; @@ -6340,8 +6343,10 @@ bool player::wield_contents( item &container, int pos, bool penalties, int base_ inv.unsort(); } - weapon = std::move( *target ); - container.contents.erase( target ); + weapon = std::move( *internal_item ); + container.contents.remove_if( [internal_item]( const item & it ) { + return internal_item == ⁢ + } ); container.on_contents_changed(); inv.update_invlet( weapon ); diff --git a/src/player.h b/src/player.h index cb610b69c3932..47eefb8e821fa 100644 --- a/src/player.h +++ b/src/player.h @@ -821,7 +821,7 @@ class player : public Character * @param penalties Whether item volume and temporary effects (e.g. GRABBED, DOWNED) should be considered. * @param base_cost Cost due to storage type. */ - bool wield_contents( item &container, int pos = 0, bool penalties = true, + bool wield_contents( item &container, item *internal_item = nullptr, bool penalties = true, int base_cost = INVENTORY_HANDLING_PENALTY ); /** * Stores an item inside another consuming moves proportional to weapon skill and volume