/* * File: kills.h * Summary: Tracks monsters the player has killed. * Written by: Darshan Shaligram */ #ifndef KILLS_H #define KILLS_H #include #include #include #include #include "enum.h" std::string apostrophise(const std::string &name); std::string apostrophise_fixup(const std::string &sentence); class monsters; class reader; class writer; // Not intended for external use! struct kill_monster_desc { kill_monster_desc(const monsters *); kill_monster_desc() { } void save(writer&) const; void load(reader&); enum name_modifier { M_NORMAL, M_ZOMBIE, M_SKELETON, M_SIMULACRUM, M_SPECTRE, M_SHAPESHIFTER // A shapeshifter pretending to be 'monnum' }; int monnum; // Number of the beast name_modifier modifier; // Nature of the beast struct less_than { bool operator () (const kill_monster_desc &m1, const kill_monster_desc &m2) const { return (m1.monnum < m2.monnum || (m1.monnum == m2.monnum && m1.modifier < m2.modifier)); } }; }; #define PLACE_LIMIT 5 // How many unique kill places we're prepared to track class kill_def { public: kill_def(const monsters *mon); kill_def() : kills(0), exp(0) { // This object just says to the world that it's uninitialised } void save(writer&) const; void load(reader&); void add_kill(const monsters *mon, unsigned short place); void add_place(unsigned short place, bool force = false); void merge(const kill_def &k, bool unique_monster); std::string info(const kill_monster_desc &md) const; std::string base_name(const kill_monster_desc &md) const; unsigned short kills; // How many kills does the player have? int exp; // Experience gained for slaying the beast. // Only set *once*, even for shapeshifters. std::vector places; // Places where we've killed the beast. private: std::string append_places(const kill_monster_desc &md, const std::string &name) const; }; // Ghosts and random Pandemonium demons. class kill_ghost { public: kill_ghost(const monsters *mon); kill_ghost() { } void save(writer&) const; void load(reader&); std::string info() const; std::string ghost_name; int exp; unsigned short place; }; // This is the structure that Lua sees. struct kill_exp { int nkills; int exp; std::string base_name; std::string desc; int monnum; // Number of the beast int modifier; // Nature of the beast std::vector places; kill_exp(const kill_def &k, const kill_monster_desc &md) : nkills(k.kills), exp(k.exp), base_name(k.base_name(md)), desc(k.info(md)), monnum(md.monnum), modifier(md.modifier) { places = k.places; } kill_exp(const kill_ghost &kg) : nkills(1), exp(kg.exp), base_name(), desc(kg.info()), monnum(-1), modifier(0) { places.push_back(kg.place); } // operator< is implemented for a descending sort. bool operator < ( const kill_exp &b) const { return exp == b.exp? (base_name < b.base_name) : (exp > b.exp); } }; class Kills { public: void record_kill(const monsters *mon); void merge(const Kills &k); bool empty() const; void save(writer&) const; void load(reader&); long get_kills(std::vector &v) const; int num_kills(const monsters *mon) const; private: typedef std::map kill_map; typedef std::vector ghost_vec; kill_map kills; ghost_vec ghosts; void record_ghost_kill(const monsters *mon); }; class KillMaster { public: KillMaster(); KillMaster(const KillMaster& other); ~KillMaster(); void record_kill(const monsters *mon, int killer, bool ispet); bool empty() const; void save(writer&) const; void load(reader&); // Number of kills, by category. long num_kills(const monsters *mon, kill_category cat) const; // Number of kills, any category. long num_kills(const monsters *mon) const; long total_kills() const; std::string kill_info() const; private: const char *category_name(kill_category kc) const; Kills categorized_kills[KC_NCATEGORIES]; private: void add_kill_info(std::string &, std::vector &, long count, const char *c, bool separator) const; }; enum KILL_DUMP_OPTIONS { KDO_NO_PLACES, // Don't dump places at all KDO_ONE_PLACE, // Show places only for single kills and uniques. KDO_ALL_PLACES // Show all available place information }; #endif