Files
oboe/src/universe/pc.hpp

211 lines
7.1 KiB
C++

/*
* pc.h
* BoE
*
* Created by Celtic Minstrel on 24/04/09.
*
*/
#ifndef BOE_DATA_PC_H
#define BOE_DATA_PC_H
#include <string>
#include <map>
#include <iosfwd>
#include <array>
#include <bitset>
#include <cstdint>
#include <limits>
#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<unsigned int>::max()), owner(owner) {}
cInvenSlot(cPlayer& owner, int slot) : slot(slot), owner(owner) {}
void clear() {
slot = std::numeric_limits<unsigned int>::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<typename Fcn>
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<eSkill, short> 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<cItem,INVENTORY_SIZE+1> items;
std::bitset<INVENTORY_SIZE> 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<eTrait,bool> traits;
eRace race;
long unique_id;
// transient stuff
std::map<eSkill,eSpell> 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<cInvenSlot, cInvenSlot> get_weapons();
const std::pair<cInvenSlot, cInvenSlot> 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<short, 51>& 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