#pragma once #include #include #include #include #include #include #include "AFSArchive.hh" #include "GSLArchive.hh" #include "ItemNameIndex.hh" #include "StaticGameData.hh" #include "Text.hh" #include "Version.hh" class RareItemSet { public: struct ExpandedDrop { uint32_t probability = 0; ItemData data; std::string str() const; std::string str(std::shared_ptr name_index) const; }; RareItemSet(); RareItemSet(const AFSArchive& afs, bool is_v1); RareItemSet(const GSLArchive& gsl, bool is_big_endian); RareItemSet(const std::string& rel, bool is_big_endian); RareItemSet(const phosg::JSON& json, std::shared_ptr name_index = nullptr); ~RareItemSet() = default; std::vector get_enemy_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t rt_index) const; std::vector get_box_specs(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid, uint8_t area) const; std::string serialize_afs(bool is_v1) const; std::string serialize_gsl(bool big_endian) const; phosg::JSON json(std::shared_ptr name_index = nullptr) const; void multiply_all_rates(double factor); void print_collection( FILE* stream, GameMode mode, Episode episode, uint8_t difficulty, uint8_t section_id, std::shared_ptr name_index = nullptr) const; void print_all_collections(FILE* stream, std::shared_ptr name_index = nullptr) const; protected: struct SpecCollection { std::vector> rt_index_to_specs; std::vector> box_area_to_specs; }; struct ParsedRELData { struct PackedDrop { uint8_t probability = 0; parray item_code; PackedDrop() = default; explicit PackedDrop(const ExpandedDrop&); ExpandedDrop expand() const; } __packed_ws__(PackedDrop, 4); template struct OffsetsT { /* 00 */ U32T monster_rares_offset; // -> parray (or 0x33 on v1) /* 04 */ U32T box_count; // Usually 30 (0x1E) /* 08 */ U32T box_areas_offset; // -> parray /* 0C */ U32T box_rares_offset; // -> parray /* 10 */ } __packed__; using Offsets = OffsetsT; using OffsetsBE = OffsetsT; check_struct_size(Offsets, 0x10); check_struct_size(OffsetsBE, 0x10); struct BoxRare { uint8_t area; ExpandedDrop drop; }; std::vector monster_rares; std::vector box_rares; ParsedRELData() = default; ParsedRELData(phosg::StringReader r, bool big_endian, bool is_v1); explicit ParsedRELData(const SpecCollection& collection); std::string serialize(bool big_endian, bool is_v1) const; template void parse_t(phosg::StringReader r, bool is_v1); template std::string serialize_t(bool is_v1) const; SpecCollection as_collection() const; }; std::unordered_map collections; const SpecCollection& get_collection(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid) const; static std::string gsl_entry_name_for_table(GameMode mode, Episode episode, uint8_t difficulty, uint8_t section_id); static uint16_t key_for_params(GameMode mode, Episode episode, uint8_t difficulty, uint8_t secid); static uint32_t expand_rate(uint8_t pc); static uint8_t compress_rate(uint32_t probability); };