#pragma once #include #include #include #include #include "GSLArchive.hh" #include "StaticGameData.hh" class RareItemSet { public: struct PackedDrop { uint8_t probability; uint8_t item_code[3]; static uint32_t expand_rate(uint8_t pc); } __attribute__((packed)); struct ExpandedDrop { uint32_t probability; uint8_t item_code[3]; ExpandedDrop(); explicit ExpandedDrop(const PackedDrop&); }; struct Table { // 0x280 in size; describes one difficulty, section ID, and episode // TODO: It looks like this structure can actually vary. In PSOGC, these all // appear to be the same size/format, but that's probably not strictly // required to be the case. /* 0000 */ parray monster_rares; /* 0194 */ parray box_areas; /* 01B2 */ parray box_rares; /* 022A */ parray unknown_a1; /* 022C */ be_uint32_t monster_rares_offset; // == 0x0000 /* 0230 */ be_uint32_t box_count; // == 0x1E /* 0234 */ be_uint32_t box_areas_offset; // == 0x0194 /* 0238 */ be_uint32_t box_rares_offset; // == 0x01B2 /* 023C */ be_uint32_t unused_offset1; /* 0240 */ parray unknown_a2; /* 0260 */ be_uint32_t unknown_a2_offset; /* 0264 */ be_uint32_t unknown_a2_count; /* 0268 */ be_uint32_t unknown_a3; /* 026C */ be_uint32_t unknown_a4; /* 0270 */ be_uint32_t offset_table_offset; // == 0x022C /* 0274 */ parray unknown_a5; /* 0280 */ std::vector get_enemy_specs(uint8_t rt_index) const; std::vector get_box_specs(uint8_t area) const; } __attribute__((packed)); virtual ~RareItemSet() = default; virtual std::vector get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const = 0; virtual std::vector get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const = 0; protected: RareItemSet() = default; static uint16_t key_for_params(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid); }; class GSLRareItemSet : public RareItemSet { public: GSLRareItemSet(std::shared_ptr data, bool is_big_endian); virtual ~GSLRareItemSet() = default; virtual std::vector get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const; virtual std::vector get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const; private: std::unordered_map tables; GSLArchive gsl; }; class RELRareItemSet : public RareItemSet { public: RELRareItemSet(std::shared_ptr data); virtual ~RELRareItemSet() = default; virtual std::vector get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const; virtual std::vector get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const; private: std::shared_ptr data; const Table& get_table(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid) const; }; class JSONRareItemSet : public RareItemSet { public: JSONRareItemSet(std::shared_ptr json); virtual ~JSONRareItemSet() = default; virtual std::vector get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const; virtual std::vector get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const; private: struct SpecCollection { std::vector> rt_index_to_specs; std::vector> box_area_to_specs; }; std::unordered_map collections; };