fix some dumb bugs in quest menu filters

This commit is contained in:
Martin Michelsen
2022-05-10 01:08:18 -07:00
parent a11b9f5b3e
commit 5db6507b17
6 changed files with 37 additions and 33 deletions
+1 -2
View File
@@ -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<uint32_t>()), 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;
+2 -1
View File
@@ -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<const Quest> loading_quest;
std::array<std::shared_ptr<Client>, 12> clients;
Lobby();
+23 -20
View File
@@ -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<string> 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<Quest> 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<const Quest> 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<const string> QuestIndex::get_gba(const string& name) const {
@@ -625,9 +636,9 @@ shared_ptr<const string> QuestIndex::get_gba(const string& name) const {
}
vector<shared_ptr<const Quest>> 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<shared_ptr<const Quest>> ret;
for (; it != end_it; it++) {
@@ -635,14 +646,6 @@ vector<shared_ptr<const Quest>> 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);
}
+4 -3
View File
@@ -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::pair<GameVersion, uint64_t>, std::shared_ptr<Quest>> version_id_to_quest;
std::map<std::pair<GameVersion, uint64_t>, std::shared_ptr<Quest>> version_menu_item_id_to_quest;
std::map<std::pair<GameVersion, std::u16string>, std::shared_ptr<Quest>> version_name_to_quest;
std::map<std::string, std::vector<std::shared_ptr<Quest>>> category_to_quests;
@@ -93,5 +94,5 @@ struct QuestIndex {
std::shared_ptr<const Quest> get(GameVersion version, uint32_t id) const;
std::shared_ptr<const std::string> get_gba(const std::string& name) const;
std::vector<std::shared_ptr<const Quest>> filter(GameVersion version,
bool is_dcv1, QuestCategory category, int16_t episode) const;
bool is_dcv1, QuestCategory category) const;
};
+6 -6
View File
@@ -633,7 +633,8 @@ void process_menu_selection(shared_ptr<ServerState> s, shared_ptr<Client> c,
case MAIN_MENU_DOWNLOAD_QUESTS:
if (c->flags & Client::Flag::EPISODE_3) {
shared_ptr<Lobby> 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<ServerState> s, shared_ptr<Client> c,
shared_ptr<Lobby> 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<QuestCategory>(cmd.item_id & 0xFF),
c->flags & Client::Flag::EPISODE_3 ? 0xFF : (l.get() ? (l->episode - 1) : -1));
static_cast<QuestCategory>(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<ServerState> s, shared_ptr<Client> 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<ServerState> s, shared_ptr<Client> 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");
+1 -1
View File
@@ -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);