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

Add a new weariness panel display #46193

Closed
Closed
32 changes: 24 additions & 8 deletions data/json/effects.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
56 changes: 56 additions & 0 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5571,6 +5571,24 @@ int Character::weariness() const
return weary.tracker - weary.intake * 0.5;
}

std::pair<int, int> 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<float>( "WEARY_INITIAL_STEP" );
while( amount >= 0 ) {
amount -= threshold;
if( threshold > 20 ) {
threshold *= get_option<float>( "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();
Expand Down Expand Up @@ -5662,6 +5680,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();
Expand Down Expand Up @@ -8346,17 +8399,20 @@ 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 )
{
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
Expand Down
14 changes: 14 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,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;
Expand Down Expand Up @@ -2689,6 +2697,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<int, int> weariness_transition_progress() const;
int weariness_level() const;
int weary_threshold() const;
int weariness() const;
Expand Down Expand Up @@ -2769,6 +2779,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<std::string, double> cached_info;
Expand Down
6 changes: 6 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
102 changes: 102 additions & 0 deletions src/panels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,23 @@ static void draw_limb2( avatar &u, const catacurses::window &w )
wnoutrefresh( w );
}

static std::pair<translation, nc_color> weariness_description( size_t weariness )
{
static const std::array<std::pair<translation, nc_color>, 6> weary_descriptions { {
{ to_translation( "Fresh" ), c_white },
{ to_translation( "Light" ), c_green },
{ to_translation( "Moderate" ), c_light_green },
{ to_translation( "Weary" ), c_yellow },
{ to_translation( "Very" ), c_light_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 void draw_stats( avatar &u, const catacurses::window &w )
{
werase( w );
Expand Down Expand Up @@ -2009,6 +2026,83 @@ static void draw_mana_wide( const player &u, const catacurses::window &w )
print_mana( u, w, " %s: %s %s : %s", -5, -5, 13, -5 );
}

static void print_weary( const player &u, const catacurses::window &w,
const std::string &fmt_string,
const int j1, const int j2 )
{
werase( w );

std::pair<int, int> transition = u.weariness_transition_progress();
std::pair<std::string, nc_color> weary_bar = get_hp_bar( transition.first, transition.second );
const float activity_level = u.instantaneous_activity_level();
int weariness = u.weariness_level();
std::pair<translation, nc_color> weary_label = weariness_description( weariness );

int no_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
NO_EXERCISE ) ) );
int light_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
LIGHT_EXERCISE ) ) );
int moderate_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
MODERATE_EXERCISE ) ) );
int brisk_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
BRISK_EXERCISE ) ) );
int active_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
ACTIVE_EXERCISE ) ) );
int extra_speed = static_cast<int>( std::round( 100 / u.exertion_adjusted_move_multiplier(
EXTRA_EXERCISE ) ) );

nc_color gray = c_light_gray;
std::string speeds = string_format( "%s/%s/%s/%s/%s/%s",
colorize( string_format( "%i", no_speed ), activity_level == NO_EXERCISE ? c_white : gray ),
colorize( string_format( "%i", light_speed ),
activity_level == LIGHT_EXERCISE ? c_green : gray ),
colorize( string_format( "%i", moderate_speed ),
activity_level == MODERATE_EXERCISE ? c_light_green : gray ),
colorize( string_format( "%i", brisk_speed ),
activity_level == BRISK_EXERCISE ? c_yellow : gray ),
colorize( string_format( "%i", active_speed ),
activity_level == ACTIVE_EXERCISE ? c_light_red : gray ),
colorize( string_format( "%i", extra_speed ), activity_level == EXTRA_EXERCISE ? c_red : gray )
);

const std::string weary_string = string_format( fmt_string,
utf8_justify( _( "Weary" ), j1 ),
colorize( utf8_justify( weary_label.first.translated(), -8 ), weary_label.second ) );
const std::string penalty_string = string_format( fmt_string,
utf8_justify( _( "Speed" ), j1 ),
speeds );
print_colored_text( w, point_zero, gray, gray, weary_string );
print_colored_text( w, point( 0, 1 ), gray, gray, penalty_string );

mvwprintz( w, point( j2 - 4, 0 ), weary_bar.second, weary_bar.first );
int width = utf8_width( weary_bar.first );
for( int i = 0; i < 5 - width; i++ ) {
mvwprintz( w, point( j2 - i, 0 ), c_white, "." );
}

wnoutrefresh( w );
}

static void draw_weary_wide( const player &u, const catacurses::window &w )
{
print_weary( u, w, " %s: %s", 5, 27 );
}

static void draw_weary_narrow( const player &u, const catacurses::window &w )
{
print_weary( u, w, " %s: %s", 5, 23 );
}

static void draw_weary_compact( const player &u, const catacurses::window &w )
{
print_weary( u, w, "%s%s", 5, 20 );
}

static void draw_weary_classic( const player &u, const catacurses::window &w )
{
print_weary( u, w, "%s : %s", 5, 25 );
}

// ============
// INITIALIZERS
// ============
Expand All @@ -2031,6 +2125,8 @@ static std::vector<window_panel> initialize_default_classic_panels()
7, 44, true ) );
ret.emplace_back( window_panel( draw_location_classic, "Location", to_translation( "Location" ),
1, 44, true ) );
ret.emplace_back( window_panel( draw_weary_classic, "Weariness", to_translation( "Weariness" ),
2, 44, true ) );
ret.emplace_back( window_panel( draw_mana_classic, "Mana", to_translation( "Mana" ),
1, 44, true, spell_panel ) );
ret.emplace_back( window_panel( draw_weather_classic, "Weather", to_translation( "Weather" ),
Expand Down Expand Up @@ -2070,6 +2166,8 @@ static std::vector<window_panel> initialize_default_compact_panels()
1, 32, true ) );
ret.emplace_back( window_panel( draw_stats, "Stats", to_translation( "Stats" ),
1, 32, true ) );
ret.emplace_back( window_panel( draw_weary_compact, "Weariness", to_translation( "Weariness" ),
2, 32, true ) );
ret.emplace_back( window_panel( draw_mana_compact, "Mana", to_translation( "Mana" ),
1, 32, true, spell_panel ) );
ret.emplace_back( window_panel( draw_time, "Time", to_translation( "Time" ),
Expand Down Expand Up @@ -2108,6 +2206,8 @@ static std::vector<window_panel> initialize_default_label_narrow_panels()
3, 32, true ) );
ret.emplace_back( window_panel( draw_char_narrow, "Movement", to_translation( "Movement" ),
3, 32, true ) );
ret.emplace_back( window_panel( draw_weary_narrow, "Weariness", to_translation( "Weariness" ),
2, 32, true ) );
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" ),
Expand Down Expand Up @@ -2154,6 +2254,8 @@ static std::vector<window_panel> initialize_default_label_panels()
2, 44, true ) );
ret.emplace_back( window_panel( draw_char_wide, "Movement", to_translation( "Movement" ),
2, 44, true ) );
ret.emplace_back( window_panel( draw_weary_wide, "Weariness", to_translation( "Weariness" ),
2, 44, true ) );
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" ),
Expand Down