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

Updates Morale Menu for clarity #31164

Merged
merged 9 commits into from
Jun 13, 2019
117 changes: 110 additions & 7 deletions src/morale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,16 @@ time_duration player_morale::morale_point::pick_time( const time_duration curren
return ( remaining_time <= new_time && same_sign ) ? new_time : remaining_time;
}

void player_morale::morale_point::set_percent_contribution( double contribution )
{
percent_contribution = contribution;
}


double player_morale::morale_point::get_percent_contribution()
{
return percent_contribution;
}
void player_morale::morale_point::decay( const time_duration ticks )
{
if( ticks < 0_turns ) {
Expand Down Expand Up @@ -348,6 +358,61 @@ morale_mult player_morale::get_temper_mult() const
return mult;
}

void player_morale::calculate_percentage()
{
const morale_mult mult = get_temper_mult();

int sum_of_positive_squares = 0;
int sum_of_negative_squares = 0;

for( auto &m : points ) {
const int bonus = m.get_net_bonus( mult );
if( bonus > 0 ) {
sum_of_positive_squares += pow( bonus, 2 );
} else {
sum_of_negative_squares += pow( bonus, 2 );
}
}

for( auto &m : points ) {
const int bonus = m.get_net_bonus( mult );
if( bonus > 0 ) {
m.set_percent_contribution( ( pow( bonus, 2 ) / sum_of_positive_squares ) * 100 );
} else {
m.set_percent_contribution( ( pow( bonus, 2 ) / sum_of_negative_squares ) * 100 );
}
}
}

int player_morale::get_total_negative_value() const
{
const morale_mult mult = get_temper_mult();
int sum = 0;
for( auto &m : points ) {
const int bonus = m.get_net_bonus( mult );
if( bonus < 0 ) {
sum += pow( bonus, 2 );
}
}
return sqrt( sum );
}

int player_morale::get_total_positive_value() const
{
const morale_mult mult = get_temper_mult();
int sum = 0;
for( auto &m : points ) {
const int bonus = m.get_net_bonus( mult );
if( bonus > 0 ) {
sum += pow( bonus, 2 );
}

}
return sqrt( sum );
}



int player_morale::get_level() const
{
if( !level_is_valid ) {
Expand Down Expand Up @@ -394,11 +459,16 @@ void player_morale::decay( const time_duration ticks )

void player_morale::display( double focus_gain )
{
const char *morale_gain_caption = _( "Total morale gain" );
/*calculates the percent contributions of the morale points,
* must be done before anything else in this method
*/
calculate_percentage();

const char *morale_gain_caption = _( "Total morale change" );
const char *focus_gain_caption = _( "Focus gain per minute" );
const char *points_is_empty = _( "Nothing affects your morale" );

int w_extra = 8;
int w_extra = 16;

// Figure out how wide the source column needs to be.
int source_column_width = std::max( utf8_width( morale_gain_caption ),
Expand All @@ -417,14 +487,24 @@ void player_morale::display( double focus_gain )
const int win_y = ( TERMY - win_h ) / 2;

catacurses::window w = catacurses::newwin( win_h, win_w, win_y, win_x );

const auto print_line = [ w ]( int y, const char *label, double value ) -> int {
//lambda function used to print almost everything to the window
const auto print_line = [ w ]( int y, const char *label, double value, bool isPercentage = false,
nc_color color_override = c_unset ) -> int {
nc_color color;
if( value != 0.0 )
{
const int decimals = ( value - static_cast<int>( value ) != 0.0 ) ? 2 : 0;
color = ( value > 0.0 ) ? c_green : c_red;
mvwprintz( w, y, getmaxx( w ) - 8, color, "%+6.*f", decimals, value );
if( color_override == c_unset ) {
color = ( value > 0.0 ) ? c_green : c_light_red;
} else {
color = color_override;
}
if( isPercentage ) {
mvwprintz( w, y, getmaxx( w ) - 8, color, "%6.*f%%", decimals, value );
} else {
mvwprintz( w, y, getmaxx( w ) - 8, color, "%+6.*f", decimals, value );
}

} else
{
color = c_dark_gray;
Expand All @@ -439,6 +519,7 @@ void player_morale::display( double focus_gain )

for( ;; ) {

//creates the window
werase( w );

draw_border( w );
Expand All @@ -456,18 +537,40 @@ void player_morale::display( double focus_gain )
if( !points.empty() ) {
const char *source_column = _( "Source" );
const char *value_column = _( "Value" );
const char *total_positve_label = _( "Total positive morale" );
const char *total_negitive_label = _( "Total negative morale" );

mvwprintz( w, 3, 2, c_light_gray, source_column );
mvwprintz( w, 3, win_w - utf8_width( value_column ) - 2, c_light_gray, value_column );

const morale_mult mult = get_temper_mult();

int line = 0;
line += print_line( 4 + line, total_positve_label, get_total_positive_value(), false,
c_light_green );
//prints out all the positive morale effects
for( size_t i = offset; i < static_cast<size_t>( rows_total ); ++i ) {
const std::string name = points[i].get_name();
const int bonus = points[i].get_net_bonus( mult );
if( bonus > 0 ) {
line += print_line( 4 + line, name.c_str(), points[i].get_percent_contribution(), true );
}

line += print_line( 4 + line, name.c_str(), bonus );
if( line >= rows_visible ) {
break; // This prevents overflowing (unlikely, but just in case)
}
}
line++; //adds a space in the GUI
//prints out all the negitve morale effects
line += print_line( 4 + line, total_negitive_label, -1 * get_total_negative_value(), false, c_red );

for( size_t i = offset; i < static_cast<size_t>( rows_total ); ++i ) {
const std::string name = points[i].get_name();
const int bonus = points[i].get_net_bonus( mult );
if( bonus < 0 ) {
line += print_line( 4 + line, name.c_str(), points[i].get_percent_contribution(), true,
c_light_red );
}
if( line >= rows_visible ) {
break; // This prevents overflowing (unlikely, but just in case)
}
Expand Down
18 changes: 17 additions & 1 deletion src/morale.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ class player_morale
* Only permanent morale is checked */
bool consistent_with( const player_morale &morale ) const;

/**calculates the percentage contribution for each morale point*/
void calculate_percentage();

int get_total_positive_value() const;
int get_total_negative_value() const;


void on_mutation_gain( const trait_id &mid );
void on_mutation_loss( const trait_id &mid );
void on_stat_change( const std::string &stat, int value );
Expand All @@ -66,6 +73,7 @@ class player_morale
void load( JsonObject &jsin );

private:

class morale_point
{
public:
Expand Down Expand Up @@ -99,7 +107,11 @@ class player_morale
void add( int new_bonus, int new_max_bonus, time_duration new_duration,
time_duration new_decay_start, bool new_cap );
void decay( time_duration ticks = 1_turns );

/*
*contribution should be bettween [0,100] (inclusive)
*/
void set_percent_contribution( double contribution );
double get_percent_contribution();
private:
morale_type type;
const itype *item_type;
Expand All @@ -108,6 +120,10 @@ class player_morale
time_duration duration; // Zero duration == infinity
time_duration decay_start;
time_duration age;
/**
*this point's percent contribution to the total positive or total negative morale effect
*/
double percent_contribution;

/**
* Returns either new_time or remaining time (which one is greater).
Expand Down