Skip to content

Commit

Permalink
Merge pull request #35634 from jbytheway/gun_stats_improvements
Browse files Browse the repository at this point in the history
Gun stats improvements
  • Loading branch information
kevingranade authored Nov 23, 2019
2 parents 94d54a9 + 74dba88 commit 2e63a63
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 55 deletions.
106 changes: 51 additions & 55 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1555,24 +1555,8 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
int /* batch */, bool /* debug */ ) const
{
const std::string space = " ";
// many statistics are dependent upon loaded ammo
// if item is unloaded (or is RELOAD_AND_SHOOT) shows approximate stats using default ammo
item *aprox = nullptr;
item tmp;
if( mod->ammo_required() && !mod->ammo_remaining() ) {
tmp.ammo_set( mod->magazine_current() ? tmp.common_ammo_default() : tmp.ammo_default() );
tmp = *mod;
aprox = &tmp;
}

const islot_gun &gun = *mod->type->gun;
const itype *curammo = mod->ammo_data();

bool has_ammo = curammo && mod->ammo_remaining();

// TODO: This doesn't cover multiple damage types
int ammo_pierce = has_ammo ? get_ranged_pierce( *curammo->ammo ) : 0;
int ammo_dispersion = has_ammo ? curammo->ammo->dispersion : 0;

const Skill &skill = *mod->gun_skill();

Expand Down Expand Up @@ -1618,7 +1602,25 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf

insert_separation_line( info );

int max_gun_range = mod->gun_range( &g->u );
// many statistics are dependent upon loaded ammo
// if item is unloaded (or is RELOAD_AND_SHOOT) shows approximate stats using default ammo
const item *loaded_mod = mod;
item tmp;
if( mod->ammo_required() && !mod->ammo_remaining() ) {
tmp = *mod;
tmp.ammo_set( mod->magazine_current() ? tmp.common_ammo_default() : tmp.ammo_default() );
loaded_mod = &tmp;
if( parts->test( iteminfo_parts::GUN_DEFAULT_AMMO ) ) {
info.emplace_back( "GUN",
_( "Gun is not loaded, so stats below assume the default ammo: " ),
string_format( "<stat>%s</stat>",
loaded_mod->ammo_data()->nname( 1 ) ) );
}
}

const itype *curammo = loaded_mod->ammo_data();

int max_gun_range = loaded_mod->gun_range( &g->u );
if( max_gun_range > 0 && parts->test( iteminfo_parts::GUN_MAX_RANGE ) ) {
info.emplace_back( "GUN", _( "Maximum range: " ), "<num>", iteminfo::no_flags,
max_gun_range );
Expand All @@ -1632,13 +1634,16 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
if( type.name.empty() ) {
continue;
}
info.emplace_back( "GUN", _( type.name ) );
int max_dispersion = g->u.get_weapon_dispersion( *mod ).max();
// For item comparison to work correctly each info object needs a
// distinct tag per aim type.
const std::string tag = "GUN_" + type.name;
info.emplace_back( tag, _( type.name ) );
int max_dispersion = g->u.get_weapon_dispersion( *loaded_mod ).max();
int range = range_with_even_chance_of_good_hit( max_dispersion + type.threshold );
info.emplace_back( "GUN", _( "Even chance of good hit at range: " ),
info.emplace_back( tag, _( "Even chance of good hit at range: " ),
_( "<num>" ), iteminfo::no_flags, range );
int aim_mv = g->u.gun_engagement_moves( *mod, type.threshold );
info.emplace_back( "GUN", _( "Time to reach aim level: " ), _( "<num> moves " ),
info.emplace_back( tag, _( "Time to reach aim level: " ), _( "<num> moves " ),
iteminfo::is_decimal | iteminfo::lower_is_better, aim_mv );
}
}
Expand All @@ -1648,17 +1653,18 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
mod->gun_damage( false ).total_damage() ) );
}

if( has_ammo ) {
if( mod->ammo_required() ) {
// ammo_damage, sum_of_damage, and ammo_mult not shown so don't need to translate.
if( mod->ammo_data()->ammo->prop_damage ) {
if( curammo->ammo->prop_damage ) {
if( parts->test( iteminfo_parts::GUN_DAMAGE_AMMOPROP ) ) {
info.push_back( iteminfo( "GUN", "ammo_mult", "*",
iteminfo::no_newline | iteminfo::no_name,
*mod->ammo_data()->ammo->prop_damage ) );
info.push_back(
iteminfo( "GUN", "ammo_mult", "*",
iteminfo::no_newline | iteminfo::no_name | iteminfo::is_decimal,
*curammo->ammo->prop_damage ) );
}
} else {
if( parts->test( iteminfo_parts::GUN_DAMAGE_LOADEDAMMO ) ) {
damage_instance ammo_dam = has_ammo ? curammo->ammo->damage : damage_instance();
damage_instance ammo_dam = curammo->ammo->damage;
info.push_back( iteminfo( "GUN", "ammo_damage", "",
iteminfo::no_newline | iteminfo::no_name |
iteminfo::show_plus, ammo_dam.total_damage() ) );
Expand All @@ -1667,15 +1673,18 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
if( parts->test( iteminfo_parts::GUN_DAMAGE_TOTAL ) ) {
info.push_back( iteminfo( "GUN", "sum_of_damage", _( " = <num>" ),
iteminfo::no_newline | iteminfo::no_name,
mod->gun_damage( true ).total_damage() ) );
loaded_mod->gun_damage( true ).total_damage() ) );
}
}

// TODO: This doesn't cover multiple damage types

if( parts->test( iteminfo_parts::GUN_ARMORPIERCE ) ) {
info.push_back( iteminfo( "GUN", space + _( "Armor-pierce: " ), "",
iteminfo::no_newline, get_ranged_pierce( gun ) ) );
}
if( has_ammo ) {
if( mod->ammo_required() ) {
int ammo_pierce = get_ranged_pierce( *curammo->ammo );
// ammo_armor_pierce and sum_of_armor_pierce don't need to translate.
if( parts->test( iteminfo_parts::GUN_ARMORPIERCE_LOADEDAMMO ) ) {
info.push_back( iteminfo( "GUN", "ammo_armor_pierce", "",
Expand All @@ -1695,7 +1704,8 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
iteminfo::no_newline | iteminfo::lower_is_better,
mod->gun_dispersion( false, false ) ) );
}
if( has_ammo ) {
if( mod->ammo_required() ) {
int ammo_dispersion = curammo->ammo->dispersion;
// ammo_dispersion and sum_of_dispersion don't need to translate.
if( parts->test( iteminfo_parts::GUN_DISPERSION_LOADEDAMMO ) ) {
info.push_back( iteminfo( "GUN", "ammo_dispersion", "",
Expand All @@ -1706,7 +1716,7 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
if( parts->test( iteminfo_parts::GUN_DISPERSION_TOTAL ) ) {
info.push_back( iteminfo( "GUN", "sum_of_dispersion", _( " = <num>" ),
iteminfo::lower_is_better | iteminfo::no_name,
mod->gun_dispersion( true, false ) ) );
loaded_mod->gun_dispersion( true, false ) ) );
}
}
info.back().bNewLine = true;
Expand All @@ -1732,31 +1742,17 @@ void item::gun_info( const item *mod, std::vector<iteminfo> &info, const iteminf
}

bool bipod = mod->has_flag( "BIPOD" );
if( aprox ) {
if( aprox->gun_recoil( g->u ) ) {
if( parts->test( iteminfo_parts::GUN_RECOIL ) ) {
info.emplace_back( "GUN", _( "Approximate recoil: " ), "",
iteminfo::no_newline | iteminfo::lower_is_better,
aprox->gun_recoil( g->u ) );
}
if( bipod && parts->test( iteminfo_parts::GUN_RECOIL_BIPOD ) ) {
info.emplace_back( "GUN", "bipod_recoil", _( " (with bipod <num>)" ),
iteminfo::lower_is_better | iteminfo::no_name,
aprox->gun_recoil( g->u, true ) );
}

if( loaded_mod->gun_recoil( g->u ) ) {
if( parts->test( iteminfo_parts::GUN_RECOIL ) ) {
info.emplace_back( "GUN", _( "Effective recoil: " ), "",
iteminfo::no_newline | iteminfo::lower_is_better,
loaded_mod->gun_recoil( g->u ) );
}
} else {
if( mod->gun_recoil( g->u ) ) {
if( parts->test( iteminfo_parts::GUN_RECOIL ) ) {
info.emplace_back( "GUN", _( "Effective recoil: " ), "",
iteminfo::no_newline | iteminfo::lower_is_better,
mod->gun_recoil( g->u ) );
}
if( bipod && parts->test( iteminfo_parts::GUN_RECOIL_BIPOD ) ) {
info.emplace_back( "GUN", "bipod_recoil", _( " (with bipod <num>)" ),
iteminfo::lower_is_better | iteminfo::no_name,
mod->gun_recoil( g->u, true ) );
}
if( bipod && parts->test( iteminfo_parts::GUN_RECOIL_BIPOD ) ) {
info.emplace_back( "GUN", "bipod_recoil", _( " (with bipod <num>)" ),
iteminfo::lower_is_better | iteminfo::no_name,
loaded_mod->gun_recoil( g->u, true ) );
}
}
info.back().bNewLine = true;
Expand Down
1 change: 1 addition & 0 deletions src/iteminfo_query.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ enum class iteminfo_parts : size_t {
AMMO_REMAINING,
AMMO_UPSCOST,

GUN_DEFAULT_AMMO,
GUN_MAX_RANGE,
GUN_AIMING_STATS,
GUN_DAMAGE,
Expand Down
19 changes: 19 additions & 0 deletions tests/iteminfo_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,22 @@ TEST_CASE( "if_covers_nothing_omit_irreelevant_info", "[item][iteminfo]" )
"--\n"
"Covers: <color_c_cyan>Nothing</color>.\n" );
}

TEST_CASE( "gun_lists_default_ammo", "[item][iteminfo]" )
{
iteminfo_query q( { iteminfo_parts::GUN_DEFAULT_AMMO } );
iteminfo_test(
item( "compbow" ), q,
"--\n"
"Gun is not loaded, so stats below assume the default ammo: <color_c_light_blue>wooden broadhead arrow</color>\n" );
}
TEST_CASE( "gun_damage_multiplier_not_integer", "[item][iteminfo]" )
{
iteminfo_query q( { iteminfo_parts::GUN_DAMAGE, iteminfo_parts::GUN_DAMAGE_AMMOPROP,
iteminfo_parts::GUN_DAMAGE_TOTAL
} );
iteminfo_test(
item( "compbow" ), q,
"--\n"
"Damage: <color_c_yellow>18</color>*<color_c_yellow>1.25</color> = <color_c_yellow>22</color>\n" );
}

0 comments on commit 2e63a63

Please sign in to comment.