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) {
common_item_set = s->common_item_set_v3;
rare_item_set = s->rare_item_sets.at("rare-table-v3");
} else {
// TODO: Should there be separate tables for V1 eventually?
} else if (!this->check_flag(Lobby::Flag::USE_DCV1_RARE_TABLE)) {
common_item_set = s->common_item_set_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(
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_ITEM_TABLE = 0x00080000,
CANNOT_CHANGE_CHEAT_MODE = 0x00100000,
USE_DCV1_RARE_TABLE = 0x00200000,
// Flags used only for lobbies
PUBLIC = 0x01000000,
+1 -1
View File
@@ -1551,7 +1551,7 @@ int main(int argc, char** argv) {
} else if (ends_with(input_filename, ".gslb")) {
rs.reset(new RareItemSet(GSLArchive(data, true), true));
} 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")) {
rs.reset(new RareItemSet(*data, true));
} else {
+9 -9
View File
@@ -86,14 +86,14 @@ RareItemSet::ExpandedDrop RareItemSet::ParsedRELData::PackedDrop::expand() const
}
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;
uint32_t root_offset = r.pget<U32T>(r.size() - 0x10);
const auto& root = r.pget<Offsets<IsBigEndian>>(root_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>();
this->monster_rares.emplace_back(d.expand());
}
@@ -163,11 +163,11 @@ std::string RareItemSet::ParsedRELData::serialize_t() const {
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) {
this->parse_t<true>(r);
this->parse_t<true>(r, is_v1);
} 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;
}
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};
for (GameMode mode : modes) {
for (size_t difficulty = 0; difficulty < 4; difficulty++) {
for (size_t section_id = 0; section_id < 10; section_id++) {
try {
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->key_for_params(mode, Episode::EP1, difficulty, section_id),
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++) {
try {
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->key_for_params(mode, episode, difficulty, section_id),
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++) {
try {
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->key_for_params(GameMode::NORMAL, episodes[ep_index], difficulty, section_id),
rel.as_collection());
+4 -4
View File
@@ -26,7 +26,7 @@ public:
};
RareItemSet();
RareItemSet(const AFSArchive& afs);
RareItemSet(const AFSArchive& afs, bool is_v1);
RareItemSet(const GSLArchive& gsl, 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);
@@ -68,7 +68,7 @@ protected:
template <bool IsBigEndian>
struct Offsets {
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)
/* 08 */ U32T box_areas_offset; // -> parray<uint8_t, 0x1E>
/* 0C */ U32T box_rares_offset; // -> parray<PackedDrop, 0x1E>
@@ -84,12 +84,12 @@ protected:
std::vector<BoxRare> box_rares;
ParsedRELData() = default;
ParsedRELData(StringReader r, bool big_endian);
ParsedRELData(StringReader r, bool big_endian, bool is_v1);
explicit ParsedRELData(const SpecCollection& collection);
std::string serialize(bool big_endian) const;
template <bool IsBigEndian>
void parse_t(StringReader r);
void parse_t(StringReader r, bool is_v1);
template <bool IsBigEndian>
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();
game->name = name;
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) &&
c->config.check_flag(Client::Flag::IS_EPISODE_3) &&
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")) {
config_log.info("Loading AFS rare item table %s", filename.c_str());
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")) {
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.
// This file is only used when client rare tables are overridden. By default,
// the client controls rare drops and this table is ignored.