/* * pc.h * BoE * * Created by Celtic Minstrel on 24/04/09. * */ #ifndef BOE_DATA_PC_H #define BOE_DATA_PC_H #include #include #include #include #include #include #include #include "scenario/item.hpp" #include "dialogxml/widgets/pictypes.hpp" #include "living.hpp" #include "skills_traits.hpp" #include "race.hpp" #include "spell.hpp" namespace legacy { struct pc_record_type; }; static struct no_party_t {} no_party; // This enum is now also used in the context of giving items enum class eBuyStatus {OK, NO_SPACE, NEED_GOLD, TOO_HEAVY, HAVE_LOTS}; enum ePartyPreset {PARTY_BLANK, PARTY_DEFAULT, PARTY_DEBUG}; enum { GIVE_DO_PRINT = 1, GIVE_ALLOW_OVERLOAD = 2, // These three are mutually exclusive: GIVE_EQUIP_SOFT = 4, GIVE_EQUIP_TRY = 8, GIVE_EQUIP_FORCE = GIVE_EQUIP_SOFT | GIVE_EQUIP_TRY, // Do a dry run to see if the PC can receive it. GIVE_CHECK_ONLY = 16 }; class cParty; class cPlayer; class cTagFile; struct cInvenSlot { unsigned int slot; explicit cInvenSlot(cPlayer& owner) : slot(std::numeric_limits::max()), owner(owner) {} cInvenSlot(cPlayer& owner, int slot) : slot(slot), owner(owner) {} void clear() { slot = std::numeric_limits::max(); } explicit operator bool() const; bool operator !() const; cItem* operator->(); const cItem* operator->() const; cItem& operator*(); const cItem& operator*() const; friend bool operator==(const cInvenSlot& a, const cInvenSlot& b) { return &a.owner == &b.owner && a.slot == b.slot; } private: cPlayer& owner; }; inline bool operator!=(const cInvenSlot& a, const cInvenSlot& b) { return !(a == b); } class cPlayer : public iLiving { cParty* party = nullptr; template cInvenSlot find_item_matching(Fcn fcn); // Allow the party to overwrite the PC's party reference // It only does this (and should ever do this) in remove_pc and replace_pc! // Sadly there is no good way to friend just those two functions. friend class cParty; public: static const int INVENTORY_SIZE = 24; // A nice convenient bitset with just the low 30 bits set, for initializing spells static const uint32_t basic_spells; // This class is shared between the game and the editors, but it should only show help dialogs // when being used in the game, which sets this flag to true on startup. static bool give_help_enabled; eMainStatus main_status; std::string name; // HACK: This is only really marked mutable so that I can use operator[] from const methods mutable std::map skills; unsigned short max_health; short cur_health; unsigned short max_sp; short cur_sp; unsigned short experience; short skill_pts; short level; short exp_adj; // Keep an extra slot for stackable items to go into before combine_things() is called. // This slot is not actually storage space and will always be eItemType::NO_ITEM unless // give_item() is still in progress. std::array items; std::bitset equip; std::bitset<62> priest_spells; std::bitset<62> mage_spells; pic_num_t which_graphic; cInvenSlot weap_poisoned; // HACK: This is only really marked mutable so that I can use operator[] from const methods mutable std::map traits; eRace race; long unique_id; // transient stuff std::map last_cast = {{ eSkill::MAGE_SPELLS, eSpell::NONE}, { eSkill::PRIEST_SPELLS, eSpell::NONE }}; // There is already a global last_spellcast_type, but that variable is for the whole party. // This one is per-PC eSkill last_cast_type = eSkill::INVALID; location combat_pos; short parry = 0; iLiving* last_attacked = nullptr; // Note: Currently this is assigned but never read bool is_alive() const override; bool is_friendly(const iLiving& other) const override; bool is_friendly() const override; bool is_shielded() const override; int get_shared_dmg(int base_dmg) const override; int get_health() const override; int get_magic() const override; int get_level() const override; location get_loc() const override; void finish_create(); void void_sanctuary() override; void heal(int how_much) override; void poison(int how_much) override; void cure(int how_much) override; void acid(int how_much) override; void curse(int how_much) override; void slow(int how_much) override; void web(int how_much) override; void disease(int how_much) override; void dumbfound(int how_much) override; void scare(int how_much) override; void sleep(eStatus type, int how_much, int adj) override; void avatar() override; void drain_sp(int how_much, bool allow_resist) override; void restore_sp(int how_much) override; bool combine_things(bool check_only = false); void sort_items(); // Possible results of give_item are a subset of eBuyStatus, and shop code calls this function, // so reuse the enum eBuyStatus give_item(cItem item, int flags); eBuyStatus can_give_item(cItem item) const; bool equip_item(int which_item, bool do_print); bool unequip_item(int which_item, bool do_print); std::pair get_weapons(); const std::pair get_weapons() const; void take_item(int which_item); void remove_charge(int which_item); const cInvenSlot has_space() const; cInvenSlot has_space(); short max_weight() const; short cur_weight() const; short free_weight() const; // Counts the encumbrance from armor only, excluding cursed effects; used for display short armor_encumbrance() const; // Counts the actual total encumbrance used for combat calculations short total_encumbrance(const std::array& reduce_chance) const; short get_prot_level(eItemAbil abil, short dat = -1) const; const cInvenSlot has_abil_equip(eItemAbil abil, short dat = -1) const; cInvenSlot has_abil_equip(eItemAbil abil, short dat = -1); const cInvenSlot has_abil(eItemAbil abil, short dat = -1) const; cInvenSlot has_abil(eItemAbil abil, short dat = -1); const cInvenSlot has_type_equip(eItemType type) const; cInvenSlot has_type_equip(eItemType type); const cInvenSlot has_type(eItemType type) const; cInvenSlot has_type(eItemType type); const cInvenSlot has_class_equip(unsigned int item_class) const; cInvenSlot has_class_equip(unsigned int item_class); const cInvenSlot has_class(unsigned int item_class, bool require_charges = false) const; cInvenSlot has_class(unsigned int item_class, bool require_charges = false); short skill(eSkill skill) const; short stat_adj(eSkill skill) const; eBuyStatus ok_to_buy(short cost,cItem item) const; void import_legacy(legacy::pc_record_type old); cPlayer(no_party_t); cPlayer(cParty& party); cPlayer(cParty& party,ePartyPreset key,short slot); cPlayer(no_party_t, const cPlayer& other); cPlayer(cParty& party, const cPlayer& other); short get_tnl() const; void writeTo(cTagFile& file) const; void readFrom(const cTagFile& file); virtual ~cPlayer() = default; // Copy-and-swap friend void swap(cPlayer& lhs, cPlayer& rhs); cPlayer(const cPlayer& other) = delete; cPlayer(cPlayer&& other); // For now, not assignable because of an issue of how to handle the unique_id cPlayer& operator=(cPlayer other) = delete; }; #endif