diff --git a/src/character.cpp b/src/character.cpp index ca6597fd33c9a..fdd4dc70270c5 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -2448,7 +2448,7 @@ std::string Character::enumerate_unmet_requirements( const item &it, const item return enumerate_as_string( unmet_reqs ); } -int Character::rust_rate( bool return_stat_effect ) const +int Character::rust_rate() const { if( get_option( "SKILL_RUST" ) == "off" ) { return 0; @@ -2456,9 +2456,9 @@ int Character::rust_rate( bool return_stat_effect ) const // Stat window shows stat effects on based on current stat int intel = get_int(); - /** @EFFECT_INT reduces skill rust */ + /** @EFFECT_INT reduces skill rust by 10% per level above 8 */ int ret = ( ( get_option( "SKILL_RUST" ) == "vanilla" || - get_option( "SKILL_RUST" ) == "capped" ) ? 500 : 500 - 35 * ( intel - 8 ) ); + get_option( "SKILL_RUST" ) == "capped" ) ? 100 : 100 + 10 * ( intel - 8 ) ); ret *= mutation_value( "skill_rust_multiplier" ); @@ -2466,8 +2466,7 @@ int Character::rust_rate( bool return_stat_effect ) const ret = 0; } - // return_stat_effect actually matters here - return ( return_stat_effect ? ret : ret / 10 ); + return ret; } int Character::read_speed( bool return_stat_effect ) const @@ -2596,29 +2595,21 @@ void Character::apply_skill_boost() void Character::do_skill_rust() { - const int rate = rust_rate(); - if( rate <= 0 ) { - return; - } - for( auto &pair : *_skills ) { - if( rate <= rng( 0, 1000 ) ) { - continue; - } - + for( std::pair &pair : *_skills ) { const Skill &aSkill = *pair.first; SkillLevel &skill_level_obj = pair.second; if( aSkill.is_combat_skill() && - ( ( has_trait_flag( "PRED2" ) && one_in( 4 ) ) || - ( has_trait_flag( "PRED3" ) && one_in( 2 ) ) || - ( has_trait_flag( "PRED4" ) && x_in_y( 2, 3 ) ) ) ) { + ( ( has_trait_flag( "PRED2" ) && calendar::once_every( 8_hours ) ) || + ( has_trait_flag( "PRED3" ) && calendar::once_every( 4_hours ) ) || + ( has_trait_flag( "PRED4" ) && calendar::once_every( 3_hours ) ) ) ) { // Their brain is optimized to remember this - if( one_in( 15600 ) ) { + if( one_in( 13 ) ) { // They've already passed the roll to avoid rust at // this point, but print a message about it now and // then. // - // 13 combat skills, 600 turns/hr, 7800 tests/hr. + // 13 combat skills. // This means PRED2/PRED3/PRED4 think of hunting on // average every 8/4/3 hours, enough for immersion // without becoming an annoyance. @@ -2631,7 +2622,7 @@ void Character::do_skill_rust() const bool charged_bio_mem = get_power_level() > 25_kJ && has_active_bionic( bio_memory ); const int oldSkillLevel = skill_level_obj.level(); - if( skill_level_obj.rust( charged_bio_mem ) ) { + if( skill_level_obj.rust( charged_bio_mem, rust_rate() ) ) { add_msg_if_player( m_warning, _( "Your knowledge of %s begins to fade, but your memory banks retain it!" ), aSkill.name() ); mod_power_level( -25_kJ ); diff --git a/src/character.h b/src/character.h index c0ef21257dfef..421eea2b0a1df 100644 --- a/src/character.h +++ b/src/character.h @@ -1296,7 +1296,7 @@ class Character : public Creature, public visitable std::string enumerate_unmet_requirements( const item &it, const item &context = item() ) const; /** Returns the player's skill rust rate */ - int rust_rate( bool return_stat_effect = true ) const; + int rust_rate() const; // Mental skills and stats /** Returns the player's reading speed */ diff --git a/src/newcharacter.cpp b/src/newcharacter.cpp index 3179fa6fc7005..a81e4609559ad 100644 --- a/src/newcharacter.cpp +++ b/src/newcharacter.cpp @@ -845,7 +845,7 @@ tab_direction set_stats( const catacurses::window &w, avatar &u, points_left &po _( "Read times: %d%%" ), read_spd ); // NOLINTNEXTLINE(cata-use-named-point-constants) mvwprintz( w_description, point( 0, 1 ), COL_STAT_PENALTY, _( "Skill rust: %d%%" ), - u.rust_rate( false ) ); + u.rust_rate() ); mvwprintz( w_description, point( 0, 2 ), COL_STAT_BONUS, _( "Crafting bonus: %2d%%" ), u.get_int() ); fold_and_print( w_description, point( 0, 4 ), getmaxx( w_description ) - 1, COL_STAT_NEUTRAL, diff --git a/src/player_display.cpp b/src/player_display.cpp index 98b5d3cbc7e71..9394c00488e20 100644 --- a/src/player_display.cpp +++ b/src/player_display.cpp @@ -314,7 +314,7 @@ static void draw_stats_tab( const catacurses::window &w_stats, const catacurses: string_format( _( "Crafting bonus: %d%%" ), you.get_int() ) ); if( you.rust_rate() ) { print_colored_text( w_info, point( 1, 5 ), col_temp, c_light_gray, - string_format( _( "Skill rust: %d%%" ), you.rust_rate( false ) ) ); + string_format( _( "Skill rust: %d%%" ), you.rust_rate() ) ); } } else if( line == 3 ) { // Display information on player perception in appropriate window diff --git a/src/skill.cpp b/src/skill.cpp index ed9c437ec908b..cb61d61f88bfa 100644 --- a/src/skill.cpp +++ b/src/skill.cpp @@ -224,12 +224,12 @@ time_duration rustRate( int level ) { // for n = [0, 7] // - // 2^15 + // 2^18 // ------- - // 2^(n-1) + // 2^(18-n) - unsigned const n = level < 0 ? 0 : level > 7 ? 7 : level; - return time_duration::from_turns( 1 << ( 15 - n + 1 ) ); + unsigned const n = clamp( level, 0, 7 ); + return time_duration::from_turns( 1 << ( 18 - n ) ); } } //namespace @@ -239,10 +239,12 @@ bool SkillLevel::isRusting() const calendar::turn - _lastPracticed > rustRate( _level ); } -bool SkillLevel::rust( bool charged_bio_mem ) +bool SkillLevel::rust( bool charged_bio_mem, int character_rate ) { const time_duration delta = calendar::turn - _lastPracticed; - if( _level <= 0 || delta <= 0_turns || delta % rustRate( _level ) != 0_turns ) { + const float char_rate = character_rate / 100.0; + if( _level <= 0 || delta <= 0_turns || + delta % ( rustRate( _level ) * char_rate ) != 0_turns ) { return false; } @@ -251,7 +253,7 @@ bool SkillLevel::rust( bool charged_bio_mem ) } _exercise -= _level; - const auto &rust_type = get_option( "SKILL_RUST" ); + const std::string &rust_type = get_option( "SKILL_RUST" ); if( _exercise < 0 ) { if( rust_type == "vanilla" || rust_type == "int" ) { _exercise = ( 100 * _level * _level ) - 1; diff --git a/src/skill.h b/src/skill.h index 33f2827a7ef45..cf64f2d336370 100644 --- a/src/skill.h +++ b/src/skill.h @@ -110,7 +110,7 @@ class SkillLevel { int _level = 0; int _exercise = 0; - time_point _lastPracticed = calendar::turn_zero; + time_point _lastPracticed = calendar::turn; bool _isTraining = true; int _highestLevel = 0; @@ -150,7 +150,7 @@ class SkillLevel void train( int amount, bool skip_scaling = false ); bool isRusting() const; - bool rust( bool charged_bio_mem ); + bool rust( bool charged_bio_mem, int character_rate ); void practice(); bool can_train() const; diff --git a/src/wish.cpp b/src/wish.cpp index f54e0237654fa..d9be428b0ece5 100644 --- a/src/wish.cpp +++ b/src/wish.cpp @@ -672,6 +672,7 @@ void debug_menu::wishskill( player *p ) skmenu.entries[skill_id + skoffset].txt = string_format( _( "@ %d: %s " ), p->get_skill_level( skill.ident() ), skill.name() ); + p->get_skill_level_object( skill.ident() ).practice(); skmenu.entries[skill_id + skoffset].text_color = p->get_skill_level( skill.ident() ) == origskills[skill_id] ? skmenu.text_color : c_yellow; }