diff --git a/src/avatar_action.cpp b/src/avatar_action.cpp index 114364d66c1ec..958794943f2a9 100644 --- a/src/avatar_action.cpp +++ b/src/avatar_action.cpp @@ -1150,7 +1150,7 @@ void avatar_action::use_item( avatar &you, item_location &loc, std::string const // Get the parent pocket before the item is obtained. if( loc.has_parent() ) { - parent_pocket = loc.parent_item().get_item()->contained_where( *loc ); + parent_pocket = loc.parent_pocket(); } loc = loc.obtain( you, 1 ); diff --git a/src/character.cpp b/src/character.cpp index eca2c5f8dc972..a86d82a20d89b 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -9102,7 +9102,7 @@ ret_val Character::can_crush_frozen_liquid( item_location loc ) { crush_tool_type tool_type = CRUSH_NO_TOOL; bool success = false; - if( !loc.has_parent() || !loc.parent_item()->contained_where( *loc )->get_pocket_data()->rigid ) { + if( !loc.has_parent() || !loc.parent_pocket()->get_pocket_data()->rigid ) { tool_type = CRUSH_HAMMER; success = has_quality( qual_HAMMER ); } else { diff --git a/src/character_inventory.cpp b/src/character_inventory.cpp index af05871a55039..ad8da8e0e9ac3 100644 --- a/src/character_inventory.cpp +++ b/src/character_inventory.cpp @@ -89,7 +89,7 @@ void Character::handle_contents_changed( const std::vector &conta if( loc.has_parent() ) { item_location parent_loc = loc.parent_item(); item_loc_with_depth parent( parent_loc ); - item_pocket *const pocket = parent_loc->contained_where( *loc ); + item_pocket *const pocket = loc.parent_pocket(); pocket->unseal(); bool exists = false; auto it = sorted_containers.lower_bound( parent ); diff --git a/src/contents_change_handler.cpp b/src/contents_change_handler.cpp index fc28f057b9f31..468ef03afdae4 100644 --- a/src/contents_change_handler.cpp +++ b/src/contents_change_handler.cpp @@ -12,7 +12,7 @@ void contents_change_handler::unseal_pocket_containing( const item_location &loc { if( loc.has_parent() ) { item_location parent = loc.parent_item(); - item_pocket *const pocket = parent->contained_where( *loc ); + item_pocket *const pocket = loc.parent_pocket(); if( pocket ) { // on_contents_changed restacks the pocket and should be called later // in Character::handle_contents_changed diff --git a/src/game.cpp b/src/game.cpp index 913e7aabc6c7e..d16c35ac5cdd5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2135,7 +2135,7 @@ int game::inventory_item_menu( item_location locThisItem, oThisItem.is_favorite = !oThisItem.is_favorite; if( locThisItem.has_parent() ) { item_location parent = locThisItem.parent_item(); - item_pocket *const pocket = parent->contained_where( oThisItem ); + item_pocket *const pocket = locThisItem.parent_pocket(); if( pocket ) { pocket->restack(); } else { diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 4779ea6b7129e..c09dd77b780e3 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -707,7 +707,7 @@ class comestible_inventory_preset : public inventory_selector_preset item_location temp = loc; // check if at least one parent container is sealed while( temp.has_parent() ) { - item_pocket *pocket = temp.parent_item()->contained_where( *temp.get_item() ); + item_pocket *pocket = temp.parent_pocket(); if( pocket->sealed() ) { sealed = _( "sealed" ); break; @@ -795,7 +795,7 @@ class comestible_inventory_preset : public inventory_selector_preset } else if( time == 0_turns ) { return 4; } else if( loc.has_parent() && - loc.parent_item()->contained_where( *loc )->spoil_multiplier() == 0.0f ) { + loc.parent_pocket()->spoil_multiplier() == 0.0f ) { return 3; } else { return 2; diff --git a/src/handle_action.cpp b/src/handle_action.cpp index 80684a8518c2d..84d2c1fcf73fb 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -2380,7 +2380,6 @@ bool game::do_regular_action( action_id &act, avatar &player_character, } else { drop_in_direction( *pnt ); } - drop_in_direction( *pnt ); } break; case ACTION_BIONICS: diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index ddfe2526e6c35..e5b00b768db4f 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -177,7 +177,7 @@ bool is_worn_ablative( item_location const &container, item_location const &chil // if the item is in an ablative pocket then put it with the item it is in // first do a short circuit test if the parent has ablative pockets at all return container->is_ablative() && container->is_worn_by_player() && - container->contained_where( *child )->get_pocket_data()->ablative; + child.parent_pocket()->get_pocket_data()->ablative; } /** The maximum distance from the screen edge, to snap a window to it */ @@ -508,11 +508,10 @@ bool inventory_entry::is_hidden( cata::optional const &hide_entries_overri return *hide_entries_override; } while( item.has_parent() && item != topmost_parent ) { - item_location parent = item.parent_item(); - if( parent.get_item()->contained_where( *item )->settings.is_collapsed() ) { + if( item.parent_pocket()->settings.is_collapsed() ) { return true; } - item = parent; + item = item.parent_item(); } return false; } diff --git a/src/item_location.cpp b/src/item_location.cpp index 9b9a74bc202ab..5559379e30549 100644 --- a/src/item_location.cpp +++ b/src/item_location.cpp @@ -85,6 +85,9 @@ class item_location::impl virtual item_location parent_item() const { return item_location(); } + virtual item_pocket *parent_pocket() const { + return nullptr; + } virtual tripoint position() const = 0; virtual std::string describe( const Character * ) const = 0; virtual item_location obtain( Character &, int ) = 0; @@ -564,6 +567,7 @@ class item_location::impl::item_in_container : public item_location::impl { private: item_location container; + mutable item_pocket *container_pkt = nullptr; // figures out the index for the item, which is where it is in the total list of contents // note: could be a better way of handling this? @@ -588,6 +592,18 @@ class item_location::impl::item_in_container : public item_location::impl return container; } + item_pocket *parent_pocket() const override { + if( container_pkt == nullptr ) { + std::vector const pkts = parent_item()->get_all_standard_pockets(); + if( pkts.size() == 1 ) { + container_pkt = pkts.front(); + } else { + container_pkt = parent_item()->contained_where( *target() ); + } + } + return container_pkt; + } + item_in_container( const item_location &container, item *which ) : impl( which ), container( container ) {} @@ -718,11 +734,11 @@ class item_location::impl::item_in_container : public item_location::impl } units::volume volume_capacity() const override { - return container->contained_where( *target() )->remaining_volume(); + return parent_pocket()->remaining_volume(); } units::mass weight_capacity() const override { - return container->contained_where( *target() )->remaining_weight(); + return parent_pocket()->remaining_weight(); } bool check_parent_capacity_recursive() const override { @@ -846,6 +862,14 @@ item_location item_location::parent_item() const return item_location::nowhere; } +item_pocket *item_location::parent_pocket() const +{ + if( where() == type::container ) { + return ptr->parent_pocket(); + } + return nullptr; +} + bool item_location::has_parent() const { if( where() == type::container ) { @@ -861,7 +885,7 @@ bool item_location::parents_can_contain_recursive( item *it ) const } item_location parent = parent_item(); - item_pocket *pocket = parent->contained_where( *get_item() ); + item_pocket *pocket = parent_pocket(); if( pocket->can_contain( *it ).success() ) { return parent.parents_can_contain_recursive( it ); @@ -877,7 +901,7 @@ int item_location::max_charges_by_parent_recursive( const item &it ) const } item_location parent = parent_item(); - item_pocket *pocket = parent->contained_where( *get_item() ); + item_pocket *pocket = parent_pocket(); return std::min( { it.charges_per_volume( pocket->remaining_volume() ), it.charges_per_weight( pocket->remaining_weight() ), diff --git a/src/item_location.h b/src/item_location.h index 77fddaa9a7167..c94fd0ded0a24 100644 --- a/src/item_location.h +++ b/src/item_location.h @@ -14,6 +14,7 @@ class character_id; class JsonObject; class JsonOut; class item; +class item_pocket; class map_cursor; class vehicle_cursor; class talker; @@ -106,6 +107,7 @@ class item_location /** returns the parent item, or an invalid location if it has no parent */ item_location parent_item() const; + item_pocket *parent_pocket() const; /** returns true if the item is in the inventory of the given character **/ bool held_by( Character const &who ) const; diff --git a/tests/unseal_and_spill_test.cpp b/tests/unseal_and_spill_test.cpp index 45fd1c93c73f6..1aaa8cc307dea 100644 --- a/tests/unseal_and_spill_test.cpp +++ b/tests/unseal_and_spill_test.cpp @@ -256,7 +256,7 @@ void match( Parent &&parent, Container &&contents, match( content_loc, content_result ); item_location container = container_from_parent( parent ); if( container ) { - item_pocket *pocket = container->contained_where( *content ); + item_pocket *pocket = content_loc.parent_pocket(); REQUIRE( pocket ); CHECK( content_result.parent_pocket_sealed == pocket->sealed() ); }