From 79e8b37c80128f331d95081d158a82838a22e430 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 26 Dec 2020 09:43:15 -0800 Subject: [PATCH 1/4] Add instantaneous activity tracking to Character This tracks the highest activity level of the Character for the current turn and the last turn. Add hack for cases (such as diagonal moves with circular distances) to keep the last activity taken in the cache and not clear it. All of this commit will become obsolete when we have turn-granularity activity tracking. This is a little spotty, but it work wells enough. --- src/character.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/character.h | 12 ++++++++++++ src/game.cpp | 6 ++++++ 3 files changed, 56 insertions(+) diff --git a/src/character.cpp b/src/character.cpp index e8ebdf33e2a25..13972e90ff6ca 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5662,6 +5662,41 @@ void Character::try_reduce_weariness( const float exertion ) weary.low_activity_ticks = std::max( weary.low_activity_ticks, 0 ); } +// Remove all this instantaneous stuff when activity tracking moves to per turn +float Character::instantaneous_activity_level() const +{ + // As this is for display purposes, we want to show last turn's activity. + if( calendar::turn > act_turn ) { + return act_cursor; + } else { + return last_act; + } +} + +// Basically, advance one turn +void Character::reset_activity_cursor() +{ + + if( calendar::turn > act_turn ) { + last_act = act_cursor; + act_cursor = NO_EXERCISE; + act_turn = calendar::turn; + } else { + act_cursor = NO_EXERCISE; + } +} + +// Log the highest activity level for this turn, and advance one turn if needed +void Character::log_instant_activity( float level ) +{ + if( calendar::turn > act_turn ) { + reset_activity_cursor(); + act_cursor = level; + } else if( level > act_cursor ) { + act_cursor = level; + } +} + float Character::activity_level() const { float max = maximum_exertion_level(); @@ -8346,6 +8381,7 @@ void Character::increase_activity_level( float new_level ) if( attempted_activity_level < new_level ) { attempted_activity_level = new_level; } + log_instant_activity( new_level ); } void Character::decrease_activity_level( float new_level ) @@ -8353,10 +8389,12 @@ void Character::decrease_activity_level( float new_level ) if( attempted_activity_level > new_level ) { attempted_activity_level = new_level; } + log_instant_activity( new_level ); } void Character::reset_activity_level() { attempted_activity_level = NO_EXERCISE; + reset_activity_cursor(); } std::string Character::activity_level_str() const diff --git a/src/character.h b/src/character.h index ede86de70ba36..b21e2243e3ce6 100644 --- a/src/character.h +++ b/src/character.h @@ -2132,6 +2132,14 @@ class Character : public Creature, public visitable void reset_activity_level(); // outputs player activity level to a printable string std::string activity_level_str() const; + // NOT SUITABLE FOR USE OTHER THAN DISPLAY + // The activity level this turn + float instantaneous_activity_level() const; + // Basically, advance this display one turn + void reset_activity_cursor(); + // When we log an activity for metabolic purposes + // log it in our cursor too + void log_instant_activity( float ); /** Returns overall bashing resistance for the body_part */ int get_armor_bash( bodypart_id bp ) const override; @@ -2768,6 +2776,10 @@ class Character : public Creature, public visitable // the player's activity level for metabolism calculations float attempted_activity_level = NO_EXERCISE; + // Display purposes only - the highest activity this turn and last + float act_cursor = NO_EXERCISE; + float last_act = NO_EXERCISE; + time_point act_turn = calendar::turn_zero; trap_map known_traps; mutable std::map cached_info; diff --git a/src/game.cpp b/src/game.cpp index 1eacd5055d80d..dc0c9b63bd92a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1673,6 +1673,12 @@ bool game::do_turn() // reset player noise u.volume = 0; + // This is a hack! Remove this when we have per-turn activity tracking + // This prevents the display from erroneously updating when we use more + // than our allotted moves in a single turn + if( u.moves < 0 ) { + u.increase_activity_level( NO_EXERCISE ); + } return false; } From caf1702a87c379d2b68a3855495682fe8139ecde Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 26 Dec 2020 09:48:07 -0800 Subject: [PATCH 2/4] Add weariness transition information function This can be used to create a hp_bar or similar showing how far away the character is from the next weariness level. --- src/character.cpp | 18 ++++++++++++++++++ src/character.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/character.cpp b/src/character.cpp index 13972e90ff6ca..89a037cd5c7da 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -5571,6 +5571,24 @@ int Character::weariness() const return weary.tracker - weary.intake * 0.5; } +std::pair Character::weariness_transition_progress() const +{ + // Mostly a duplicate of the below function. No real way to clean this up + int amount = weariness(); + int threshold = weary_threshold(); + amount -= threshold * get_option( "WEARY_INITIAL_STEP" ); + while( amount >= 0 ) { + amount -= threshold; + if( threshold > 20 ) { + threshold *= get_option( "WEARY_THRESH_SCALING" ); + } + } + + // If we return the absolute value of the amount, it will work better + // Because as it decreases, we will approach a transition + return {std::abs( amount ), threshold}; +} + int Character::weariness_level() const { int amount = weariness(); diff --git a/src/character.h b/src/character.h index b21e2243e3ce6..92b41e6feb8f2 100644 --- a/src/character.h +++ b/src/character.h @@ -2696,6 +2696,8 @@ class Character : public Creature, public visitable bool defer_move( const tripoint &next ); time_duration get_consume_time( const item &it ); + // For display purposes mainly, how far we are from the next level of weariness + std::pair weariness_transition_progress() const; int weariness_level() const; int weary_threshold() const; int weariness() const; From fbede0bd663d2a527a25d800c9c095718c090cd1 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 26 Dec 2020 09:50:22 -0800 Subject: [PATCH 3/4] Add weariness and activity panel displays Add weariness and activity level display to the stat panel (in all layouts except the classic one), and a separate weariness panel showing distance from weariness transition as well as the malus to the current activity level. I should rewrite this code to be more generic and reduce duplication. The basic info is included in the stats panel because it is fairly vital to know, but the transition and extent of the malus are more reasonable to not know if you want more space in the sidebar panels. The names and contextualization for the data could probably use some work. --- src/panels.cpp | 270 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 268 insertions(+), 2 deletions(-) diff --git a/src/panels.cpp b/src/panels.cpp index fc3194f00a798..c6dcdd7b07d2e 100644 --- a/src/panels.cpp +++ b/src/panels.cpp @@ -993,6 +993,40 @@ static void draw_limb2( avatar &u, const catacurses::window &w ) wnoutrefresh( w ); } +static std::pair weariness_description( size_t weariness ) +{ + static const std::array, 6> weary_descriptions { { + {to_translation( "Fresh" ), c_green}, + {to_translation( "Light" ), c_yellow }, + {to_translation( "Moderate" ), c_light_red}, + {to_translation( "Weary" ), c_light_red }, + {to_translation( "Very" ), c_red }, + {to_translation( "Extreme" ), c_red } + } }; + // We can have more than level 5, but we don't really care about it + if( weariness >= weary_descriptions.size() ) { + weariness = 5; + } + return weary_descriptions[weariness]; +} + +static std::string activity_level_str( float level ) +{ + static const std::array activity_descriptions { { + to_translation( "None" ), + to_translation( "Light" ), + to_translation( "Moderate" ), + to_translation( "Brisk" ), + to_translation( "Active" ), + to_translation( "Extreme" ), + } }; + // Activity levels are 1, 2, 4, 6, 8, 10 + // So we can easily cut them in half and round down for an index + int idx = std::floor( level / 2 ); + + return activity_descriptions[idx].translated(); +} + static void draw_stats( avatar &u, const catacurses::window &w ) { werase( w ); @@ -1016,6 +1050,30 @@ static void draw_stats( avatar &u, const catacurses::window &w ) mvwprintz( w, point( 25, 0 ), c_light_gray, _( "PER" ) ); mvwprintz( w, point( stat < 10 ? 30 : 29, 0 ), stat_clr, stat < 100 ? to_string( stat ) : "99+" ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + if( u.exertion_adjusted_move_multiplier( activity ) < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + static const std::string weary_label = translate_marker( "WRY" ); + static const std::string activity_label = translate_marker( "ACT" ); + + const int wlabel_len = utf8_width( _( weary_label ) ); + const int alabel_len = utf8_width( _( activity_label ) ); + const int act_start = ( getmaxx( w ) / 2 ) - 1; + + mvwprintz( w, point_south, c_light_gray, _( weary_label ) ); + mvwprintz( w, point( wlabel_len + 1, 1 ), weary.second, weary.first.translated() ); + mvwprintz( w, point( act_start, 1 ), c_light_gray, _( activity_label ) ); + mvwprintz( w, point( act_start + alabel_len + 1, 1 ), act_color, activity_level_str( activity ) ); + wnoutrefresh( w ); } @@ -1309,6 +1367,30 @@ static void draw_stat_narrow( avatar &u, const catacurses::window &w ) mvwprintz( w, point( 19, 2 ), c_light_gray, _( "Safe :" ) ); mvwprintz( w, point( 8, 2 ), pwr_pair.first, "%s", pwr_pair.second ); mvwprintz( w, point( 26, 2 ), safe_color(), g->safe_mode ? _( "On" ) : _( "Off" ) ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + if( u.exertion_adjusted_move_multiplier( activity ) < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + static const std::string weary_label = translate_marker( "Weary:" ); + static const std::string activity_label = translate_marker( "Activ:" ); + + const int wlabel_len = utf8_width( _( weary_label ) ); + const int alabel_len = utf8_width( _( activity_label ) ); + const int act_start = ( getmaxx( w ) / 2 ) - 1; + + mvwprintz( w, point( 1, 3 ), c_light_gray, _( weary_label ) ); + mvwprintz( w, point( wlabel_len + 2, 3 ), weary.second, weary.first.translated() ); + mvwprintz( w, point( act_start, 3 ), c_light_gray, _( activity_label ) ); + mvwprintz( w, point( act_start + alabel_len + 1, 3 ), act_color, activity_level_str( activity ) ); + wnoutrefresh( w ); } @@ -1335,6 +1417,30 @@ static void draw_stat_wide( avatar &u, const catacurses::window &w ) mvwprintz( w, point( 31, 1 ), c_light_gray, _( "Safe :" ) ); mvwprintz( w, point( 38, 0 ), pwr_pair.first, "%s", pwr_pair.second ); mvwprintz( w, point( 38, 1 ), safe_color(), g->safe_mode ? _( "On" ) : _( "Off" ) ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + if( u.exertion_adjusted_move_multiplier( activity ) < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + static const std::string weary_label = translate_marker( "Weary:" ); + static const std::string activity_label = translate_marker( "Activ:" ); + + const int wlabel_len = utf8_width( _( weary_label ) ); + const int alabel_len = utf8_width( _( activity_label ) ); + const int act_start = ( getmaxx( w ) / 2 ) - 1; + + mvwprintz( w, point( 1, 2 ), c_light_gray, _( weary_label ) ); + mvwprintz( w, point( wlabel_len + 2, 2 ), weary.second, weary.first.translated() ); + mvwprintz( w, point( act_start, 2 ), c_light_gray, _( activity_label ) ); + mvwprintz( w, point( act_start + alabel_len + 1, 2 ), act_color, activity_level_str( activity ) ); + wnoutrefresh( w ); } @@ -1970,6 +2076,158 @@ static void draw_hint( const avatar &, const catacurses::window &w ) wnoutrefresh( w ); } +static void draw_weariness( const avatar &u, const catacurses::window &w ) +{ + werase( w ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + const float exertion_mult = u.exertion_adjusted_move_multiplier( activity ) ; + if( exertion_mult < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + std::pair bar = u.weariness_transition_progress(); + std::pair weary_bar = get_hp_bar( bar.first, bar.second ); + + static const std::string progress_label = translate_marker( "Transition:" ); + static const std::string malus_label = translate_marker( "Malus: " ); + + const int wplabel_len = utf8_width( _( progress_label ) ); + const int malus_start = getmaxx( w ) - utf8_width( _( malus_label ) ) - 5; + const int malus = ( 1 / exertion_mult ) * 100 - 100; + + const std::string malus_str = string_format( "%s+%3d%%", _( malus_label ), malus ); + + mvwprintz( w, point_zero, c_light_gray, _( progress_label ) ); + mvwprintz( w, point( wplabel_len + 1, 0 ), weary_bar.second, weary_bar.first ); + mvwprintz( w, point( malus_start, 0 ), act_color, malus_str ); + + wnoutrefresh( w ); +} + +static void draw_weariness_narrow( const avatar &u, const catacurses::window &w ) +{ + werase( w ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + const float exertion_mult = u.exertion_adjusted_move_multiplier( activity ) ; + if( exertion_mult < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + std::pair bar = u.weariness_transition_progress(); + std::pair weary_bar = get_hp_bar( bar.first, bar.second ); + + static const std::string progress_label = translate_marker( "Transition:" ); + static const std::string malus_label = translate_marker( "Malus: " ); + + const int wplabel_len = utf8_width( _( progress_label ) ); + const int malus_start = getmaxx( w ) - utf8_width( _( malus_label ) ) - 5; + const int malus = ( 1 / exertion_mult ) * 100 - 100; + + const std::string malus_str = string_format( "%s+%3d%%", _( malus_label ), malus ); + + mvwprintz( w, point_east, c_light_gray, _( progress_label ) ); + mvwprintz( w, point( wplabel_len + 1, 0 ), weary_bar.second, weary_bar.first ); + mvwprintz( w, point( malus_start, 0 ), act_color, malus_str ); + + wnoutrefresh( w ); +} + +static void draw_weariness_wide( const avatar &u, const catacurses::window &w ) +{ + werase( w ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + const float exertion_mult = u.exertion_adjusted_move_multiplier( activity ) ; + if( exertion_mult < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + std::pair bar = u.weariness_transition_progress(); + std::pair weary_bar = get_hp_bar( bar.first, bar.second ); + + static const std::string progress_label = translate_marker( "Weary Transition:" ); + static const std::string malus_label = translate_marker( "Weary Malus: " ); + + const int wplabel_len = utf8_width( _( progress_label ) ); + const int malus_start = getmaxx( w ) - utf8_width( _( malus_label ) ) - 5; + const int malus = ( 1 / exertion_mult ) * 100 - 100; + + const std::string malus_str = string_format( "%s+%3d%%", _( malus_label ), malus ); + + mvwprintz( w, point_east, c_light_gray, _( progress_label ) ); + mvwprintz( w, point( wplabel_len + 1, 0 ), weary_bar.second, weary_bar.first ); + mvwprintz( w, point( malus_start, 0 ), act_color, malus_str ); + + wnoutrefresh( w ); +} + +static void draw_weariness_classic( const avatar &u, const catacurses::window &w ) +{ + werase( w ); + + int weariness = u.weariness_level(); + std::pair weary = weariness_description( weariness ); + const float activity = u.instantaneous_activity_level(); + + nc_color act_color; + const float exertion_mult = u.exertion_adjusted_move_multiplier( activity ) ; + if( exertion_mult < 1.0 ) { + act_color = c_red; + } else { + act_color = c_light_gray; + } + + static const std::string weary_label = translate_marker( "Weariness:" ); + static const std::string activity_label = translate_marker( "Activity:" ); + + const int wlabel_len = utf8_width( _( weary_label ) ); + const int alabel_len = utf8_width( _( activity_label ) ); + const int act_start = std::floor( getmaxx( w ) / 2 ); + + mvwprintz( w, point_zero, c_light_gray, _( weary_label ) ); + mvwprintz( w, point( wlabel_len + 1, 0 ), weary.second, weary.first.translated() ); + mvwprintz( w, point( act_start, 0 ), c_light_gray, _( activity_label ) ); + mvwprintz( w, point( act_start + alabel_len + 1, 0 ), act_color, activity_level_str( activity ) ); + + std::pair bar = u.weariness_transition_progress(); + std::pair weary_bar = get_hp_bar( bar.first, bar.second ); + + static const std::string progress_label = translate_marker( "Weary Transition:" ); + static const std::string malus_label = translate_marker( "Weary Malus: " ); + + const int wplabel_len = utf8_width( _( progress_label ) ); + const int malus_start = getmaxx( w ) - utf8_width( _( malus_label ) ) - 5; + const int malus = ( 1 / exertion_mult ) * 100 - 100; + + const std::string malus_str = string_format( "%s+%3d%%", _( malus_label ), malus ); + + mvwprintz( w, point_south, c_light_gray, _( progress_label ) ); + mvwprintz( w, point( wplabel_len + 1, 1 ), weary_bar.second, weary_bar.first ); + mvwprintz( w, point( malus_start, 1 ), act_color, malus_str ); + + wnoutrefresh( w ); +} + static void print_mana( const player &u, const catacurses::window &w, const std::string &fmt_string, const int j1, const int j2, const int j3, const int j4 ) { @@ -2029,6 +2287,8 @@ static std::vector initialize_default_classic_panels() ret.emplace_back( window_panel( draw_health_classic, "Health", to_translation( "Health" ), 7, 44, true ) ); + ret.emplace_back( window_panel( draw_weariness_classic, "Weariness", to_translation( "Weariness" ), + 2, 44, true ) ); ret.emplace_back( window_panel( draw_location_classic, "Location", to_translation( "Location" ), 1, 44, true ) ); ret.emplace_back( window_panel( draw_mana_classic, "Mana", to_translation( "Mana" ), @@ -2069,6 +2329,8 @@ static std::vector initialize_default_compact_panels() ret.emplace_back( window_panel( draw_stealth, "Sound", to_translation( "Sound" ), 1, 32, true ) ); ret.emplace_back( window_panel( draw_stats, "Stats", to_translation( "Stats" ), + 2, 32, true ) ); + ret.emplace_back( window_panel( draw_weariness, "Weariness", to_translation( "Weariness" ), 1, 32, true ) ); ret.emplace_back( window_panel( draw_mana_compact, "Mana", to_translation( "Mana" ), 1, 32, true, spell_panel ) ); @@ -2111,7 +2373,9 @@ static std::vector initialize_default_label_narrow_panels() ret.emplace_back( window_panel( draw_mana_narrow, "Mana", to_translation( "Mana" ), 1, 32, true, spell_panel ) ); ret.emplace_back( window_panel( draw_stat_narrow, "Stats", to_translation( "Stats" ), - 3, 32, true ) ); + 4, 32, true ) ); + ret.emplace_back( window_panel( draw_weariness_narrow, "Weariness", to_translation( "Weariness" ), + 1, 32, true ) ); ret.emplace_back( window_panel( draw_veh_padding, "Vehicle", to_translation( "Vehicle" ), 1, 32, true ) ); ret.emplace_back( window_panel( draw_loc_narrow, "Location", to_translation( "Location" ), @@ -2157,7 +2421,9 @@ static std::vector initialize_default_label_panels() ret.emplace_back( window_panel( draw_mana_wide, "Mana", to_translation( "Mana" ), 1, 44, true, spell_panel ) ); ret.emplace_back( window_panel( draw_stat_wide, "Stats", to_translation( "Stats" ), - 2, 44, true ) ); + 3, 44, true ) ); + ret.emplace_back( window_panel( draw_weariness_wide, "Weariness", to_translation( "Weariness" ), + 1, 44, true ) ); ret.emplace_back( window_panel( draw_veh_padding, "Vehicle", to_translation( "Vehicle" ), 1, 44, true ) ); ret.emplace_back( window_panel( draw_loc_wide_map, "Location", to_translation( "Location" ), From 30fc49bc2f7b7431c22d9d178ecbb536430b0501 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Sat, 26 Dec 2020 10:16:03 -0800 Subject: [PATCH 4/4] Show effects of weariness in effect description Now that activity levels are publicly shown, these can explain their effects in detail. --- data/json/effects.json | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/data/json/effects.json b/data/json/effects.json index c67f5b53cc091..fe12c140b940c 100644 --- a/data/json/effects.json +++ b/data/json/effects.json @@ -2355,49 +2355,65 @@ "type": "effect_type", "id": "weary_1", "name": [ "Lightly Weary" ], - "desc": [ "You've been pretty active for a while; operating at the highest levels of activity will be impaired." ] + "desc": [ + "You've been pretty active for a while; operating at the highest levels of activity will be impaired.\nThe following move penalties are applied for the following activity levels:\nExtreme: 1.25x" + ] }, { "type": "effect_type", "id": "weary_2", "name": [ "Moderately Weary" ], - "desc": [ "You've been quite active for a while; operating at higher levels of activity will be impaired." ] + "desc": [ + "You've been quite active for a while; operating at higher levels of activity will be impaired.\nThe following move penalties are applied for the following activity levels:\nExtreme: 1.67x, Active: 1.33x" + ] }, { "type": "effect_type", "id": "weary_3", "name": [ "Weary" ], - "desc": [ "You've been very active for a while, and need to slow down for a bit." ] + "desc": [ + "You've been very active for a while, and need to slow down for a bit.\nThe following move penalties are applied for the following activity levels:\nExtreme: 2.5x, Active: 2x, Brisk: 1.5x" + ] }, { "type": "effect_type", "id": "weary_4", "name": [ "Very Weary" ], - "desc": [ "You've been extremely active for a while, and need to slow down." ] + "desc": [ + "You've been extremely active for a while, and need to slow down.\nThe following move penalties are applied for the following activity levels:\nExtreme: 5x, Active: 4x, Brisk: 3x, Moderate: 2x" + ] }, { "type": "effect_type", "id": "weary_5", "name": [ "Extremely Weary" ], - "desc": [ "You've been extremely active for a while, and can't take much more activity." ] + "desc": [ + "You've been extremely active for a while, and can't take much more activity.\nThe following move penalties are applied for the following activity levels:\nExtreme: 10x, Active: 8x, Brisk: 6x, Moderate: 4x, Light: 2x" + ] }, { "type": "effect_type", "id": "weary_6", "name": [ "Extremely Weary" ], - "desc": [ "You've been extremely active for a while, and really need to get some rest." ] + "desc": [ + "You've been extremely active for a while, and really need to get some rest.\nThe following move penalties are applied for the following activity levels:\nExtreme: 10x, Active: 8x, Brisk: 6x, Moderate: 4x, Light: 2x" + ] }, { "type": "effect_type", "id": "weary_7", "name": [ "Extremely Weary" ], - "desc": [ "You've been extremely active for a while; it's time to stop." ] + "desc": [ + "You've been extremely active for a while; it's time to stop.\nThe following move penalties are applied for the following activity levels:\nExtreme: 10x, Active: 8x, Brisk: 6x, Moderate: 4x, Light: 2x" + ] }, { "type": "effect_type", "id": "weary_8", "name": [ "Extremely Weary" ], - "desc": [ "You've been extremely active for a while, and can no longer keep pushing." ] + "desc": [ + "You've been extremely active for a while, and can no longer keep pushing.\nThe following move penalties are applied for the following activity levels:\nExtreme: 10x, Active: 8x, Brisk: 6x, Moderate: 4x, Light: 2x" + ] }, { "type": "effect_type",