From 52d8f227a28f56c36dc67b75157d0803d8e62d0d Mon Sep 17 00:00:00 2001 From: Maleclypse <54345792+Maleclypse@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:32:58 -0500 Subject: [PATCH] irwss fix Co-Authored-By: Alexey --- src/map.cpp | 40 +++++++++++++++++++++++++++ src/mattack_actors.cpp | 61 +++++------------------------------------- 2 files changed, 47 insertions(+), 54 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 726839e0eb471..fa4334e0c4a4c 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1108,6 +1108,10 @@ void map::register_vehicle_zone( vehicle *veh, const int zlev ) } bool map::deregister_vehicle_zone( zone_data &zone ) const +// returns a list of tripoints which contain parts from moving vehicles within \p max_range +// distance from \p source position, if any parts are CONTROLS, ENGINE or WHEELS returns a +// list of tripoints with exclusively such parts instead. Used for monster gun actor targeting. +std::set get_moving_vehicle_targets( const Creature &source, int max_range ); { if( const std::optional vp = veh_at( getlocal( zone.get_start_point() ) ).part_with_feature( "CARGO", false ) ) { @@ -1122,6 +1126,42 @@ bool map::deregister_vehicle_zone( zone_data &zone ) const return false; } +std::set map::get_moving_vehicle_targets( const Creature &z, int max_range ) +{ + const tripoint_bub_ms zpos( z.pos() ); + std::set priority; + std::set visible; + for( wrapped_vehicle &v : get_vehicles() ) { + if( !v.v->is_moving() ) { + continue; + } + if( !fov_3d && v.pos.z != zpos.z() ) { + continue; + } + if( rl_dist( zpos, tripoint_bub_ms( v.pos ) ) > max_range + 40 ) { + continue; // coarse distance filter, 40 = ~24 * sqrt(2) - rough max diameter of a vehicle + } + for( const vpart_reference &vpr : v.v->get_all_parts() ) { + const tripoint_bub_ms vppos = static_cast( vpr.pos() ); + if( rl_dist( zpos, vppos ) > max_range ) { + continue; + } + if( !z.sees( vppos ) ) { + continue; + } + if( vpr.has_feature( VPFLAG_CONTROLS ) || + vpr.has_feature( VPFLAG_ENGINE ) || + vpr.has_feature( VPFLAG_WHEEL ) ) { + priority.emplace( vppos ); + } else { + visible.emplace( vppos ); + } + } + } + return !priority.empty() ? priority : visible; +} + + // 3D vehicle functions VehicleList map::get_vehicles( const tripoint &start, const tripoint &end ) diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index 95949cee5076d..6cf828b9ae2be 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -32,9 +32,7 @@ #include "rng.h" #include "sounds.h" #include "translations.h" -#include "vehicle.h" #include "viewer.h" -#include "veh_type.h" static const efftype_id effect_badpoison( "badpoison" ); @@ -833,25 +831,6 @@ int gun_actor::get_max_range() const return max_range; } -static vehicle *find_target_vehicle( monster &z, int range ) -{ - map &here = get_map(); - vehicle *chosen = nullptr; - for( wrapped_vehicle &v : here.get_vehicles() ) { - if( !z.sees( v.pos ) ) { - continue; - } - if( !fov_3d && v.pos.z != z.pos().z ) { - continue; - } - int new_dist = rl_dist( z.pos(), v.pos ); - if( v.v->velocity != 0 && new_dist < range ) { - chosen = v.v; - range = new_dist; - } - } - return chosen; -} bool gun_actor::call( monster &z ) const @@ -877,48 +856,22 @@ bool gun_actor::call( monster &z ) const } aim_at = target->pos(); } else { - target = z.attack_target(); + aim_at = target ? target->pos() : tripoint_zero; if( !target || !z.sees( *target ) || ( !target->is_monster() && !z.aggro_character ) ) { - //return false; if( !target_moving_vehicles ) { return false; } - //No living targets, try to find a moving car - untargeted = true; - vehicle *veh = find_target_vehicle( z, get_max_range() ); - if( !veh ) { - return false; - } - std::vector valid_targets; - std::vector visible_points; - for( const tripoint &p : veh->get_points() ) { - if( !z.sees( p ) ) { - continue; - } - visible_points.push_back( p ); - for( const vpart_reference &vp : veh->get_all_parts() ) { - if( vp.pos() != p ) { - continue; - } - if( veh->part_with_feature( vp.part_index(), VPFLAG_CONTROLS, true ) >= 0 && - veh->part_with_feature( vp.part_index(), VPFLAG_ENGINE, true ) >= 0 && - veh->part_with_feature( vp.part_index(), VPFLAG_WHEEL, true ) >= 0 ) { - valid_targets.push_back( p ); - break; - } - } - } - if( !valid_targets.empty() ) { - aim_at = random_entry( valid_targets, tripoint_zero ); - } else if( !visible_points.empty() ) { - aim_at = random_entry( visible_points, tripoint_zero ); - } else { + untargeted = true; // no living targets, try to find moving car parts + const std::set moving_veh_parts = get_map() + .get_moving_vehicle_targets( z, get_max_range() ); + if( moving_veh_parts.empty() ) { return false; } + aim_at = random_entry( moving_veh_parts, tripoint_bub_ms() ).raw() } } - int dist = rl_dist( z.pos(), aim_at ); + const int dist = rl_dist( z.pos(), aim_at ); if( target ) { add_msg_debug( debugmode::DF_MATTACK, "Target %s at range %d", target->disp_name(), dist ); } else {