diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index 3b0c9251bd590..fd8eee5d153bd 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -6430,8 +6430,18 @@ void unload_loot_activity_actor::do_turn( player_activity &act, Character &you ) for( item *contained : it->first->all_items_top( item_pocket::pocket_type::MAGAZINE ) ) { // no liquids don't want to spill stuff if( !contained->made_of( phase_id::LIQUID ) && !contained->made_of( phase_id::GAS ) ) { + if( it->first->is_ammo_belt() ) { + if( it->first->type->magazine->linkage ) { + item link( *it->first->type->magazine->linkage, calendar::turn, contained->count() ); + here.add_item_or_charges( src_loc, link ); + } + } move_item( you, *contained, contained->count(), src_loc, src_loc, this_veh, this_part ); it->first->remove_item( *contained ); + + if( it->first->has_flag( flag_MAG_DESTROY ) && it->first->ammo_remaining() == 0 ) { + here.i_rem( src_loc, it->first ); + } } if( you.moves <= 0 ) { return; diff --git a/src/activity_item_handling.cpp b/src/activity_item_handling.cpp index 345e91138a8ce..8eaac8b30a5b3 100644 --- a/src/activity_item_handling.cpp +++ b/src/activity_item_handling.cpp @@ -2276,8 +2276,18 @@ void activity_on_turn_move_loot( player_activity &act, Character &you ) for( item *contained : it->first->all_items_top( item_pocket::pocket_type::MAGAZINE ) ) { // no liquids don't want to spill stuff if( !contained->made_of( phase_id::LIQUID ) && !contained->made_of( phase_id::GAS ) ) { + if( it->first->is_ammo_belt() ) { + if( it->first->type->magazine->linkage ) { + item link( *it->first->type->magazine->linkage, calendar::turn, contained->count() ); + here.add_item_or_charges( src_loc, link ); + } + } move_item( you, *contained, contained->count(), src_loc, src_loc, this_veh, this_part ); it->first->remove_item( *contained ); + + if( it->first->has_flag( flag_MAG_DESTROY ) && it->first->ammo_remaining() == 0 ) { + here.i_rem( src_loc, it->first ); + } } } for( item *contained : it->first->all_items_top( item_pocket::pocket_type::MAGAZINE_WELL ) ) { diff --git a/tests/clzones_test.cpp b/tests/clzones_test.cpp index f8c95494b0e2d..af19dbf7aaee8 100644 --- a/tests/clzones_test.cpp +++ b/tests/clzones_test.cpp @@ -1,22 +1,41 @@ #include #include +#include "activity_actor_definitions.h" #include "cata_catch.h" #include "clzones.h" #include "item.h" #include "item_category.h" #include "item_pocket.h" #include "map_helpers.h" +#include "player_helpers.h" #include "point.h" #include "ret_val.h" #include "type_id.h" static const faction_id faction_your_followers( "your_followers" ); +static const itype_id itype_556( "556" ); +static const itype_id itype_ammolink223( "ammolink223" ); +static const itype_id itype_belt223( "belt223" ); + static const zone_type_id zone_type_LOOT_DRINK( "LOOT_DRINK" ); static const zone_type_id zone_type_LOOT_FOOD( "LOOT_FOOD" ); static const zone_type_id zone_type_LOOT_PDRINK( "LOOT_PDRINK" ); static const zone_type_id zone_type_LOOT_PFOOD( "LOOT_PFOOD" ); +static const zone_type_id zone_type_zone_unload_all( "zone_unload_all" ); + +static int count_items_or_charges( const tripoint src, const itype_id &id ) +{ + int n = 0; + map_stack items = get_map().i_at( src ); + for( const item &it : items ) { + if( it.typeId() == id ) { + n += it.count(); + } + } + return n; +} static void create_tile_zone( const std::string &name, const zone_type_id &zone_type, tripoint pos ) { @@ -24,6 +43,39 @@ static void create_tile_zone( const std::string &name, const zone_type_id &zone_ zm.add( name, zone_type, faction_your_followers, false, true, pos, pos ); } +TEST_CASE( "zone unloading ammo belts", "[zones][items][ammo_belt][activities][unload]" ) +{ + avatar &dummy = get_avatar(); + map &here = get_map(); + + clear_avatar(); + clear_map(); + + tripoint_abs_ms const start = here.getglobal( tripoint_east ); + dummy.set_location( start ); + create_tile_zone( "Unload All", zone_type_zone_unload_all, start.raw() ); + + item ammo_belt = item( itype_belt223, calendar::turn ); + ammo_belt.ammo_set( ammo_belt.ammo_default() ); + int belt_ammo_count_before_unload = ammo_belt.ammo_remaining(); + + REQUIRE( belt_ammo_count_before_unload > 0 ); + + WHEN( "unloading ammo belts using zone_unload_all " ) { + here.add_item_or_charges( tripoint_east, ammo_belt ); + dummy.assign_activity( + player_activity( unload_loot_activity_actor() ) ); + process_activity( dummy ); + + THEN( "check that the ammo and linkages are both unloaded and the ammo belt is removed" ) { + CHECK( count_items_or_charges( tripoint_east, itype_belt223 ) == 0 ); + CHECK( count_items_or_charges( tripoint_east, + itype_ammolink223 ) == belt_ammo_count_before_unload ); + CHECK( count_items_or_charges( tripoint_east, itype_556 ) == belt_ammo_count_before_unload ); + } + } +} + // Comestibles sorting is a bit awkward. Unlike other loot, they're almost // always inside of a container, and their sort zone changes based on their // shelf life and whether the container prevents rotting.