add support for v1 rare item tables

This commit is contained in:
Martin Michelsen
2023-11-13 16:18:20 -08:00
parent 08fbbd50ad
commit 33a6e307e9
9 changed files with 5931 additions and 18 deletions
+5 -2
View File
@@ -61,10 +61,13 @@ void Lobby::create_item_creator() {
} else if (this->base_version == GameVersion::GC || this->base_version == GameVersion::XB) { } else if (this->base_version == GameVersion::GC || this->base_version == GameVersion::XB) {
common_item_set = s->common_item_set_v3; common_item_set = s->common_item_set_v3;
rare_item_set = s->rare_item_sets.at("rare-table-v3"); rare_item_set = s->rare_item_sets.at("rare-table-v3");
} else { } else if (!this->check_flag(Lobby::Flag::USE_DCV1_RARE_TABLE)) {
// TODO: Should there be separate tables for V1 eventually?
common_item_set = s->common_item_set_v2; common_item_set = s->common_item_set_v2;
rare_item_set = s->rare_item_sets.at("rare-table-v2"); rare_item_set = s->rare_item_sets.at("rare-table-v2");
} else {
// TODO: We should probably have a v1 common item set at some point too
common_item_set = s->common_item_set_v2;
rare_item_set = s->rare_item_sets.at("rare-table-v1");
} }
this->item_creator.reset(new ItemCreator( this->item_creator.reset(new ItemCreator(
common_item_set, common_item_set,
+1
View File
@@ -42,6 +42,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
CANNOT_CHANGE_DROPS_ENABLED = 0x00040000, CANNOT_CHANGE_DROPS_ENABLED = 0x00040000,
CANNOT_CHANGE_ITEM_TABLE = 0x00080000, CANNOT_CHANGE_ITEM_TABLE = 0x00080000,
CANNOT_CHANGE_CHEAT_MODE = 0x00100000, CANNOT_CHANGE_CHEAT_MODE = 0x00100000,
USE_DCV1_RARE_TABLE = 0x00200000,
// Flags used only for lobbies // Flags used only for lobbies
PUBLIC = 0x01000000, PUBLIC = 0x01000000,
+1 -1
View File
@@ -1551,7 +1551,7 @@ int main(int argc, char** argv) {
} else if (ends_with(input_filename, ".gslb")) { } else if (ends_with(input_filename, ".gslb")) {
rs.reset(new RareItemSet(GSLArchive(data, true), true)); rs.reset(new RareItemSet(GSLArchive(data, true), true));
} else if (ends_with(input_filename, ".afs")) { } else if (ends_with(input_filename, ".afs")) {
rs.reset(new RareItemSet(AFSArchive(data))); rs.reset(new RareItemSet(AFSArchive(data), (cli_quest_version == QuestScriptVersion::DC_V1)));
} else if (ends_with(input_filename, ".rel")) { } else if (ends_with(input_filename, ".rel")) {
rs.reset(new RareItemSet(*data, true)); rs.reset(new RareItemSet(*data, true));
} else { } else {
+9 -9
View File
@@ -86,14 +86,14 @@ RareItemSet::ExpandedDrop RareItemSet::ParsedRELData::PackedDrop::expand() const
} }
template <bool IsBigEndian> template <bool IsBigEndian>
void RareItemSet::ParsedRELData::parse_t(StringReader r) { void RareItemSet::ParsedRELData::parse_t(StringReader r, bool is_v1) {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type; using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
uint32_t root_offset = r.pget<U32T>(r.size() - 0x10); uint32_t root_offset = r.pget<U32T>(r.size() - 0x10);
const auto& root = r.pget<Offsets<IsBigEndian>>(root_offset); const auto& root = r.pget<Offsets<IsBigEndian>>(root_offset);
StringReader monsters_r = r.sub(root.monster_rares_offset); StringReader monsters_r = r.sub(root.monster_rares_offset);
for (size_t z = 0; z < 0x65; z++) { for (size_t z = 0; z < (is_v1 ? 0x33 : 0x65); z++) {
const auto& d = monsters_r.get<PackedDrop>(); const auto& d = monsters_r.get<PackedDrop>();
this->monster_rares.emplace_back(d.expand()); this->monster_rares.emplace_back(d.expand());
} }
@@ -163,11 +163,11 @@ std::string RareItemSet::ParsedRELData::serialize_t() const {
return std::move(w.str()); return std::move(w.str());
} }
RareItemSet::ParsedRELData::ParsedRELData(StringReader r, bool big_endian) { RareItemSet::ParsedRELData::ParsedRELData(StringReader r, bool big_endian, bool is_v1) {
if (big_endian) { if (big_endian) {
this->parse_t<true>(r); this->parse_t<true>(r, is_v1);
} else { } else {
this->parse_t<false>(r); this->parse_t<false>(r, is_v1);
} }
} }
@@ -229,14 +229,14 @@ RareItemSet::SpecCollection RareItemSet::ParsedRELData::as_collection() const {
return ret; return ret;
} }
RareItemSet::RareItemSet(const AFSArchive& afs) { RareItemSet::RareItemSet(const AFSArchive& afs, bool is_v1) {
const array<GameMode, 4> modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO}; const array<GameMode, 4> modes = {GameMode::NORMAL, GameMode::BATTLE, GameMode::CHALLENGE, GameMode::SOLO};
for (GameMode mode : modes) { for (GameMode mode : modes) {
for (size_t difficulty = 0; difficulty < 4; difficulty++) { for (size_t difficulty = 0; difficulty < 4; difficulty++) {
for (size_t section_id = 0; section_id < 10; section_id++) { for (size_t section_id = 0; section_id < 10; section_id++) {
try { try {
size_t index = difficulty * 10 + section_id; size_t index = difficulty * 10 + section_id;
ParsedRELData rel(afs.get_reader(index), false); ParsedRELData rel(afs.get_reader(index), false, is_v1);
this->collections.emplace( this->collections.emplace(
this->key_for_params(mode, Episode::EP1, difficulty, section_id), this->key_for_params(mode, Episode::EP1, difficulty, section_id),
rel.as_collection()); rel.as_collection());
@@ -264,7 +264,7 @@ RareItemSet::RareItemSet(const GSLArchive& gsl, bool is_big_endian) {
for (size_t section_id = 0; section_id < 10; section_id++) { for (size_t section_id = 0; section_id < 10; section_id++) {
try { try {
string filename = this->gsl_entry_name_for_table(mode, episode, difficulty, section_id); string filename = this->gsl_entry_name_for_table(mode, episode, difficulty, section_id);
ParsedRELData rel(gsl.get_reader(filename), is_big_endian); ParsedRELData rel(gsl.get_reader(filename), is_big_endian, false);
this->collections.emplace( this->collections.emplace(
this->key_for_params(mode, episode, difficulty, section_id), this->key_for_params(mode, episode, difficulty, section_id),
rel.as_collection()); rel.as_collection());
@@ -285,7 +285,7 @@ RareItemSet::RareItemSet(const string& rel_data, bool is_big_endian) {
for (size_t section_id = 0; section_id < 10; section_id++) { for (size_t section_id = 0; section_id < 10; section_id++) {
try { try {
size_t index = (ep_index * 40) + difficulty * 10 + section_id; size_t index = (ep_index * 40) + difficulty * 10 + section_id;
ParsedRELData rel(r.sub(0x280 * index, 0x280), is_big_endian); ParsedRELData rel(r.sub(0x280 * index, 0x280), is_big_endian, false);
this->collections.emplace( this->collections.emplace(
this->key_for_params(GameMode::NORMAL, episodes[ep_index], difficulty, section_id), this->key_for_params(GameMode::NORMAL, episodes[ep_index], difficulty, section_id),
rel.as_collection()); rel.as_collection());
+4 -4
View File
@@ -26,7 +26,7 @@ public:
}; };
RareItemSet(); RareItemSet();
RareItemSet(const AFSArchive& afs); RareItemSet(const AFSArchive& afs, bool is_v1);
RareItemSet(const GSLArchive& gsl, bool is_big_endian); RareItemSet(const GSLArchive& gsl, bool is_big_endian);
RareItemSet(const std::string& rel, bool is_big_endian); RareItemSet(const std::string& rel, bool is_big_endian);
RareItemSet(const JSON& json, GameVersion version, std::shared_ptr<const ItemNameIndex> name_index = nullptr); RareItemSet(const JSON& json, GameVersion version, std::shared_ptr<const ItemNameIndex> name_index = nullptr);
@@ -68,7 +68,7 @@ protected:
template <bool IsBigEndian> template <bool IsBigEndian>
struct Offsets { struct Offsets {
using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type; using U32T = typename std::conditional<IsBigEndian, be_uint32_t, le_uint32_t>::type;
/* 00 */ U32T monster_rares_offset; // -> parray<PackedDrop, 0x65> /* 00 */ U32T monster_rares_offset; // -> parray<PackedDrop, 0x65> (or 0x33 on v1)
/* 04 */ U32T box_count; // Usually 30 (0x1E) /* 04 */ U32T box_count; // Usually 30 (0x1E)
/* 08 */ U32T box_areas_offset; // -> parray<uint8_t, 0x1E> /* 08 */ U32T box_areas_offset; // -> parray<uint8_t, 0x1E>
/* 0C */ U32T box_rares_offset; // -> parray<PackedDrop, 0x1E> /* 0C */ U32T box_rares_offset; // -> parray<PackedDrop, 0x1E>
@@ -84,12 +84,12 @@ protected:
std::vector<BoxRare> box_rares; std::vector<BoxRare> box_rares;
ParsedRELData() = default; ParsedRELData() = default;
ParsedRELData(StringReader r, bool big_endian); ParsedRELData(StringReader r, bool big_endian, bool is_v1);
explicit ParsedRELData(const SpecCollection& collection); explicit ParsedRELData(const SpecCollection& collection);
std::string serialize(bool big_endian) const; std::string serialize(bool big_endian) const;
template <bool IsBigEndian> template <bool IsBigEndian>
void parse_t(StringReader r); void parse_t(StringReader r, bool is_v1);
template <bool IsBigEndian> template <bool IsBigEndian>
std::string serialize_t() const; std::string serialize_t() const;
+3
View File
@@ -3589,6 +3589,9 @@ shared_ptr<Lobby> create_game_generic(
shared_ptr<Lobby> game = s->create_lobby(); shared_ptr<Lobby> game = s->create_lobby();
game->name = name; game->name = name;
game->set_flag(Lobby::Flag::GAME); game->set_flag(Lobby::Flag::GAME);
if (c->config.check_flag(Client::Flag::IS_DC_V1)) {
game->set_flag(Lobby::Flag::USE_DCV1_RARE_TABLE);
}
if ((c->version() == GameVersion::GC) && if ((c->version() == GameVersion::GC) &&
c->config.check_flag(Client::Flag::IS_EPISODE_3) && c->config.check_flag(Client::Flag::IS_EPISODE_3) &&
c->config.check_flag(Client::Flag::IS_EP3_TRIAL_EDITION)) { c->config.check_flag(Client::Flag::IS_EP3_TRIAL_EDITION)) {
+1 -1
View File
@@ -928,7 +928,7 @@ void ServerState::load_item_tables() {
} else if (ends_with(filename, ".afs")) { } else if (ends_with(filename, ".afs")) {
config_log.info("Loading AFS rare item table %s", filename.c_str()); config_log.info("Loading AFS rare item table %s", filename.c_str());
shared_ptr<string> data(new string(load_file(path))); shared_ptr<string> data(new string(load_file(path)));
this->rare_item_sets.emplace(basename, new RareItemSet(AFSArchive(data))); this->rare_item_sets.emplace(basename, new RareItemSet(AFSArchive(data), false));
} else if (ends_with(filename, ".gsl")) { } else if (ends_with(filename, ".gsl")) {
config_log.info("Loading GSL rare item table %s", filename.c_str()); config_log.info("Loading GSL rare item table %s", filename.c_str());
+5906
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
// Rare table for PSO DC and PC. // Rare table for PSO DCv2 and PC.
// See rare-table-v4.json for a description of how this file works. // See rare-table-v4.json for a description of how this file works.
// This file is only used when client rare tables are overridden. By default, // This file is only used when client rare tables are overridden. By default,
// the client controls rare drops and this table is ignored. // the client controls rare drops and this table is ignored.