Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(UI): make empty-handed unarmed damage bonus more visible #4241

Merged
merged 9 commits into from
Feb 22, 2024
2 changes: 1 addition & 1 deletion data/json/skills.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
"type": "skill",
"id": "unarmed",
"name": { "str": "unarmed combat" },
"description": "Your skill in hand-to-hand fighting. For the unskilled, it's a good way to get hurt, but those with enough practice can perform special blows and techniques to quickly dispatch enemies.",
"description": "Your skill in hand-to-hand fighting, with unarmed weapons or empty-handed. Skill increases attack accuracy and unlocks techniques in many martial arts, while also providing a bonus to bare-handed damage.",
"tags": [ "combat_skill", "weapon_skill" ],
"companion_combat_rank_factor": 1,
"companion_survival_rank_factor": 1,
Expand Down
54 changes: 54 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ static const skill_id skill_dodge( "dodge" );
static const skill_id skill_gun( "gun" );
static const skill_id skill_swimming( "swimming" );
static const skill_id skill_throw( "throw" );
static const skill_id skill_unarmed( "unarmed" );

static const species_id HUMAN( "HUMAN" );
static const species_id ROBOT( "ROBOT" );
Expand Down Expand Up @@ -350,9 +351,11 @@ static const std::string flag_PLOWABLE( "PLOWABLE" );
static const mtype_id mon_player_blob( "mon_player_blob" );
static const mtype_id mon_shadow_snake( "mon_shadow_snake" );

static const trait_flag_str_id trait_flag_NEED_ACTIVE_TO_MELEE( "NEED_ACTIVE_TO_MELEE" );
static const trait_flag_str_id trait_flag_PRED2( "PRED2" );
static const trait_flag_str_id trait_flag_PRED3( "PRED3" );
static const trait_flag_str_id trait_flag_PRED4( "PRED4" );
static const trait_flag_str_id trait_flag_UNARMED_BONUS( "UNARMED_BONUS" );

static const trait_flag_str_id flag_NO_THIRST( "NO_THIRST" );
static const trait_flag_str_id flag_NO_RADIATION( "NO_RADIATION" );
Expand Down Expand Up @@ -11224,6 +11227,57 @@ float Character::stability_roll() const
return get_melee() + get_str() + ( get_per() / 3.0f ) + ( get_dex() / 4.0f );
}

int Character::display_empty_handed_base_damage() const
{
int empty_hand_base_damage = get_skill_level( skill_unarmed ) * 2;
const bool left_empty = !natural_attack_restricted_on( bodypart_id( "hand_l" ) );
const bool right_empty = !natural_attack_restricted_on( bodypart_id( "hand_r" ) );

if( !left_empty && !right_empty ) {
// Mutation and bionic bonuses don't matter so just print unarmed bonus
return empty_hand_base_damage;
} else {

// Mutation and bionic bonuses double if both hands are free
int per_hand = 0;
if( has_bionic( bionic_id( "bio_razors" ) ) ) {
per_hand += 4;
}
for( const trait_id &mut : get_mutations() ) {
if( mut->flags.count( trait_flag_NEED_ACTIVE_TO_MELEE ) > 0 &&
!has_active_mutation( mut ) ) {
continue;
}
// Fixed bonuses are nice and simple
per_hand += mut->bash_dmg_bonus + mut->cut_dmg_bonus + mut->pierce_dmg_bonus;

// Random bonuses are more fiddly, since we want baseline numbers let's just report the minimum
const std::pair<int, int> rand_bash = mut->rand_bash_bonus;
const std::pair<int, int> rand_cut = mut->rand_cut_bonus;
per_hand += rand_bash.first + rand_cut.first;

// Extra skill bonus is also fairly simple, but each type of fixed bonus can trigger it separately
if( mut->flags.count( trait_flag_UNARMED_BONUS ) > 0 ) {
if( mut->bash_dmg_bonus > 0 ) {
per_hand += std::min( get_skill_level( skill_unarmed ) / 2, 4 );
}
if( mut->cut_dmg_bonus > 0 ) {
per_hand += std::min( get_skill_level( skill_unarmed ) / 2, 4 );
}
if( mut->pierce_dmg_bonus > 0 ) {
per_hand += std::min( get_skill_level( skill_unarmed ) / 2, 4 );
}
}
}
empty_hand_base_damage += per_hand; // First hand
if( left_empty && right_empty ) {
// Second hand
empty_hand_base_damage += per_hand;
}
return empty_hand_base_damage;
}
}

bool Character::uncanny_dodge()
{
return character_funcs::try_uncanny_dodge( *this );
Expand Down
2 changes: 2 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ class Character : public Creature, public location_visitable<Character>
int attack_cost( const item &weap ) const;
/** Gets melee accuracy component from weapon+skills */
float get_hit_weapon( const item &weap ) const;
/** Gets the minimum combined bare-handed damage from skill, bionics, and mutations for display functions */
int display_empty_handed_base_damage() const;

// If average == true, adds expected values of random rolls instead of rolling.
/** Adds all 3 types of physical damage to instance */
Expand Down
4 changes: 4 additions & 0 deletions src/character_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,10 @@ static void draw_skills_tab( const catacurses::window &w_skills,
if( aSkill->ident() == skill_id( "dodge" ) ) {
mvwprintz( w_skills, point( 14, y_pos ), cstatus, "%4.1f/%-2d(%2d%%)",
you.get_dodge(), level_num, exercise < 0 ? 0 : exercise );
}
if( aSkill->ident() == skill_id( "unarmed" ) ) {
mvwprintz( w_skills, point( 15, y_pos ), cstatus, "%3d/%-2d(%2d%%)",
you.display_empty_handed_base_damage(), level_num, exercise < 0 ? 0 : exercise );
} else {
mvwprintz( w_skills, point( 19, y_pos ), cstatus, "%-2d(%2d%%)",
level_num,
Expand Down
4 changes: 3 additions & 1 deletion src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,11 @@ bool character_martial_arts::pick_style( const avatar &you ) // Style selecti
"\n"
"STR: <color_white>%d</color>, DEX: <color_white>%d</color>, "
"PER: <color_white>%d</color>, INT: <color_white>%d</color>\n"
"Base empty-handed damage: %3d\n"
"Effective dodge rating: %4.1f\n"
"Press [<color_yellow>%s</color>] for more info.\n" ),
you.get_str(), you.get_dex(), you.get_per(), you.get_int(),
ctxt.get_desc( "SHOW_DESCRIPTION" ) );
you.display_empty_handed_base_damage(), you.get_dodge(), ctxt.get_desc( "SHOW_DESCRIPTION" ) );
ma_style_callback callback( static_cast<size_t>( STYLE_OFFSET ), selectable_styles );
kmenu.callback = &callback;
kmenu.input_category = "MELEE_STYLE_PICKER";
Expand Down
Loading