From a1268c0a7a7f5f4704f94f1b27254cd3b8777380 Mon Sep 17 00:00:00 2001 From: bombasticSlacks Date: Sun, 30 Jan 2022 21:26:42 -0400 Subject: [PATCH 1/3] more mod fixes --- src/item.cpp | 34 +++++++++++++++++++++++++++++++--- src/item.h | 6 +++++- src/item_factory.cpp | 1 + src/itype.h | 3 +++ src/ranged.cpp | 2 +- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index 1efdccd50d7a4..72ade88d1ba75 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 { @@ -9591,6 +9591,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() ) { @@ -10108,8 +10126,18 @@ 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 ) { + 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; + } + } + } 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!" ), From b127ca086226c7e5fcc8d19b28a6a07dd66e972a Mon Sep 17 00:00:00 2001 From: bombasticSlacks Date: Sun, 30 Jan 2022 22:39:45 -0400 Subject: [PATCH 2/3] typo fix --- src/item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/item.cpp b/src/item.cpp index 72ade88d1ba75..222d0dca6cc76 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -10129,7 +10129,7 @@ bool item::uses_magazine() const itype_id item::magazine_default( bool conversion ) const { // consider modded ammo types - if( !conversion ) { + if( conversion ) { const itype_id ammo = ammo_default(); for( const itype_id mag : contents.magazine_compatible() ) { auto mag_types = mag->magazine->type; From 414f706fbf0dc6436362a152b16fc74a20ff2da9 Mon Sep 17 00:00:00 2001 From: bombasticSlacks Date: Sun, 30 Jan 2022 23:09:39 -0400 Subject: [PATCH 3/3] additional safety check --- src/item.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/item.cpp b/src/item.cpp index 222d0dca6cc76..460d1c62db0b4 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -10129,7 +10129,7 @@ bool item::uses_magazine() const itype_id item::magazine_default( bool conversion ) const { // consider modded ammo types - if( conversion ) { + 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; @@ -10138,6 +10138,8 @@ itype_id item::magazine_default( bool conversion ) const } } } + + // otherwise return the default return contents.magazine_default(); }