Skip to content

Commit

Permalink
Not to try to reload a gun without default ammo type defined (#73714)
Browse files Browse the repository at this point in the history
* Should not reload a gun without ammo defined.

* Update src/item_location.cpp

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
osuphobia and github-actions[bot] authored May 12, 2024
1 parent 740475c commit 46926a4
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/character_ammo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ bool Character::list_ammo( const item_location &base, std::vector<item::reload_o
int ammo_search_range = is_mounted() ? -1 : 1;
for( item_location &p : opts ) {
for( item_location &ammo : find_ammo( *p, empty, ammo_search_range ) ) {
if( p->can_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 ) );
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9998,7 +9998,7 @@ static item::reload_option favorite_ammo_or_select( avatar &u, item_location &lo
std::vector<item::reload_option> 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() ) {
Expand Down
8 changes: 4 additions & 4 deletions src/game_inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions src/inventory_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) ) {
Expand All @@ -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();
Expand Down
14 changes: 14 additions & 0 deletions src/item_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,3 +1157,17 @@ std::unique_ptr<talker> get_talker_for( item_location *it )
return std::make_unique<talker_item>( 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 );
}
7 changes: 7 additions & 0 deletions src/item_location.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions tests/player_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,15 @@ 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 {
const itype_id magazine_id = gun->magazine_default();
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 ) );
Expand Down
4 changes: 2 additions & 2 deletions tests/reloading_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand All @@ -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" ) {
Expand Down

0 comments on commit 46926a4

Please sign in to comment.