From 5db6507b17ab2a1c90d7b414e19bd6b57b4e2b27 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 10 May 2022 01:08:18 -0700 Subject: [PATCH] fix some dumb bugs in quest menu filters --- src/Lobby.cc | 3 +-- src/Lobby.hh | 3 ++- src/Quest.cc | 43 ++++++++++++++++++++++-------------------- src/Quest.hh | 7 ++++--- src/ReceiveCommands.cc | 12 ++++++------ src/SendCommands.cc | 2 +- 6 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/Lobby.cc b/src/Lobby.cc index d602594e..5bc5ce9e 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -14,8 +14,7 @@ using namespace std; Lobby::Lobby() : lobby_id(0), min_level(0), max_level(0xFFFFFFFF), next_game_item_id(0), version(GameVersion::GC), section_id(0), episode(1), difficulty(0), mode(0), rare_seed(random_object()), event(0), - block(0), type(0), leader_id(0), max_clients(12), flags(0), - loading_quest_id(0) { + block(0), type(0), leader_id(0), max_clients(12), flags(0) { for (size_t x = 0; x < 12; x++) { this->next_item_id[x] = 0; diff --git a/src/Lobby.hh b/src/Lobby.hh index 658ada53..91e6672c 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -14,6 +14,7 @@ #include "Map.hh" #include "RareItemSet.hh" #include "Text.hh" +#include "Quest.hh" struct Lobby { enum Flag { @@ -66,7 +67,7 @@ struct Lobby { uint8_t leader_id; uint8_t max_clients; uint32_t flags; - uint32_t loading_quest_id; // for use with joinable quests + std::shared_ptr loading_quest; std::array, 12> clients; Lobby(); diff --git a/src/Quest.cc b/src/Quest.cc index ff27df42..c591473b 100644 --- a/src/Quest.cc +++ b/src/Quest.cc @@ -141,7 +141,8 @@ struct PSOQuestHeaderBB { Quest::Quest(const string& bin_filename) - : quest_id(-1), + : internal_id(-1), + menu_item_id(0), category(QuestCategory::UNKNOWN), episode(0), is_dcv1(false), @@ -204,7 +205,7 @@ Quest::Quest(const string& bin_filename) } // parse the number out of the first token - this->quest_id = strtoull(tokens[0].c_str() + 1, nullptr, 10); + this->internal_id = strtoull(tokens[0].c_str() + 1, nullptr, 10); // get the category from the second token if needed if (this->category == QuestCategory::UNKNOWN) { @@ -586,6 +587,7 @@ QuestIndex::QuestIndex(const std::string& directory) : directory(directory) { auto filename_set = list_directory(this->directory); vector filenames(filename_set.begin(), filename_set.end()); sort(filenames.begin(), filenames.end()); + uint32_t next_menu_item_id = 1; for (const auto& filename : filenames) { string full_path = this->directory + "/" + filename; @@ -601,12 +603,21 @@ QuestIndex::QuestIndex(const std::string& directory) : directory(directory) { ends_with(filename, ".qst")) { try { shared_ptr q(new Quest(full_path)); - this->version_id_to_quest.emplace(make_pair(q->version, q->quest_id), q); - this->version_name_to_quest.emplace(make_pair(q->version, q->name), q); + q->menu_item_id = next_menu_item_id++; string ascii_name = encode_sjis(q->name); - log(INFO, "Indexed quest %s (%s-%" PRId64 ", %s, episode=%hhu, joinable=%s, dcv1=%s)", - ascii_name.c_str(), name_for_version(q->version), q->quest_id, - name_for_category(q->category), q->episode, + if (!this->version_menu_item_id_to_quest.emplace( + make_pair(q->version, q->menu_item_id), q).second) { + throw logic_error("duplicate quest menu item id"); + } + if (!this->version_name_to_quest.emplace( + make_pair(q->version, q->name), q).second) { + throw runtime_error(string_printf( + "duplicate quest name (%s-%" PRId64 "): %s", + name_for_version(q->version), q->internal_id, ascii_name.c_str())); + } + log(INFO, "Indexed quest %s (%s-%" PRId64 " => %" PRIu32 ", %s, episode=%hhu, joinable=%s, dcv1=%s)", + ascii_name.c_str(), name_for_version(q->version), q->internal_id, + q->menu_item_id, name_for_category(q->category), q->episode, q->joinable ? "true" : "false", q->is_dcv1 ? "true" : "false"); } catch (const exception& e) { log(WARNING, "Failed to parse quest file %s (%s)", filename.c_str(), e.what()); @@ -616,8 +627,8 @@ QuestIndex::QuestIndex(const std::string& directory) : directory(directory) { } shared_ptr QuestIndex::get(GameVersion version, - uint32_t id) const { - return this->version_id_to_quest.at(make_pair(version, id)); + uint32_t menu_item_id) const { + return this->version_menu_item_id_to_quest.at(make_pair(version, menu_item_id)); } shared_ptr QuestIndex::get_gba(const string& name) const { @@ -625,9 +636,9 @@ shared_ptr QuestIndex::get_gba(const string& name) const { } vector> QuestIndex::filter(GameVersion version, - bool is_dcv1, QuestCategory category, int16_t episode) const { - auto it = this->version_id_to_quest.lower_bound(make_pair(version, 0)); - auto end_it = this->version_id_to_quest.upper_bound(make_pair(version, 0xFFFFFFFF)); + bool is_dcv1, QuestCategory category) const { + auto it = this->version_menu_item_id_to_quest.lower_bound(make_pair(version, 0)); + auto end_it = this->version_menu_item_id_to_quest.upper_bound(make_pair(version, 0xFFFFFFFF)); vector> ret; for (; it != end_it; it++) { @@ -635,14 +646,6 @@ vector> QuestIndex::filter(GameVersion version, if ((q->is_dcv1 != is_dcv1) || (q->category != category)) { continue; } - - // Only check episode and solo if the category isn't a mode (that is, ignore - // episode if querying for battle/challenge/solo quests). Also, ignore - // ignore episode if it's < 0 (e.g. for the download quest menu). - if ((episode >= 0) && !category_is_mode(category) && ((q->episode != episode))) { - continue; - } - ret.emplace_back(q); } diff --git a/src/Quest.hh b/src/Quest.hh index 2b91ebea..a812d157 100644 --- a/src/Quest.hh +++ b/src/Quest.hh @@ -47,7 +47,8 @@ public: BIN_DAT_DLQ, QST, }; - int64_t quest_id; + int64_t internal_id; + uint32_t menu_item_id; QuestCategory category; uint8_t episode; // 0 = ep1, 1 = ep2, 2 = ep4, 0xFF = ep3 bool is_dcv1; @@ -81,7 +82,7 @@ public: struct QuestIndex { std::string directory; - std::map, std::shared_ptr> version_id_to_quest; + std::map, std::shared_ptr> version_menu_item_id_to_quest; std::map, std::shared_ptr> version_name_to_quest; std::map>> category_to_quests; @@ -93,5 +94,5 @@ struct QuestIndex { std::shared_ptr get(GameVersion version, uint32_t id) const; std::shared_ptr get_gba(const std::string& name) const; std::vector> filter(GameVersion version, - bool is_dcv1, QuestCategory category, int16_t episode) const; + bool is_dcv1, QuestCategory category) const; }; diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index f1ed845e..3cc92338 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -633,7 +633,8 @@ void process_menu_selection(shared_ptr s, shared_ptr c, case MAIN_MENU_DOWNLOAD_QUESTS: if (c->flags & Client::Flag::EPISODE_3) { shared_ptr l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr; - auto quests = s->quest_index->filter(c->version, false, QuestCategory::EPISODE_3, 0xFF); + auto quests = s->quest_index->filter( + c->version, false, QuestCategory::EPISODE_3); if (quests.empty()) { send_lobby_message_box(c, u"$C6There are no quests\navailable."); } else { @@ -783,8 +784,7 @@ void process_menu_selection(shared_ptr s, shared_ptr c, shared_ptr l = c->lobby_id ? s->find_lobby(c->lobby_id) : nullptr; auto quests = s->quest_index->filter(c->version, c->flags & Client::Flag::DCV1, - static_cast(cmd.item_id & 0xFF), - c->flags & Client::Flag::EPISODE_3 ? 0xFF : (l.get() ? (l->episode - 1) : -1)); + static_cast(cmd.item_id & 0xFF)); if (quests.empty()) { send_lobby_message_box(c, u"$C6There are no quests\navailable in that\ncategory."); break; @@ -834,7 +834,7 @@ void process_menu_selection(shared_ptr s, shared_ptr c, } else { l->flags |= Lobby::Flag::QUEST_IN_PROGRESS; } - l->loading_quest_id = q->quest_id; + l->loading_quest = q; for (size_t x = 0; x < l->max_clients; x++) { if (!l->clients[x]) { continue; @@ -973,9 +973,9 @@ void process_quest_list_request(shared_ptr s, shared_ptr c, menu = &quest_categories_menu; } else if (l->mode == 1) { menu = &quest_battle_menu; - } else if (l->mode == 1) { + } else if (l->mode == 2) { menu = &quest_challenge_menu; - } else if (l->mode == 1) { + } else if (l->mode == 3) { menu = &quest_solo_menu; } else { throw logic_error("no quest menu available for mode"); diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 1ae08327..ff751fdb 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -810,7 +810,7 @@ void send_quest_menu_t( for (const auto& quest : quests) { auto& e = entries.emplace_back(); e.menu_id = menu_id; - e.item_id = quest->quest_id; + e.item_id = quest->menu_item_id; e.name = quest->name; e.short_desc = quest->short_description; add_color_inplace(e.short_desc);