add support for v1 rare item tables
This commit is contained in:
+5
-2
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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());
|
||||
|
||||
Executable
+5906
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user