fix some dumb bugs in quest menu filters
This commit is contained in:
+1
-2
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user