From 7d22ba6e6785eb540fad27460ce6f5c6c2757b50 Mon Sep 17 00:00:00 2001 From: scarf Date: Sun, 26 Nov 2023 16:18:21 +0900 Subject: [PATCH] feat: allow using `MOUNTABLE` terrains nearby when firing heavy weapon (#3751) * feat: allow using `MOUNTABLE` terrains nearby when firing heavy weapon * fix: check if the potential support is passable Co-authored-by: Chaosvolt --------- Co-authored-by: Chaosvolt --- src/ranged.cpp | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/ranged.cpp b/src/ranged.cpp index 0b933e99187a..3707fe2ae887 100644 --- a/src/ranged.cpp +++ b/src/ranged.cpp @@ -148,7 +148,6 @@ static constexpr int AIF_DURATION_LIMIT = 10; static projectile make_gun_projectile( const item &gun ); static void cycle_action( item &weap, const tripoint &pos ); -bool can_use_heavy_weapon( const Character &who, const map &m, const tripoint &pos ); dispersion_sources calculate_dispersion( const map &m, const Character &who, const item &gun, int at_recoil, bool burst ); @@ -773,10 +772,14 @@ void npc::pretend_fire( npc *source, int shots, item &gun ) } } -bool can_use_heavy_weapon( const Character &who, const map &m, const tripoint &pos ) + +namespace { - if( who.is_mounted() && who.mounted_creature->has_flag( MF_RIDEABLE_MECH ) ) { - return true; + +auto is_mountable( const map &m, const tripoint &pos ) -> bool +{ + if( m.impassable( pos ) ) { + return false; } // usage of any attached bipod is dependent upon terrain @@ -785,19 +788,37 @@ bool can_use_heavy_weapon( const Character &who, const map &m, const tripoint &p } if( const optional_vpart_position vp = m.veh_at( pos ) ) { + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) return vp->vehicle().has_part( pos, "MOUNTABLE" ); } - return false; } +auto is_mountable_nearby( const map &m, const tripoint &pos ) -> bool +{ + const auto &xs = closest_points_first( pos, 1 ); + return std::any_of( xs.begin(), xs.end(), + [&m]( const tripoint & x ) -> bool { return is_mountable( m, x ); } ); +} + +auto can_use_heavy_weapon( const Character &who, const map &m, const tripoint &pos ) -> bool +{ + if( who.is_mounted() && who.mounted_creature->has_flag( MF_RIDEABLE_MECH ) ) { + return true; + } + return is_mountable_nearby( m, pos ); +} + +} // namespace + + dispersion_sources calculate_dispersion( const map &m, const Character &who, const item &gun, int at_recoil, bool burst ) { - bool bipod = can_use_heavy_weapon( who, m, who.pos() ); + const bool bipod = can_use_heavy_weapon( who, m, who.pos() ); - int gun_recoil = gun.gun_recoil( bipod ); - int eff_recoil = at_recoil + ( burst ? ranged::burst_penalty( who, gun, gun_recoil ) : 0 ); + const int gun_recoil = gun.gun_recoil( bipod ); + const int eff_recoil = at_recoil + ( burst ? ranged::burst_penalty( who, gun, gun_recoil ) : 0 ); dispersion_sources dispersion( ranged::get_weapon_dispersion( who, gun ) ); dispersion.add_range( eff_recoil ); return dispersion; @@ -2072,6 +2093,7 @@ double ranged::recoil_vehicle( const Character &who ) if( who.in_vehicle ) { if( const optional_vpart_position vp = get_map().veh_at( who.pos() ) ) { + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) return static_cast( std::abs( vp->vehicle().velocity ) ) * 3 / 100; } } @@ -3732,8 +3754,8 @@ bool ranged::gunmode_checks_common( avatar &you, const map &m, std::vector &messages, - const gun_mode &gmode ) +auto ranged::gunmode_checks_weapon( avatar &you, const map &m, std::vector &messages, + const gun_mode &gmode ) -> bool { bool result = true;