#pragma once #include #include #include #include #include #include #include "AFSArchive.hh" #include "CommonItemSet.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, Difficulty difficulty, uint8_t secid, uint8_t rt_index) const; std::vector get_box_specs( GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid, uint8_t area_norm) const; bool has_entries_for_game_config(GameMode mode, Episode episode, Difficulty difficulty) const; std::string serialize_afs(bool is_v1) const; std::string serialize_gsl(bool big_endian) const; std::string serialize_html( GameMode mode, Episode episode, Difficulty difficulty, std::shared_ptr name_index = nullptr, std::shared_ptr common_item_set = nullptr) 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, Difficulty 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_norm_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 */ } __attribute__((packed)); using Offsets = OffsetsT; using OffsetsBE = OffsetsT; check_struct_size(Offsets, 0x10); check_struct_size(OffsetsBE, 0x10); struct BoxRare { uint8_t area_norm_plus_1; 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, Difficulty difficulty, uint8_t secid) const; static std::string gsl_entry_name_for_table(GameMode mode, Episode episode, Difficulty difficulty, uint8_t section_id); static uint16_t key_for_params(GameMode mode, Episode episode, Difficulty difficulty, uint8_t secid); static uint32_t expand_rate(uint8_t pc); static uint8_t compress_rate(uint32_t probability); };