Skip to content

Commit

Permalink
Merge pull request #38263 from kevingranade/cap-aim-at-unseen-targets
Browse files Browse the repository at this point in the history
Cap aim level when there is no target or when the target is not visible
  • Loading branch information
Rivet-the-Zombie authored Feb 27, 2020
2 parents f2e0310 + 8b21391 commit 63d3fb8
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/ranged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,13 +838,13 @@ static int find_target( const std::vector<Creature *> &t, const tripoint &tpos )
return -1;
}

static void do_aim( player &p, const item &relevant )
static void do_aim( player &p, const item &relevant, const double min_recoil )
{
const double aim_amount = p.aim_per_move( relevant, p.recoil );
if( aim_amount > 0 ) {
if( aim_amount > 0 && p.recoil > min_recoil ) {
// Increase aim at the cost of moves
p.mod_moves( -1 );
p.recoil = std::max( 0.0, p.recoil - aim_amount );
p.recoil = std::max( min_recoil, p.recoil - aim_amount );
} else {
// If aim is already maxed, we're just waiting, so pass the turn.
p.set_moves( 0 );
Expand Down Expand Up @@ -1022,6 +1022,21 @@ static int print_ranged_chance( const player &p, const catacurses::window &w, in
return line_number;
}

// Handle capping aim level when the player cannot see the target tile or there is nothing to aim at.
static double calculate_aim_cap( const player &p, const tripoint &target )
{
double min_recoil = 0.0;
const Creature *victim = g->critter_at( target, true );
if( victim == nullptr || !p.sees( *victim ) ) {
const int range = rl_dist( p.pos(), target );
// Get angle of triangle that spans the target square.
const double angle = atan2( 1, range );
// Convert from radians to arcmin.
min_recoil = 60 * 180 * angle / M_PI;
}
return min_recoil;
}

static int print_aim( const player &p, const catacurses::window &w, int line_number,
input_context &ctxt, item *weapon,
const double target_size, const tripoint &pos, double predicted_recoil )
Expand All @@ -1034,7 +1049,9 @@ static int print_aim( const player &p, const catacurses::window &w, int line_num
dispersion_sources dispersion = p.get_weapon_dispersion( *weapon );
dispersion.add_range( p.recoil_vehicle() );

const double min_dispersion = p.effective_dispersion( p.weapon.sight_dispersion() );
const double min_recoil = calculate_aim_cap( p, pos );
const double effective_recoil = p.effective_dispersion( p.weapon.sight_dispersion() );
const double min_dispersion = std::max( min_recoil, effective_recoil );
const double steadiness_range = MAX_RECOIL - min_dispersion;
// This is a relative measure of how steady the player's aim is,
// 0 is the best the player can do.
Expand Down Expand Up @@ -1597,8 +1614,9 @@ std::vector<tripoint> target_handler::target_ui( player &pc, target_mode mode,
recoil_pos = dst;

set_last_target( dst );
const double min_recoil = calculate_aim_cap( pc, dst );
for( int i = 0; i < 10; ++i ) {
do_aim( pc, *relevant );
do_aim( pc, *relevant, min_recoil );
}
if( pc.moves <= 0 ) {
// We've run out of moves, clear target vector, but leave target selected.
Expand Down Expand Up @@ -1659,12 +1677,13 @@ std::vector<tripoint> target_handler::target_ui( player &pc, target_mode mode,
}
int aim_threshold = it->threshold;
set_last_target( dst );
const double min_recoil = calculate_aim_cap( pc, dst );
do {
do_aim( pc, relevant ? *relevant : null_item_reference() );
} while( pc.moves > 0 && pc.recoil > aim_threshold && pc.recoil - sight_dispersion > 0 );
do_aim( pc, relevant ? *relevant : null_item_reference(), min_recoil );
} while( pc.moves > 0 && pc.recoil > aim_threshold && pc.recoil - sight_dispersion > min_recoil );

if( pc.recoil <= aim_threshold ||
pc.recoil - sight_dispersion == 0 ) {
pc.recoil - sight_dispersion == min_recoil ) {
// If we made it under the aim threshold, go ahead and fire.
// Also fire if we're at our best aim level already.
pc.view_offset = old_offset;
Expand Down

0 comments on commit 63d3fb8

Please sign in to comment.