diff --git a/src/character_ammo.cpp b/src/character_ammo.cpp index b1477346a656b..0dc483fca95bf 100644 --- a/src/character_ammo.cpp +++ b/src/character_ammo.cpp @@ -104,14 +104,14 @@ bool Character::list_ammo( const item_location &base, std::vectorcan_reload_with( *ammo.get_item(), false ) ) { + if( p.can_reload_with( ammo, false ) ) { // Record that there's a matching ammo type, // even if something is preventing reloading at the moment. ammo_match_found = true; } else if( ( ammo->has_flag( flag_SPEEDLOADER ) || ammo->has_flag( flag_SPEEDLOADER_CLIP ) ) && p->allows_speedloader( ammo->typeId() ) && ammo->ammo_remaining() > 1 && p->ammo_remaining() < 1 ) { // Again, this is "are they compatible", later check handles "can we do it now". - ammo_match_found = p->can_reload_with( *ammo.get_item(), false ); + ammo_match_found = p.can_reload_with( ammo, false ); } if( can_reload( *p, ammo.get_item() ) ) { ammo_list.emplace_back( this, p, std::move( ammo ) ); diff --git a/src/game.cpp b/src/game.cpp index 227662390cf6d..9595e3c56b6bd 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -9998,7 +9998,7 @@ static item::reload_option favorite_ammo_or_select( avatar &u, item_location &lo std::vector ammo_list; if( u.list_ammo( loc, ammo_list, false ) ) { const auto is_favorite_and_compatible = [&loc, &u]( const item::reload_option & opt ) { - return opt.ammo == u.ammo_location && loc->can_reload_with( *u.ammo_location.get_item(), false ); + return opt.ammo == u.ammo_location && loc.can_reload_with( u.ammo_location, false ); }; auto it = std::find_if( ammo_list.begin(), ammo_list.end(), is_favorite_and_compatible ); if( it != ammo_list.end() ) { diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 1783434af7f54..2a964dc129a20 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -2803,7 +2803,7 @@ class select_ammo_inventory_preset : public inventory_selector_preset append_cell( [&you, target]( const item_location & loc ) { for( const item_location &opt : get_possible_reload_targets( target ) ) { - if( opt->can_reload_with( *loc, true ) ) { + if( opt.can_reload_with( loc, true ) ) { if( opt == target ) { return std::string(); } @@ -2871,11 +2871,11 @@ class select_ammo_inventory_preset : public inventory_selector_preset for( item_location &p : opts ) { if( ( loc->has_flag( flag_SPEEDLOADER ) && p->allows_speedloader( loc->typeId() ) && - loc->ammo_remaining() > 1 && p->ammo_remaining() < 1 ) && p->can_reload_with( *loc, true ) ) { + loc->ammo_remaining() > 1 && p->ammo_remaining() < 1 ) && p.can_reload_with( loc, true ) ) { return true; } - if( p->can_reload_with( *loc, true ) ) { + if( p.can_reload_with( loc, true ) ) { return true; } } @@ -2944,7 +2944,7 @@ item::reload_option game_menus::inv::select_ammo( Character &you, const item_loc item_location target_loc; for( const item_location &opt : get_possible_reload_targets( loc ) ) { - if( opt->can_reload_with( *selected.first, true ) ) { + if( opt.can_reload_with( selected.first, true ) ) { target_loc = opt; break; } diff --git a/src/inventory_ui.cpp b/src/inventory_ui.cpp index ab2fca1330749..9c9448aee6c34 100644 --- a/src/inventory_ui.cpp +++ b/src/inventory_ui.cpp @@ -3381,7 +3381,7 @@ void ammo_inventory_selector::set_all_entries_chosen_count() for( inventory_entry *entry : col->get_entries( return_item, true ) ) { for( const item_location &loc : get_possible_reload_targets( reload_loc ) ) { item_location it = entry->any_item(); - if( loc->can_reload_with( *it, true ) ) { + if( loc.can_reload_with( it, true ) ) { item::reload_option tmp_opt( &u, loc, it ); int count = entry->get_available_count(); if( it->has_flag( flag_SPEEDLOADER ) || it->has_flag( flag_SPEEDLOADER_CLIP ) ) { @@ -3402,7 +3402,7 @@ void ammo_inventory_selector::mod_chosen_count( inventory_entry &entry, int valu return; } for( const item_location &loc : get_possible_reload_targets( reload_loc ) ) { - if( loc->can_reload_with( *entry.any_item(), true ) ) { + if( loc.can_reload_with( entry.any_item(), true ) ) { item::reload_option tmp_opt( &u, loc, entry.any_item() ); tmp_opt.qty( entry.chosen_count + value ); entry.chosen_count = tmp_opt.qty(); diff --git a/src/item_location.cpp b/src/item_location.cpp index 6327745e99ed6..1c8cc36387e6d 100644 --- a/src/item_location.cpp +++ b/src/item_location.cpp @@ -1157,3 +1157,17 @@ std::unique_ptr get_talker_for( item_location *it ) return std::make_unique( it ); } +bool item_location::can_reload_with( const item_location &ammo, bool now ) const +{ + const item_location reloadable = *this; + if( reloadable->is_gun() && !reloadable->ammo_default() ) { + return false; + } else if( reloadable->is_magazine() ) { + if( reloadable.has_parent() ) { + if( reloadable.parent_item()->is_gun() && !reloadable.parent_item()->ammo_default() ) { + return false; + } + } + } + return reloadable->can_reload_with( *ammo, now ); +} \ No newline at end of file diff --git a/src/item_location.h b/src/item_location.h index e89b226c53700..51e1e1e7edbf3 100644 --- a/src/item_location.h +++ b/src/item_location.h @@ -154,6 +154,13 @@ class item_location */ void overflow(); + /** + * returns whether the item can be reloaded with the specified item. + * @param ammo item to be loaded in + * @param now whether the currently contained ammo/magazine should be taken into account + */ + bool can_reload_with( const item_location &ammo, bool now ) const; + private: class impl; diff --git a/tests/player_helpers.cpp b/tests/player_helpers.cpp index fddc12ca75060..5f60e02f0a495 100644 --- a/tests/player_helpers.cpp +++ b/tests/player_helpers.cpp @@ -180,7 +180,7 @@ void arm_shooter( Character &shooter, const std::string &gun_type, if( gun->magazine_integral() ) { item_location ammo = shooter.i_add( item( ammo_id, calendar::turn, gun->ammo_capacity( type_of_ammo ) ) ); - REQUIRE( gun->can_reload_with( *ammo, true ) ); + REQUIRE( gun.can_reload_with( ammo, true ) ); REQUIRE( shooter.can_reload( *gun, &*ammo ) ); gun->reload( shooter, ammo, gun->ammo_capacity( type_of_ammo ) ); } else { @@ -188,7 +188,7 @@ void arm_shooter( Character &shooter, const std::string &gun_type, item_location magazine = shooter.i_add( item( magazine_id ) ); item_location ammo = shooter.i_add( item( ammo_id, calendar::turn, magazine->ammo_capacity( type_of_ammo ) ) ); - REQUIRE( magazine->can_reload_with( *ammo, true ) ); + REQUIRE( magazine.can_reload_with( ammo, true ) ); REQUIRE( shooter.can_reload( *magazine, &*ammo ) ); magazine->reload( shooter, ammo, magazine->ammo_capacity( type_of_ammo ) ); gun->reload( shooter, magazine, magazine->ammo_capacity( type_of_ammo ) ); diff --git a/tests/reloading_test.cpp b/tests/reloading_test.cpp index 6dd22f8d0e846..7c953e3f237bd 100644 --- a/tests/reloading_test.cpp +++ b/tests/reloading_test.cpp @@ -923,7 +923,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) dummy.set_wielded_item( item( "sw_610", calendar::turn_zero, 0 ) ); REQUIRE( dummy.get_wielded_item()->ammo_remaining() == 0 ); - REQUIRE( dummy.get_wielded_item()->can_reload_with( *ammo, false ) ); + REQUIRE( dummy.get_wielded_item().can_reload_with( ammo, false ) ); WHEN( "the player triggers auto reload until the revolver is full" ) { reload_a_revolver( dummy, *dummy.get_wielded_item(), *ammo ); @@ -937,7 +937,7 @@ TEST_CASE( "automatic_reloading_action", "[reload],[gun]" ) GIVEN( "the player has another gun with ammo" ) { item_location gun2 = dummy.i_add( item( "sw_610", calendar::turn_zero, 0 ) ); REQUIRE( gun2->ammo_remaining() == 0 ); - REQUIRE( gun2->can_reload_with( *ammo, false ) ); + REQUIRE( gun2.can_reload_with( ammo, false ) ); WHEN( "the player triggers auto reload until the first revolver is full" ) { reload_a_revolver( dummy, *dummy.get_wielded_item(), *ammo ); WHEN( "the player triggers auto reload until the second revolver is full" ) {