Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gun-mounted ammo holders #70858

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions data/json/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -2387,5 +2387,10 @@
"id": "BLEEDSLOW2",
"type": "json_flag",
"info": "The character bleeds even slower than normal, losing blood at 1/3rd the normal rate."
},
{
"id": "NOT_MAGAZINE",
"type": "json_flag",
"//": "Skips a check in Character::list_ammo that would otherwise prevent items here from being used to reload a gun."
}
]
122 changes: 122 additions & 0 deletions data/json/items/gunmod/accessories.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,127 @@
"location": "belt clip",
"mod_targets": [ "rugerlcp", "kp32", "kp3at", "kpf9", "cop_38", "moss_brownie" ],
"flags": [ "IS_ARMOR", "SKINTIGHT", "WATER_FRIENDLY" ]
},
{
"id": "12ga_shell_holder_stock",
"type": "GUNMOD",
"name": { "str": "stock-mounted shell holder" },
"description": "Designed to be strapped to the side of a shotgun's stock, this polymer shotshell holder can store five 12 gauge shells for easy reloading.",
"weight": "50 g",
"volume": "350 ml",
"price": 2000,
"price_postapoc": 50,
"install_time": "30 s",
"material": [ "plastic" ],
"flags": [ "NOT_MAGAZINE" ],
"symbol": ":",
"color": "black",
"location": "stock accessory",
"mod_targets": [ "shotgun" ],
"pocket_data": [
{
"pocket_type": "CONTAINER",
"rigid": true,
"max_contains_volume": "100 ml",
"max_contains_weight": "250 g",
"ammo_restriction": { "shot": 5 },
"moves": 25
}
],
"pocket_mods": [
{
"pocket_type": "CONTAINER",
"rigid": true,
"max_contains_volume": "100 ml",
"max_contains_weight": "250 g",
"ammo_restriction": { "shot": 5 },
"moves": 25
}
],
"min_skills": [ [ "weapon", 1 ] ]
},
{
"id": "12ga_shell_holder_stock_leather",
"type": "GUNMOD",
"name": { "str": "stock-mounted leather shell holder" },
"description": "Designed to be strapped to the side of a shotgun's stock, this leather shotshell holder can store five 12 gauge shells for easy reloading.",
"weight": "16 g",
"volume": "60 ml",
"price": 2000,
"price_postapoc": 50,
"install_time": "30 s",
"material": [ "leather" ],
"flags": [ "NOT_MAGAZINE" ],
"symbol": ":",
"color": "brown",
"location": "stock accessory",
"mod_targets": [ "shotgun" ],
"pocket_mods": [
{
"pocket_type": "CONTAINER",
"rigid": true,
"max_contains_volume": "100 ml",
"max_contains_weight": "250 g",
"ammo_restriction": { "shot": 5 },
"moves": 25
}
],
"min_skills": [ [ "weapon", 1 ] ]
},
{
"id": "rifle_cart_holder_stock",
"type": "GUNMOD",
"name": { "str": "stock-mounted cartridge holder" },
"description": "Designed to be strapped to the side of a rifle's stock, this polymer cartridge holder can store seven rounds for easy reloading. Fits most larger calibers.",
"weight": "16 g",
"volume": "60 ml",
"price": 2000,
"price_postapoc": 50,
"install_time": "30 s",
"material": [ "plastic" ],
"flags": [ "NOT_MAGAZINE" ],
"symbol": ":",
"color": "black",
"location": "stock accessory",
"mod_targets": [ "rifle" ],
"pocket_mods": [
{
"pocket_type": "CONTAINER",
"rigid": true,
"max_contains_volume": "100 ml",
"max_contains_weight": "250 g",
"ammo_restriction": { "338lapua": 7, "3007": 7, "300": 7, "308": 7, "762R": 7, "77mm_arisaka": 7, "762": 7, "50": 7, "30carbine": 7, "223": 7, "123ln": 7, "303": 7 },
"moves": 25
}
],
"min_skills": [ [ "weapon", 1 ] ]
},
{
"id": "rifle_cart_holder_stock_leather",
"type": "GUNMOD",
"name": { "str": "stock-mounted leather cartridge holder" },
"description": "Designed to be strapped to the side of a rifle's stock, this leather cartridge holder can store seven rounds for easy reloading. Fits most larger calibers.",
"weight": "16 g",
"volume": "60 ml",
"price": 2000,
"price_postapoc": 50,
"install_time": "30 s",
"material": [ "leather" ],
"flags": [ "NOT_MAGAZINE" ],
"symbol": ":",
"color": "brown",
"location": "stock accessory",
"mod_targets": [ "rifle" ],
"pocket_mods": [
{
"pocket_type": "CONTAINER",
"rigid": true,
"max_contains_volume": "100 ml",
"max_contains_weight": "250 g",
"ammo_restriction": { "338lapua": 7, "3007": 7, "300": 7, "308": 7, "762R": 7, "77mm_arisaka": 7, "762": 7, "50": 7, "30carbine": 7, "223": 7, "123ln": 7, "303": 7 },
"moves": 25
}
],
"min_skills": [ [ "weapon", 1 ] ]
}
]
6 changes: 4 additions & 2 deletions src/activity_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ void gunmod_remove_activity_actor::finish( player_activity &act, Character &who

bool gunmod_remove_activity_actor::gunmod_unload( Character &who, item &gunmod )
{
if( gunmod.has_flag( flag_BRASS_CATCHER ) ) {
if( gunmod.has_flag( flag_BRASS_CATCHER ) || gunmod.has_flag( flag_NOT_MAGAZINE ) ) {
// Exclude brass catchers so that removing them wouldn't spill the casings
return true;
}
Expand Down Expand Up @@ -674,19 +674,21 @@ void gunmod_remove_activity_actor::serialize( JsonOut &jsout ) const
jsout.member( "moves_total", moves_total );
jsout.member( "gun", gun );
jsout.member( "gunmod", gunmod_idx );
jsout.member( "mod_contents", mod_contents );

jsout.end_object();
}

std::unique_ptr<activity_actor> gunmod_remove_activity_actor::deserialize( JsonValue &jsin )
{
gunmod_remove_activity_actor actor( 0, item_location(), -1 );
gunmod_remove_activity_actor actor( 0, item_location(), -1, {} );

JsonObject data = jsin.get_object();

data.read( "moves_total", actor.moves_total );
data.read( "gun", actor.gun );
data.read( "gunmod", actor.gunmod_idx );
data.read( "mod_contents", actor.mod_contents );

return actor.clone();
}
Expand Down
6 changes: 4 additions & 2 deletions src/activity_actor_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,15 @@ class gunmod_remove_activity_actor : public activity_actor
int moves_total;
item_location gun;
int gunmod_idx;
std::list<item> mod_contents;

public:
gunmod_remove_activity_actor(
int moves_total,
const item_location &gun,
int gunmod_idx
) : moves_total( moves_total ), gun( gun ), gunmod_idx( gunmod_idx ) {}
int gunmod_idx,
std::list<item> mod_contents
) : moves_total( moves_total ), gun( gun ), gunmod_idx( gunmod_idx ), mod_contents {}

activity_id get_type() const override {
return activity_id( "ACT_GUNMOD_REMOVE" );
Expand Down
1 change: 1 addition & 0 deletions src/character_ammo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ item::reload_option Character::select_ammo( const item_location &base,
item::reload_option Character::select_ammo( const item_location &base, bool prompt,
bool empty ) const
{

if( !base ) {
return item::reload_option();
}
Expand Down
23 changes: 20 additions & 3 deletions src/character_guns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void find_ammo_helper( T &src, const item &obj, bool empty, Output out, bool nes
src.visit_items( [&src, &nested, &out, &obj, empty]( item * node, item * parent ) {

// This stops containers and magazines counting *themselves* as ammo sources
if( node == &obj ) {
if( node == &obj && !node->has_flag( flag_NOT_MAGAZINE ) ) {
return VisitResponse::SKIP;
}

Expand All @@ -32,7 +32,7 @@ void find_ammo_helper( T &src, const item &obj, bool empty, Output out, bool nes
}

// Do not steal ammo from magazines
if( parent != nullptr && parent->is_magazine() ) {
if( parent != nullptr && parent->is_magazine() && !parent->is_magazine() ) {
return VisitResponse::SKIP;
}

Expand Down Expand Up @@ -252,6 +252,7 @@ bool Character::gunmod_remove( item &gun, item &mod )
break;
}
}

if( gunmod_idx == mods.size() ) {
debugmsg( "Cannot remove non-existent gunmod" );
return false;
Expand All @@ -264,7 +265,23 @@ bool Character::gunmod_remove( item &gun, item &mod )
// Removing gunmod takes only half as much time as installing it
const int moves = has_trait( trait_DEBUG_HS ) ? 0 : mod.type->gunmod->install_time / 2;
item_location gun_loc = item_location( *this, &gun );
assign_activity( gunmod_remove_activity_actor( moves, gun_loc, static_cast<int>( gunmod_idx ) ) );
if( mod.has_flag( flag_NOT_MAGAZINE ) ) {
std::list<item> mod_contents;
for( const item *it : gun.all_items_ptr( pocket_type::CONTAINER ) ) {
mod_contents.push_back( *it );
}
if( !mod_contents.empty() ) {
assign_activity( gunmod_remove_activity_actor( moves, gun_loc, static_cast<int>( gunmod_idx ), mod_contents ) );
// make the activity do this stuff
// map &here = get_map();
// for( item &content : mod_contents ) {
// here.add_item_or_charges( this->pos(), content );
// }
return true;
}
} else {
assign_activity( gunmod_remove_activity_actor( moves, gun_loc, static_cast<int>( gunmod_idx ), {} ) );
}
return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/flag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ const flag_id flag_NO_TURRET( "NO_TURRET" );
const flag_id flag_NO_UNLOAD( "NO_UNLOAD" );
const flag_id flag_NO_UNWIELD( "NO_UNWIELD" );
const flag_id flag_NO_WEAR_EFFECT( "NO_WEAR_EFFECT" );
const flag_id flag_NOT_MAGAZINE( "NOT_MAGAZINE" );
const flag_id flag_NPC_ACTIVATE( "NPC_ACTIVATE" );
const flag_id flag_NPC_ALT_ATTACK( "NPC_ALT_ATTACK" );
const flag_id flag_NPC_SAFE( "NPC_SAFE" );
Expand Down
1 change: 1 addition & 0 deletions src/flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ extern const flag_id flag_NO_TURRET;
extern const flag_id flag_NO_UNLOAD;
extern const flag_id flag_NO_UNWIELD;
extern const flag_id flag_NO_WEAR_EFFECT;
extern const flag_id flag_NOT_MAGAZINE;
extern const flag_id flag_NPC_ACTIVATE;
extern const flag_id flag_NPC_ALT_ATTACK;
extern const flag_id flag_NPC_SAFE;
Expand Down
5 changes: 3 additions & 2 deletions src/item_pocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,6 @@ bool item_pocket::can_reload_with( const item &ammo, const bool now ) const
}

return true;

} else if( is_type( pocket_type::MAGAZINE_WELL ) ) {
// Reloading is refused if there already is full magazine here
// Reloading with another identical mag with identical contents is also pointless so it is not allowed
Expand All @@ -1725,10 +1724,12 @@ bool item_pocket::can_reload_with( const item &ammo, const bool now ) const
front().same_contents( ammo ) );
} else if( is_type( pocket_type::CONTAINER ) ) {
// Reloading is possible if liquid combines with old liquid

if( front().can_combine( ammo ) ) {
return true;
}
if( !ammo.made_of( phase_id::LIQUID ) ) {
return true;
}
}
}
return false;
Expand Down
Loading