1 #pragma once 2 #ifndef CATA_SRC_MORALE_H 3 #define CATA_SRC_MORALE_H 4 5 #include <algorithm> 6 #include <functional> 7 #include <iosfwd> 8 #include <map> 9 #include <vector> 10 11 #include "calendar.h" 12 #include "morale_types.h" 13 #include "type_id.h" 14 15 class JsonIn; 16 class JsonObject; 17 class JsonOut; 18 class item; 19 struct itype; 20 struct morale_mult; 21 22 class player_morale 23 { 24 public: 25 player_morale(); 26 27 player_morale( player_morale && ) noexcept = default; 28 player_morale( const player_morale & ) = default; 29 player_morale &operator =( player_morale && ) = default; 30 player_morale &operator =( const player_morale & ) = default; 31 32 /** Adds morale to existing or creates one */ 33 void add( const morale_type &type, int bonus, int max_bonus = 0, 34 const time_duration &duration = 6_minutes, const time_duration &decay_start = 3_minutes, 35 bool capped = false, const itype *item_type = nullptr ); 36 /** Sets the new level for the permanent morale, or creates one */ 37 void set_permanent( const morale_type &type, int bonus, const itype *item_type = nullptr ); 38 /** Returns bonus from specified morale */ 39 int has( const morale_type &type, const itype *item_type = nullptr ) const; 40 /** Removes specified morale */ 41 void remove( const morale_type &type, const itype *item_type = nullptr ); 42 /** Clears up all morale points */ 43 void clear(); 44 /** Returns overall morale level */ 45 int get_level() const; 46 /** Ticks down morale counters and removes them */ 47 void decay( const time_duration &ticks = 1_turns ); 48 /** Displays morale screen */ 49 void display( int focus_eq, int pain_penalty, int fatigue_penalty ); 50 /** Returns false whether morale is inconsistent with the argument. 51 * Only permanent morale is checked */ 52 bool consistent_with( const player_morale &morale ) const; 53 54 /**calculates the percentage contribution for each morale point*/ 55 void calculate_percentage(); 56 57 int get_total_positive_value() const; 58 int get_total_negative_value() const; 59 60 /** Returns perceived pain. Only used in morale_test.cpp*/ 61 int get_perceived_pain() const; 62 63 void on_mutation_gain( const trait_id &mid ); 64 void on_mutation_loss( const trait_id &mid ); 65 void on_stat_change( const std::string &stat, int value ); 66 void on_item_wear( const item &it ); 67 void on_item_takeoff( const item &it ); 68 void on_worn_item_transform( const item &old_it, const item &new_it ); 69 void on_worn_item_washed( const item &it ); 70 void on_effect_int_change( const efftype_id &eid, int intensity, 71 const bodypart_id &bp = bodypart_id( "bp_null" ) ); 72 73 void store( JsonOut &jsout ) const; 74 void load( const JsonObject &jsin ); 75 76 private: 77 78 class morale_point 79 { 80 public: 81 explicit morale_point( 82 const morale_type &type = MORALE_NULL, 83 const itype *item_type = nullptr, 84 int bonus = 0, 85 int max_bonus = 0, 86 time_duration duration = 6_minutes, 87 time_duration decay_start = 3_minutes, 88 bool capped = false ) : 89 type(type)90 type( type ), 91 item_type( item_type ), 92 bonus( normalize_bonus( bonus, max_bonus, capped ) ), 93 duration( std::max( duration, 0_turns ) ), 94 decay_start( std::max( decay_start, 0_turns ) ), 95 age( 0_turns ) {} 96 97 void deserialize( JsonIn &jsin ); 98 void serialize( JsonOut &json ) const; 99 100 std::string get_name() const; 101 int get_net_bonus() const; 102 int get_net_bonus( const morale_mult &mult ) const; 103 bool is_expired() const; 104 bool is_permanent() const; 105 bool matches( const morale_type &_type, const itype *_item_type = nullptr ) const; 106 bool matches( const morale_point &mp ) const; 107 108 void add( int new_bonus, int new_max_bonus, time_duration new_duration, 109 time_duration new_decay_start, bool new_cap ); 110 void decay( const time_duration &ticks = 1_turns ); 111 /* 112 *contribution should be between [0,100] (inclusive) 113 */ 114 void set_percent_contribution( double contribution ); 115 double get_percent_contribution() const; 116 private: 117 morale_type type; 118 const itype *item_type; 119 120 int bonus = 0; 121 time_duration duration = 0_turns; // Zero duration == infinity 122 time_duration decay_start = 0_turns; 123 time_duration age = 0_turns; 124 /** 125 *this point's percent contribution to the total positive or total negative morale effect 126 */ 127 double percent_contribution = 0; 128 129 /** 130 * Returns either new_time or remaining time (which one is greater). 131 * Only returns new time if same_sign is true 132 */ 133 time_duration pick_time( const time_duration ¤t_time, const time_duration &new_time, 134 bool same_sign ) const; 135 /** 136 * Returns normalized bonus if either max_bonus != 0 or capped == true 137 */ 138 int normalize_bonus( int bonus, int max_bonus, bool capped ) const; 139 }; 140 protected: 141 morale_mult get_temper_mult() const; 142 143 void set_prozac( bool new_took_prozac ); 144 void set_prozac_bad( bool new_took_prozac_bad ); 145 void set_stylish( bool new_stylish ); 146 void set_worn( const item &it, bool worn ); 147 void set_mutation( const trait_id &mid, bool active ); 148 bool has_mutation( const trait_id &mid ); 149 bool has_flag( const json_character_flag &flag ); 150 151 void remove_if( const std::function<bool( const morale_point & )> &func ); 152 void remove_expired(); 153 void invalidate(); 154 155 void update_stylish_bonus(); 156 void update_squeamish_penalty(); 157 void update_masochist_bonus(); 158 void update_bodytemp_penalty( const time_duration &ticks ); 159 void update_constrained_penalty(); 160 161 private: 162 std::vector<morale_point> points; 163 164 struct body_part_data { 165 unsigned int covered; 166 unsigned int fancy; 167 unsigned int filthy; 168 int hot; 169 int cold; 170 body_part_databody_part_data171 body_part_data() : 172 covered( 0 ), 173 fancy( 0 ), 174 filthy( 0 ), 175 hot( 0 ), 176 cold( 0 ) {} 177 }; 178 std::map<bodypart_id, body_part_data> body_parts; 179 body_part_data no_body_part; 180 181 using mutation_handler = std::function<void ( player_morale * )>; 182 struct mutation_data { 183 public: 184 mutation_data() = default; mutation_datamutation_data185 explicit mutation_data( const mutation_handler &on_gain_and_loss ) : 186 on_gain( on_gain_and_loss ), 187 on_loss( on_gain_and_loss ) {} mutation_datamutation_data188 mutation_data( const mutation_handler &on_gain, const mutation_handler &on_loss ) : 189 on_gain( on_gain ), 190 on_loss( on_loss ) {} 191 void set_active( player_morale *sender, bool new_active ); 192 bool get_active() const; 193 void clear(); 194 private: 195 mutation_handler on_gain; 196 mutation_handler on_loss; 197 bool active = false; 198 }; 199 std::map<trait_id, mutation_data> mutations; 200 201 std::map<itype_id, int> super_fancy_items; 202 203 // Mutability is required for lazy initialization 204 mutable int level; 205 mutable bool level_is_valid; 206 207 bool took_prozac; 208 bool took_prozac_bad; 209 bool stylish; 210 int perceived_pain; 211 }; 212 213 #endif // CATA_SRC_MORALE_H 214