#pragma once #include #include #include #include #include #include "QuestScript.hh" #include "StaticGameData.hh" struct QuestCategoryIndex { struct Category { enum Flag { NORMAL = 0x01, BATTLE = 0x02, CHALLENGE = 0x04, SOLO = 0x08, GOVERNMENT = 0x10, DOWNLOAD = 0x20, EP3_DOWNLOAD = 0x40, HIDE_ON_PRE_V3 = 0x80, }; uint32_t category_id; uint8_t flags; char type; std::string short_token; std::u16string name; std::u16string description; explicit Category(uint32_t category_id, const JSON& json); bool matches_flags(uint8_t request) const; }; std::vector categories; explicit QuestCategoryIndex(const JSON& json); const Category& find(char type, const std::string& short_token) const; const Category& at(uint32_t category_id) const; }; class Quest { public: struct DATSectionHeader { le_uint32_t type; // 1 = objects, 2 = enemies. There are other types too le_uint32_t section_size; // Includes this header le_uint32_t area; le_uint32_t data_size; } __attribute__((packed)); enum class FileFormat { BIN_DAT = 0, BIN_DAT_UNCOMPRESSED, BIN_DAT_GCI, BIN_DAT_VMS, BIN_DAT_DLQ, QST, }; int64_t internal_id; uint32_t menu_item_id; uint32_t category_id; Episode episode; bool joinable; QuestScriptVersion version; std::string file_basename; // we append -. when reading FileFormat file_format; bool has_mnm_extension; bool is_dlq_encoded; std::u16string name; std::u16string short_description; std::u16string long_description; Quest(const std::string& file_basename, QuestScriptVersion version, std::shared_ptr category_index); Quest(const Quest&) = default; Quest(Quest&&) = default; Quest& operator=(const Quest&) = default; Quest& operator=(Quest&&) = default; std::string bin_filename() const; std::string dat_filename() const; std::shared_ptr bin_contents() const; std::shared_ptr dat_contents() const; static std::string encode_download_quest_file( const std::string& compressed_data, size_t decompressed_size = 0, uint32_t encryption_seed = 0); std::shared_ptr create_download_quest() const; static std::string decode_gci_file( const std::string& filename, ssize_t find_seed_num_threads = -1, int64_t known_seed = -1); static std::string decode_vms_file( const std::string& filename, ssize_t find_seed_num_threads = -1, int64_t known_seed = -1); static std::string decode_dlq_file(const std::string& filename); static std::string decode_dlq_data(const std::string& filename); static std::pair decode_qst_file(const std::string& filename); static std::string encode_qst( const std::string& bin_data, const std::string& dat_data, const std::u16string& name, const std::string& file_basename, QuestScriptVersion version, bool is_dlq_encoded); std::string encode_qst() const; private: // these are populated when requested mutable std::shared_ptr bin_contents_ptr; mutable std::shared_ptr dat_contents_ptr; }; struct QuestIndex { std::string directory; std::shared_ptr category_index; std::map, std::shared_ptr> version_menu_item_id_to_quest; std::map>> category_to_quests; std::map> gba_file_contents; QuestIndex(const std::string& directory, std::shared_ptr category_index); std::shared_ptr get(QuestScriptVersion version, uint32_t id) const; std::shared_ptr get_gba(const std::string& name) const; std::vector> filter( QuestScriptVersion version, uint32_t category_id) const; };