#pragma once #include #include #include #include #include #include "Text.hh" class LevelTable; template struct CharacterStatsT { /* 00 */ U16T atp = 0; /* 02 */ U16T mst = 0; /* 04 */ U16T evp = 0; /* 06 */ U16T hp = 0; /* 08 */ U16T dfp = 0; /* 0A */ U16T ata = 0; /* 0C */ U16T lck = 0; /* 0E */ operator CharacterStatsT() const { CharacterStatsT ret; ret.atp = this->atp; ret.mst = this->mst; ret.evp = this->evp; ret.hp = this->hp; ret.dfp = this->dfp; ret.ata = this->ata; ret.lck = this->lck; return ret; } } __attribute__((packed)); using CharacterStats = CharacterStatsT; using CharacterStatsBE = CharacterStatsT; check_struct_size(CharacterStats, 0x0E); check_struct_size(CharacterStatsBE, 0x0E); template struct PlayerStatsT { /* 00 */ CharacterStatsT char_stats; /* 0E */ U16T esp = 0; /* 10 */ F32T attack_range = 0.0; /* 14 */ F32T knockback_range = 0.0; /* 18 */ U32T level = 0; // Qedit specifies this as tech level when used for enemies /* 1C */ U32T experience = 0; /* 20 */ U32T meseta = 0; // Qedit specifies this as TP when used for enemies /* 24 */ operator PlayerStatsT() const { PlayerStatsT ret; ret.char_stats = this->char_stats; ret.esp = this->esp; ret.attack_range = this->attack_range; ret.knockback_range = this->knockback_range; ret.level = this->level; ret.experience = this->experience; ret.meseta = this->meseta; return ret; } } __attribute__((packed)); using PlayerStats = PlayerStatsT; using PlayerStatsBE = PlayerStatsT; check_struct_size(PlayerStats, 0x24); check_struct_size(PlayerStatsBE, 0x24); template struct LevelStatsDeltaT { /* 00 */ uint8_t atp; /* 01 */ uint8_t mst; /* 02 */ uint8_t evp; /* 03 */ uint8_t hp; /* 04 */ uint8_t dfp; /* 05 */ uint8_t ata; /* 06 */ uint8_t lck; /* 07 */ uint8_t tp; /* 08 */ U32T experience; /* 0C */ void apply(CharacterStats& ps) const { ps.ata += this->ata; ps.atp += this->atp; ps.dfp += this->dfp; ps.evp += this->evp; ps.hp += this->hp; ps.mst += this->mst; ps.lck += this->lck; } } __attribute__((packed)); using LevelStatsDelta = LevelStatsDeltaT; using LevelStatsDeltaBE = LevelStatsDeltaT; check_struct_size(LevelStatsDelta, 0x0C); check_struct_size(LevelStatsDeltaBE, 0x0C); class LevelTable { // This is the base class for all the LevelTable implementations. The public interface here only defines functions // that the server needs to handle requests, but some subclasses implement more functionality. See the comments and // Offsets structures inside the subclasses' constructor implementations for more details on the file formats. public: virtual ~LevelTable() = default; virtual const CharacterStats& base_stats_for_class(uint8_t char_class) const = 0; virtual const PlayerStats& max_stats_for_class(uint8_t char_class) const = 0; virtual const LevelStatsDelta& stats_delta_for_level(uint8_t char_class, uint8_t level) const = 0; void reset_to_base(PlayerStats& stats, uint8_t char_class) const; void advance_to_level(PlayerStats& stats, uint32_t level, uint8_t char_class) const; protected: LevelTable() = default; }; class LevelTableV2 : public LevelTable { // from PlayerTable.prs (PC) public: LevelTableV2(const std::string& data, bool compressed); virtual ~LevelTableV2() = default; virtual const CharacterStats& base_stats_for_class(uint8_t char_class) const; const PlayerStats& level_100_stats_for_class(uint8_t char_class) const; virtual const PlayerStats& max_stats_for_class(uint8_t char_class) const; virtual const LevelStatsDelta& stats_delta_for_level(uint8_t char_class, uint8_t level) const; private: std::array base_stats; std::array level_100_stats; std::array max_stats; std::array, 9> level_deltas; }; class LevelTableV3BE : public LevelTable { // from PlyLevelTbl.cpt (GC) public: LevelTableV3BE(const std::string& data, bool encrypted); virtual ~LevelTableV3BE() = default; virtual const CharacterStats& base_stats_for_class(uint8_t char_class) const; virtual const PlayerStats& max_stats_for_class(uint8_t char_class) const; virtual const LevelStatsDelta& stats_delta_for_level(uint8_t char_class, uint8_t level) const; private: std::array, 12> level_deltas; }; class LevelTableV4 : public LevelTable { // from PlyLevelTbl.prs (BB) public: LevelTableV4(const std::string& data, bool compressed); virtual ~LevelTableV4() = default; virtual const CharacterStats& base_stats_for_class(uint8_t char_class) const; virtual const PlayerStats& max_stats_for_class(uint8_t char_class) const; virtual const LevelStatsDelta& stats_delta_for_level(uint8_t char_class, uint8_t level) const; private: std::array base_stats; std::array, 12> level_deltas; };