From 40b6557657c3924cea57894f51c1de0a26d26734 Mon Sep 17 00:00:00 2001 From: Dillon Matchett Date: Mon, 31 Jan 2022 03:22:07 -0400 Subject: [PATCH] More Gun Mod Upgrades (#54961) --- src/item.cpp | 36 +++++++++++++++++++++++++++++++++--- src/item.h | 6 +++++- src/item_factory.cpp | 1 + src/itype.h | 3 +++ src/ranged.cpp | 2 +- 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index b94381092f7ec..05573695412c5 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -575,8 +575,8 @@ item &item::ammo_set( const itype_id &ammo, int qty ) qty = ammo_capacity( ammo_type ); // else try to add a magazine using default ammo count property if set - } else if( !magazine_default().is_null() ) { - item mag( magazine_default() ); + } else if( !magazine_default( true ).is_null() ) { + item mag( magazine_default( true ) ); if( mag.type->magazine->count > 0 ) { qty = mag.type->magazine->count; } else { @@ -9600,6 +9600,24 @@ skill_id item::melee_skill() const return res; } + +int item::min_cycle_recoil() const +{ + if( !is_gun() ) { + return 0; + } + int to_cycle = type->gun->min_cycle_recoil; + // This should only be used for one mod or it'll mess things up + // TODO: maybe generalize this so you can have mods for hot loads or whatever + for( const item *mod : gunmods() ) { + // this value defaults to -1 + if( mod->type->gunmod->overwrite_min_cycle_recoil > 0 ) { + to_cycle = mod->type->gunmod->overwrite_min_cycle_recoil; + } + } + return to_cycle; +} + int item::gun_dispersion( bool with_ammo, bool with_scaling ) const { if( !is_gun() ) { @@ -10117,8 +10135,20 @@ bool item::uses_magazine() const return contents.has_pocket_type( item_pocket::pocket_type::MAGAZINE_WELL ); } -itype_id item::magazine_default( bool /* conversion */ ) const +itype_id item::magazine_default( bool conversion ) const { + // consider modded ammo types + if( conversion && !ammo_types().empty() ) { + const itype_id ammo = ammo_default(); + for( const itype_id mag : contents.magazine_compatible() ) { + auto mag_types = mag->magazine->type; + if( mag_types.find( ammo->ammo->type ) != mag_types.end() ) { + return mag; + } + } + } + + // otherwise return the default return contents.magazine_default(); } diff --git a/src/item.h b/src/item.h index 81670b1fd422b..7f37aa715318f 100644 --- a/src/item.h +++ b/src/item.h @@ -2244,7 +2244,7 @@ class item : public visitable /** Get the default magazine type (if any) for the current effective ammo type * @param conversion whether to include the effect of any flags or mods which convert item's ammo type * @return magazine type or "null" if item has integral magazine or no magazines for current ammo type */ - itype_id magazine_default( bool conversion = true ) const; + itype_id magazine_default( bool conversion = false ) const; /** Get compatible magazines (if any) for this item * @return magazine compatibility which is always empty if item has integral magazine @@ -2344,6 +2344,10 @@ class item : public visitable * Returns empty instance on non-gun items. */ damage_instance gun_damage( bool with_ammo = true, bool shot = false ) const; + /** + * The minimum force required to cycle the gun, can be overridden by mods + */ + int min_cycle_recoil() const; /** * Summed dispersion of a gun, including values from mods. Returns 0 on non-gun items. */ diff --git a/src/item_factory.cpp b/src/item_factory.cpp index f8e353f3f2a22..63d9b1c4d8064 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -2931,6 +2931,7 @@ void Item_factory::load( islot_gunmod &slot, const JsonObject &jo, const std::st assign( jo, "ammo_to_fire_multiplier", slot.ammo_to_fire_multiplier ); assign( jo, "ammo_to_fire_modifier", slot.ammo_to_fire_modifier ); assign( jo, "weight_multiplier", slot.weight_multiplier ); + assign( jo, "overwrite_min_cycle_recoil", slot.overwrite_min_cycle_recoil ); // convert aim_speed to FoV and aim_speed_modifier automatically, if FoV is not set if( slot.aim_speed >= 0 && slot.field_of_view <= 0 ) { if( slot.aim_speed > 6 ) { diff --git a/src/itype.h b/src/itype.h index 65acbc9710c27..104de0dc79cf9 100644 --- a/src/itype.h +++ b/src/itype.h @@ -791,6 +791,9 @@ struct islot_gunmod : common_ranged_data { /** Not compatable on weapons that have this mod slot */ std::set blacklist_mod; + + // minimum recoil to cycle while this is installed + int overwrite_min_cycle_recoil = -1; }; struct islot_magazine { diff --git a/src/ranged.cpp b/src/ranged.cpp index 1acbe4225950b..b013014391a9c 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -658,7 +658,7 @@ bool Character::handle_gun_damage( item &it ) it.inc_damage(); } if( !it.has_flag( flag_PRIMITIVE_RANGED_WEAPON ) ) { - if( it.ammo_data() != nullptr && ( ( it.ammo_data()->ammo->recoil < firing.min_cycle_recoil ) || + if( it.ammo_data() != nullptr && ( ( it.ammo_data()->ammo->recoil < it.min_cycle_recoil() ) || ( it.has_fault_flag( "BAD_CYCLING" ) && one_in( 16 ) ) ) && it.faults_potential().count( fault_gun_chamber_spent ) ) { add_msg_player_or_npc( m_bad, _( "Your %s fails to cycle!" ),