1 /** 2 * @file 3 * @brief Tracks monsters the player has killed. 4 **/ 5 6 #pragma once 7 8 #include <cstdio> 9 #include <map> 10 #include <string> 11 #include <vector> 12 13 #include "enum.h" 14 15 class monster; 16 struct monster_info; 17 class reader; 18 class writer; 19 20 // Not intended for external use! 21 struct kill_monster_desc 22 { 23 kill_monster_desc(const monster*); 24 kill_monster_desc(const monster_info&); kill_monster_desckill_monster_desc25 kill_monster_desc() { } 26 27 void save(writer&) const; 28 void load(reader&); 29 30 enum name_modifier 31 { 32 M_NORMAL, M_ZOMBIE, M_SKELETON, M_SIMULACRUM, M_SPECTRE, 33 M_SHAPESHIFTER, // A shapeshifter pretending to be 'monnum' 34 }; 35 36 monster_type monnum; // Number of the beast 37 name_modifier modifier; // Nature of the beast 38 39 struct less_than 40 { operatorkill_monster_desc::less_than41 bool operator () (const kill_monster_desc &m1, 42 const kill_monster_desc &m2) const 43 { 44 return m1.monnum < m2.monnum 45 || (m1.monnum == m2.monnum && m1.modifier < m2.modifier); 46 } 47 }; 48 }; 49 50 #define PLACE_LIMIT 5 // How many unique kill places we're prepared to track 51 class kill_def 52 { 53 public: 54 kill_def(const monster* mon); kill_def()55 kill_def() : kills(0), exp(0) 56 { 57 // This object just says to the world that it's uninitialised 58 } 59 60 void save(writer&) const; 61 void load(reader&); 62 63 void add_kill(const monster* mon, level_id place); 64 void add_place(level_id place, bool force = false); 65 66 void merge(const kill_def &k, bool unique_monster); 67 68 string info(const kill_monster_desc &md) const; 69 string base_name(const kill_monster_desc &md) const; 70 71 unsigned short kills; // How many kills does the player have? 72 int exp; // Experience gained for slaying the beast. 73 // Only set *once*, even for shapeshifters. 74 75 vector<level_id> places; // Places where we've killed the beast. 76 private: 77 string append_places(const kill_monster_desc &md, const string &name) const; 78 }; 79 80 // Ghosts and random Pandemonium demons. 81 class kill_ghost 82 { 83 public: 84 kill_ghost(const monster* mon); kill_ghost()85 kill_ghost() { } 86 87 void save(writer&) const; 88 void load(reader&); 89 90 string info() const; 91 92 string ghost_name; 93 int exp; 94 level_id place; 95 }; 96 97 // This is the structure that Lua sees. 98 struct kill_exp 99 { 100 int nkills; 101 int exp; 102 string base_name; 103 string desc; 104 105 monster_type monnum; // Number of the beast 106 int modifier; // Nature of the beast 107 108 vector<level_id> places; 109 kill_expkill_exp110 kill_exp(const kill_def &k, const kill_monster_desc &md) 111 : nkills(k.kills), exp(k.exp), base_name(k.base_name(md)), 112 desc(k.info(md)), 113 monnum(md.monnum), modifier(md.modifier), places(k.places) 114 { 115 } 116 kill_expkill_exp117 kill_exp(const kill_ghost &kg) 118 : nkills(1), exp(kg.exp), base_name(), desc(kg.info()), 119 monnum(MONS_PROGRAM_BUG), modifier(0) 120 { 121 places.push_back(kg.place); 122 } 123 124 // operator< is implemented for a descending sort. 125 bool operator < (const kill_exp &b) const 126 { 127 return exp == b.exp? (base_name < b.base_name) : (exp > b.exp); 128 } 129 }; 130 131 class Kills 132 { 133 public: 134 void record_kill(const monster* mon); 135 void merge(const Kills &k); 136 137 bool empty() const; 138 void save(writer&) const; 139 void load(reader&); 140 141 int get_kills(vector<kill_exp> &v) const; 142 int num_kills(const monster* mon) const; 143 int num_kills(const monster_info& mon) const; 144 private: 145 int num_kills(kill_monster_desc desc) const; 146 147 typedef map<kill_monster_desc, kill_def, 148 kill_monster_desc::less_than> kill_map; 149 typedef vector<kill_ghost> ghost_vec; 150 151 kill_map kills; 152 ghost_vec ghosts; 153 154 void record_ghost_kill(const monster* mon); 155 }; 156 157 class KillMaster 158 { 159 public: 160 void record_kill(const monster* mon, int killer, bool ispet); 161 162 bool empty() const; 163 void save(writer&) const; 164 void load(reader&); 165 166 // Number of kills, by category. 167 int num_kills(const monster* mon, kill_category cat) const; 168 int num_kills(const monster_info& mon, kill_category cat) const; 169 // Number of kills, any category. 170 int num_kills(const monster* mon) const; 171 int num_kills(const monster_info& mon) const; 172 173 int total_kills() const; 174 175 string kill_info() const; 176 private: 177 const char *category_name(kill_category kc) const; 178 179 Kills categorized_kills[KC_NCATEGORIES]; 180 private: 181 void add_kill_info(string &, vector<kill_exp> &, 182 int count, const char *c, bool separator) const; 183 }; 184 185 enum KILL_DUMP_OPTIONS 186 { 187 KDO_NO_PLACES, // Don't dump places at all 188 KDO_ONE_PLACE, // Show places only for single kills and uniques. 189 KDO_ALL_PLACES, // Show all available place information 190 }; 191