Skip to content

Commit

Permalink
Guns need more skill, performing much worse at low skills (CleverRave…
Browse files Browse the repository at this point in the history
…n#66347)

* increase penalties to dispersion at low skills.

* make skill effect on base_aim_speed_cap frontloaded

* Update src/character.cpp

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* make aiming a combo of limb scores

* Low marksman skill makes it harder to reorient your aim

* add a final divisor to aim speed based on skill

* Update src/character.cpp

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* attempt #1 to fix this test

* test fix

* more test fixes

* more fixes

* Update ranged_balance_test.cpp

* Update ranged_balance_test.cpp

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
anoobindisguise and github-actions[bot] committed Jun 23, 2023
1 parent 4cab242 commit b36311d
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 40 deletions.
4 changes: 2 additions & 2 deletions data/json/character_modifiers.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
{
"type": "character_mod",
"id": "aim_speed_mod",
"description": "Gun aim speed modifier <color_dark_gray>(Manipulation)</color>",
"description": "Gun aim speed modifier <color_dark_gray>(Manipulation, Grip, Lift)</color> ",
"mod_type": "x",
"value": { "limb_score": "manip", "limb_type": "hand" }
"value": { "limb_score": [ [ "grip", 0.2 ], [ "manip", 0.2 ], [ "lift", 0.6 ] ], "limb_score_op": "+", "min": 0.1, "max": 1.0 }
},
{
"type": "character_mod",
Expand Down
6 changes: 5 additions & 1 deletion src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1058,10 +1058,14 @@ double Character::aim_per_move( const item &gun, double recoil,

aim_speed *= get_modifier( character_modifier_aim_speed_mod );

// finally multiply everything by a harsh function that is eliminated by 7.5 gunskill
aim_speed /= std::max( 1.0, 2.5 - 0.2 * get_skill_level( gun_skill ) );
// Use a milder attenuation function to replace the previous logarithmic attenuation function when recoil is closed to 0.
aim_speed *= std::max( recoil / MAX_RECOIL, 1 - logarithmic_range( 0, MAX_RECOIL, recoil ) );

double base_aim_speed_cap = 20 + 1.0 * get_skill_level( gun_skill );
// add 4 max aim speed per skill up to 5 skill, then 1 per skill for skill 5-10
double base_aim_speed_cap = 5.0 + 1.0 * get_skill_level( gun_skill ) + std::max( 10.0,
3.0 * get_skill_level( gun_skill ) );

// This upper limit usually only affects the first half of the aiming process
// Pistols have a much higher aiming speed limit
Expand Down
9 changes: 6 additions & 3 deletions src/ranged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2155,7 +2155,7 @@ static double dispersion_from_skill( double skill, double weapon_dispersion )
return 0.0;
}
double skill_shortfall = static_cast<double>( MAX_SKILL ) - skill;
double dispersion_penalty = 3 * skill_shortfall;
double dispersion_penalty = 10 * skill_shortfall;
double skill_threshold = 5;
if( skill >= skill_threshold ) {
double post_threshold_skill_shortfall = static_cast<double>( MAX_SKILL ) - skill;
Expand All @@ -2166,7 +2166,7 @@ static double dispersion_from_skill( double skill, double weapon_dispersion )
// Unskilled shooters suffer greater penalties, still scaling with weapon penalties.
double pre_threshold_skill_shortfall = skill_threshold - skill;
dispersion_penalty += weapon_dispersion *
( 1.25 + pre_threshold_skill_shortfall * 3.75 / skill_threshold );
( 1.25 + pre_threshold_skill_shortfall * 10.0 / skill_threshold );

return dispersion_penalty;
}
Expand Down Expand Up @@ -3161,7 +3161,10 @@ void target_ui::recalc_aim_turning_penalty()
} else {
// Raise it proportionally to how much
// the player has to turn from previous aiming point
const double recoil_per_degree = MAX_RECOIL / 180.0;
// the player loses their aim more quickly if less skilled, normalizing at 5 skill.
/** @EFFECT_GUN increases the penalty for reorienting aim while below 5 */
const double skill_penalty = std::max( 0.0, 5.0 - you->get_skill_level( skill_gun ) );
const double recoil_per_degree = skill_penalty * MAX_RECOIL / 180.0;
const units::angle angle_curr = coord_to_angle( src, curr_recoil_pos );
const units::angle angle_desired = coord_to_angle( src, dst );
const units::angle phi = normalize( angle_curr - angle_desired );
Expand Down
14 changes: 7 additions & 7 deletions tests/iteminfo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1590,16 +1590,16 @@ TEST_CASE( "gun_or_other_ranged_weapon_attributes", "[iteminfo][weapon][gun]" )
std::vector<iteminfo_parts> aim_stats = { iteminfo_parts::GUN_AIMING_STATS };
CHECK( item_info_str( glock, aim_stats ) ==
"--\n"
"<color_c_white>Base aim speed</color>: <color_c_yellow>48</color>\n"
"<color_c_white>Base aim speed</color>: <color_c_yellow>29</color>\n"
"<color_c_cyan>Regular</color>\n"
"Even chance of good hit at range: <color_c_yellow>3</color>\n"
"Time to reach aim level: <color_c_yellow>99</color> moves\n"
"Even chance of good hit at range: <color_c_yellow>2</color>\n"
"Time to reach aim level: <color_c_yellow>233</color> moves\n"
"<color_c_cyan>Careful</color>\n"
"Even chance of good hit at range: <color_c_yellow>6</color>\n"
"Time to reach aim level: <color_c_yellow>165</color> moves\n"
"Even chance of good hit at range: <color_c_yellow>3</color>\n"
"Time to reach aim level: <color_c_yellow>399</color> moves\n"
"<color_c_cyan>Precise</color>\n"
"Even chance of good hit at range: <color_c_yellow>8</color>\n"
"Time to reach aim level: <color_c_yellow>263</color> moves\n" );
"Even chance of good hit at range: <color_c_yellow>4</color>\n"
"Time to reach aim level: <color_c_yellow>645</color> moves\n" );
}

SECTION( "compatible magazines" ) {
Expand Down
54 changes: 27 additions & 27 deletions tests/ranged_balance_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ static void test_shooting_scenario( npc &shooter, const int min_quickdraw_range,
CAPTURE( shooter.get_modifier( character_modifier_ranged_dispersion_manip_mod ) );
CAPTURE( good_stats.n() );
CAPTURE( good_stats.margin_of_error() );
CHECK( good_stats.avg() > 0.5 );
CHECK( good_stats.avg() > 0.0 );
}
{
const dispersion_sources dispersion = get_dispersion( shooter, 500, max_good_range );
Expand All @@ -190,7 +190,7 @@ static void test_shooting_scenario( npc &shooter, const int min_quickdraw_range,
static void test_fast_shooting( npc &shooter, const int moves, float hit_rate )
{
const int fast_shooting_range = 3;
const float hit_rate_cap = hit_rate + 0.3f;
const float hit_rate_cap = hit_rate + 0.5f;
const dispersion_sources dispersion = get_dispersion( shooter, moves, fast_shooting_range );
firing_statistics fast_stats = firing_test( dispersion, fast_shooting_range,
Threshold( accuracy_standard, hit_rate ) );
Expand All @@ -210,7 +210,7 @@ static void test_fast_shooting( npc &shooter, const int moves, float hit_rate )
CHECK( fast_stats.avg() > hit_rate );
CAPTURE( fast_stats_upper.n() );
CAPTURE( fast_stats_upper.margin_of_error() );
CHECK( fast_stats_upper.avg() < hit_rate_cap );
CHECK( fast_stats_upper.avg() <= hit_rate_cap );
}

static void assert_encumbrance( npc &shooter, int encumbrance )
Expand Down Expand Up @@ -249,32 +249,32 @@ TEST_CASE( "unskilled_shooter_accuracy", "[ranged] [balance] [slow]" )
SECTION( "an unskilled shooter with a common pistol" ) {
arm_shooter( shooter, "glock_19" );
test_shooting_scenario( shooter, 4, 5, 17 );
test_fast_shooting( shooter, 60, 0.3 );
test_fast_shooting( shooter, 60, 0.15 );
}
SECTION( "an unskilled archer with a common bow" ) {
arm_shooter( shooter, "shortbow", { "bow_sight_pin" }, "arrow_field_point_fletched" );
test_shooting_scenario( shooter, 4, 4, 13 );
test_fast_shooting( shooter, 90, 0.3 );
test_fast_shooting( shooter, 90, 0.1 );
}
SECTION( "an unskilled archer with a common crossbow" ) {
arm_shooter( shooter, "crossbow", {}, "bolt_makeshift" );
test_shooting_scenario( shooter, 4, 5, 17 );
test_fast_shooting( shooter, 80, 0.3 );
test_fast_shooting( shooter, 80, 0.15 );
}
SECTION( "an unskilled shooter with a common shotgun" ) {
arm_shooter( shooter, "remington_870" );
test_shooting_scenario( shooter, 4, 4, 19 );
test_fast_shooting( shooter, 80, 0.3 );
test_fast_shooting( shooter, 80, 0.15 );
}
SECTION( "an unskilled shooter with a common smg" ) {
arm_shooter( shooter, "mp40semi" );
test_shooting_scenario( shooter, 4, 5, 18 );
test_fast_shooting( shooter, 80, 0.3 );
test_fast_shooting( shooter, 80, 0.15 );
}
SECTION( "an unskilled shooter with a common rifle" ) {
arm_shooter( shooter, "ar15" );
test_shooting_scenario( shooter, 5, 5, 25 );
test_fast_shooting( shooter, 100, 0.3 );
test_fast_shooting( shooter, 100, 0.15 );
}
}

Expand All @@ -290,32 +290,32 @@ TEST_CASE( "competent_shooter_accuracy", "[ranged] [balance]" )
SECTION( "a skilled shooter with an accurate pistol" ) {
arm_shooter( shooter, "sw_619", { "red_dot_sight" } );
test_shooting_scenario( shooter, 10, 12, 35 );
test_fast_shooting( shooter, 40, 0.4 );
test_fast_shooting( shooter, 40, 0.35 );
}
SECTION( "a skilled archer with an accurate bow" ) {
arm_shooter( shooter, "recurbow", { "bow_sight" } );
test_shooting_scenario( shooter, 8, 10, 35 );
test_fast_shooting( shooter, 70, 0.4 );
test_fast_shooting( shooter, 70, 0.35 );
}
SECTION( "a skilled archer with an accurate crossbow" ) {
arm_shooter( shooter, "compositecrossbow", { "tele_sight" }, "bolt_steel" );
test_shooting_scenario( shooter, 9, 10, 35 );
test_fast_shooting( shooter, 70, 0.4 );
test_fast_shooting( shooter, 70, 0.35 );
}
SECTION( "a skilled shooter with a nice shotgun" ) {
arm_shooter( shooter, "mossberg_590" );
test_shooting_scenario( shooter, 9, 12, 35 );
test_fast_shooting( shooter, 70, 0.4 );
test_fast_shooting( shooter, 70, 0.35 );
}
SECTION( "a skilled shooter with a nice smg" ) {
arm_shooter( shooter, "hk_mp5", { "red_dot_sight" } );
test_shooting_scenario( shooter, 9, 12, 35 );
test_fast_shooting( shooter, 80, 0.4 );
test_fast_shooting( shooter, 80, 0.3 );
}
SECTION( "a skilled shooter with a carbine" ) {
arm_shooter( shooter, "m4_carbine", { "red_dot_sight" }, "556_m855a1" );
test_shooting_scenario( shooter, 10, 15, 48 );
test_fast_shooting( shooter, 80, 0.4 );
test_fast_shooting( shooter, 80, 0.3 );
}
SECTION( "a skilled shooter with an available sniper rifle" ) {
arm_shooter( shooter, "M24" );
Expand Down Expand Up @@ -518,7 +518,7 @@ TEST_CASE( "shot_features", "[gun]" "[slow]" )

// BUCKSHOT
// Unarmored target
shoot_monster( "shotgun_s", {}, "shot_00", 18, 86, "mon_wolf_mutant_huge" );
shoot_monster( "shotgun_s", {}, "shot_00", 18, 72, "mon_wolf_mutant_huge" );
// Heavy damage at range.
shoot_monster( "shotgun_s", {}, "shot_00", 12, 120, "mon_wolf_mutant_huge" );
// More damage at close range.
Expand All @@ -528,15 +528,15 @@ TEST_CASE( "shot_features", "[gun]" "[slow]" )

// Lightly armored target (armor_bullet: 5)
// Outcomes for lightly armored enemies are very similar.
shoot_monster( "shotgun_s", {}, "shot_00", 18, 33, "mon_zombie_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 12, 57, "mon_zombie_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 18, 20, "mon_zombie_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 12, 40, "mon_zombie_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 5, 116, "mon_zombie_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 1, 73, "mon_zombie_brute" );

// Armored target (armor_bullet: 10)
shoot_monster( "shotgun_s", {}, "shot_00", 18, 8, "mon_smoker_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 12, 18, "mon_smoker_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 5, 62, "mon_smoker_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 5, 47, "mon_smoker_brute" );
shoot_monster( "shotgun_s", {}, "shot_00", 1, 72, "mon_smoker_brute" );
}

Expand All @@ -559,24 +559,24 @@ TEST_CASE( "shot_features_with_choke", "[gun]" "[slow]" )
shoot_monster( "shotgun_s", { "choke" }, "shot_bird", 1, 61, "mon_zombie_brute" );

// Unarmored target
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 111, "mon_wolf_mutant_huge" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 95, "mon_wolf_mutant_huge" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 144, "mon_wolf_mutant_huge" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 5, 165, "mon_wolf_mutant_huge" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 1, 75, "mon_wolf_mutant_huge" );
// Triviallly armored target (armor_bullet: 1)
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 50, "mon_zombie_tough" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 81, "mon_zombie_tough" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 32, "mon_zombie_tough" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 61, "mon_zombie_tough" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 5, 105, "mon_zombie_tough" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 1, 100, "mon_zombie_tough" );
// Armored target (armor_bullet: 5)
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 46, "mon_zombie_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 77, "mon_zombie_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 25, "mon_zombie_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 54, "mon_zombie_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 5, 124, "mon_zombie_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 1, 73, "mon_zombie_brute" );
// Armored target (armor_bullet: 10)
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 11, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 26, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 5, 81, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 18, 10, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 12, 11, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 5, 62, "mon_smoker_brute" );
shoot_monster( "shotgun_s", { "choke" }, "shot_00", 1, 71, "mon_smoker_brute" );
}

Expand Down

0 comments on commit b36311d

Please sign in to comment.