merge upstream master 20260611
Feature/merge upstream master 20260611
This commit is contained in:
+3
-1
@@ -99,7 +99,7 @@ set(SOURCES
|
||||
src/LevelTable.cc
|
||||
src/Lobby.cc
|
||||
src/Loggers.cc
|
||||
src/MagEvolutionTable.cc
|
||||
src/MagMetadataTable.cc
|
||||
src/Main.cc
|
||||
src/Map.cc
|
||||
src/Menu.cc
|
||||
@@ -126,9 +126,11 @@ set(SOURCES
|
||||
src/ServerShell.cc
|
||||
src/ServerState.cc
|
||||
src/ShellCommands.cc
|
||||
src/ShopRandomSets.cc
|
||||
src/SignalWatcher.cc
|
||||
src/StaticGameData.cc
|
||||
src/TeamIndex.cc
|
||||
src/TekkerAdjustmentSet.cc
|
||||
src/Text.cc
|
||||
src/TextIndex.cc
|
||||
src/Version.cc
|
||||
|
||||
@@ -1130,3 +1130,7 @@ Rappy size modifier
|
||||
|
||||
Disable HP reduction warning sound in Challenge mode
|
||||
3OE1 => 04076A28 4E800020
|
||||
|
||||
Mag invincibility effect sparkliness modifier
|
||||
(Default 003C; smaller values are more sparkly)
|
||||
3OE1 => 801131C4 3860XXXX
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <future>
|
||||
#include <phosg/Filesystem.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <resource_file/Emulators/PPC32Emulator.hh>
|
||||
#include <resource_file/Emulators/X86Emulator.hh>
|
||||
#include <resource_file/ExecutableFormats/DOLFile.hh>
|
||||
#include <resource_file/ExecutableFormats/PEFile.hh>
|
||||
@@ -973,6 +974,197 @@ std::vector<DiffEntry> diff_dol_files(const std::string& a_filename, const std::
|
||||
return ret;
|
||||
}
|
||||
|
||||
void diff_dol_files_semantic(
|
||||
FILE* stream,
|
||||
const std::string& a_filename,
|
||||
const std::string& b_filename,
|
||||
const std::unordered_set<uint32_t>& a_ignore_functions,
|
||||
const std::unordered_set<uint32_t>& b_ignore_functions) {
|
||||
ResourceDASM::DOLFile a(a_filename.c_str());
|
||||
ResourceDASM::DOLFile b(b_filename.c_str());
|
||||
|
||||
// There must be the same number of sections
|
||||
if (a.sections.size() != b.sections.size()) {
|
||||
throw std::runtime_error("DOL files do not have the same section count");
|
||||
}
|
||||
|
||||
for (size_t section_index = 0; section_index < a.sections.size(); section_index++) {
|
||||
const auto& a_sec = a.sections[section_index];
|
||||
const auto& b_sec = b.sections[section_index];
|
||||
|
||||
if (!a_sec.is_text || !b_sec.is_text) {
|
||||
phosg::fwrite_fmt(stderr, "SECTION {} DATA\n", section_index);
|
||||
// TODO: Diff the contents as binary data
|
||||
|
||||
} else {
|
||||
phosg::fwrite_fmt(stderr, "SECTION {} TEXT\n", section_index);
|
||||
|
||||
struct FileAnalysis {
|
||||
struct Function {
|
||||
const ResourceDASM::EmulatorBase::DisassembleResult::Label* label;
|
||||
size_t size;
|
||||
std::vector<std::pair<uint32_t, uint32_t>> code; // [(opcode, mask)]
|
||||
};
|
||||
std::vector<Function> functions;
|
||||
ResourceDASM::EmulatorBase::DisassembleResult dasm;
|
||||
};
|
||||
|
||||
auto disassemble_section = [&](const ResourceDASM::DOLFile& file, const ResourceDASM::DOLFile::Section& sec) -> FileAnalysis {
|
||||
std::multimap<uint32_t, std::string> labels;
|
||||
if ((file.entrypoint >= sec.address) && (file.entrypoint < (sec.address + sec.data.size()))) {
|
||||
labels.emplace(file.entrypoint, "entry");
|
||||
}
|
||||
FileAnalysis ret;
|
||||
ret.dasm = ResourceDASM::PPC32Emulator::disassemble_structured(
|
||||
sec.data.data(), sec.data.size(), sec.address, &labels);
|
||||
|
||||
FileAnalysis::Function* prev_fn = nullptr;
|
||||
for (const auto& [addr, label] : ret.dasm.labels) {
|
||||
if (label.refs.call_addrs.empty() ||
|
||||
(label.address < sec.address) ||
|
||||
(label.address >= (sec.address + sec.data.size()))) {
|
||||
continue;
|
||||
}
|
||||
if (prev_fn) {
|
||||
prev_fn->size = addr - prev_fn->label->address;
|
||||
}
|
||||
auto& fn = ret.functions.emplace_back();
|
||||
fn.label = &label;
|
||||
prev_fn = &fn;
|
||||
}
|
||||
if (prev_fn) {
|
||||
prev_fn->size = sec.data.size() - (prev_fn->label->address - sec.address);
|
||||
}
|
||||
|
||||
for (auto& fn : ret.functions) {
|
||||
const be_uint32_t* code = reinterpret_cast<const be_uint32_t*>(
|
||||
sec.data.data() + (fn.label->address - sec.address));
|
||||
for (size_t z = 0; z < fn.size >> 2; z++) {
|
||||
uint32_t opcode = code[z];
|
||||
if ((opcode & 0xFC000000) == 0x34000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // subic.
|
||||
} else if ((opcode & 0xFC000000) == 0x38000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // addi
|
||||
} else if ((opcode & 0xFC1F0000) == 0x3C000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lis
|
||||
} else if ((opcode & 0xFC000000) == 0x48000000) {
|
||||
fn.code.emplace_back(opcode, 0xFC000000); // b[la]
|
||||
} else if ((opcode & 0xF8000000) == 0x60000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // ori
|
||||
} else if ((opcode & 0xF8000000) == 0x80000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lwz, lwzu
|
||||
} else if ((opcode & 0xFC000000) == 0x88000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lbz
|
||||
} else if ((opcode & 0xF8000000) == 0x90000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // stw, stwu
|
||||
} else if ((opcode & 0xF8000000) == 0x98000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // stb, stbu
|
||||
} else if ((opcode & 0xF8000000) == 0xA0000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lhz, lhzu
|
||||
} else if ((opcode & 0xFC000000) == 0xAC000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lhau
|
||||
} else if ((opcode & 0xF8000000) == 0xB0000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // sth, sthu
|
||||
} else if ((opcode & 0xF8000000) == 0xC0000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lfs, lfsu
|
||||
} else if ((opcode & 0xFC000000) == 0xC8000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // lfd
|
||||
} else if ((opcode & 0xF8000000) == 0xD0000000) {
|
||||
fn.code.emplace_back(opcode, 0xFFFF0000); // stfs, stfsu
|
||||
} else {
|
||||
fn.code.emplace_back(opcode, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
auto a_ana = disassemble_section(a, a_sec);
|
||||
auto b_ana = disassemble_section(b, b_sec);
|
||||
|
||||
bool use_color = isatty(fileno(stream));
|
||||
auto a_fn_it = a_ana.functions.cbegin();
|
||||
auto b_fn_it = b_ana.functions.cbegin();
|
||||
while ((a_fn_it != a_ana.functions.end()) || (b_fn_it != b_ana.functions.end())) {
|
||||
if ((a_fn_it != a_ana.functions.end()) && (b_fn_it != b_ana.functions.end())) {
|
||||
phosg::fwrite_fmt(stream, "FUNCTION: A:{:08X} B:{:08X}\n", a_fn_it->label->address, b_fn_it->label->address);
|
||||
|
||||
bool functions_identical = true;
|
||||
for (size_t z = 0; z < std::max<size_t>(a_fn_it->code.size(), b_fn_it->code.size()); z++) {
|
||||
uint32_t a_op = (z < a_fn_it->code.size()) ? a_fn_it->code[z].first : 0xFFFFFFFF;
|
||||
uint32_t b_op = (z < b_fn_it->code.size()) ? b_fn_it->code[z].first : 0xFFFFFFFF;
|
||||
uint32_t a_mask = (z < a_fn_it->code.size()) ? a_fn_it->code[z].second : 0xFFFFFFFF;
|
||||
uint32_t b_mask = (z < b_fn_it->code.size()) ? b_fn_it->code[z].second : 0xFFFFFFFF;
|
||||
uint32_t mask = a_mask | b_mask;
|
||||
if ((a_op & mask) != (b_op & mask)) {
|
||||
functions_identical = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!functions_identical) {
|
||||
for (size_t z = 0; z < std::max<size_t>(a_fn_it->code.size(), b_fn_it->code.size()); z++) {
|
||||
uint32_t a_op = (z < a_fn_it->code.size()) ? a_fn_it->code[z].first : 0xFFFFFFFF;
|
||||
uint32_t b_op = (z < b_fn_it->code.size()) ? b_fn_it->code[z].first : 0xFFFFFFFF;
|
||||
uint32_t a_mask = (z < a_fn_it->code.size()) ? a_fn_it->code[z].second : 0xFFFFFFFF;
|
||||
uint32_t b_mask = (z < b_fn_it->code.size()) ? b_fn_it->code[z].second : 0xFFFFFFFF;
|
||||
uint32_t mask = a_mask | b_mask;
|
||||
if ((a_op & mask) == (b_op & mask)) {
|
||||
phosg::fwrite_fmt(stream, " {:08X}->{:08X} {:08X} {}\n",
|
||||
a_fn_it->label->address + z * 4, b_fn_it->label->address + z * 4,
|
||||
a_op, ResourceDASM::PPC32Emulator::disassemble_one(a_fn_it->label->address + z * 4, a_op));
|
||||
} else {
|
||||
if (use_color) {
|
||||
phosg::print_color_escape(stream, phosg::TerminalFormat::BOLD, phosg::TerminalFormat::FG_RED, phosg::TerminalFormat::END);
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "- {:08X}->{:08X} {:08X} {}\n",
|
||||
a_fn_it->label->address + z * 4, b_fn_it->label->address + z * 4,
|
||||
a_op, ResourceDASM::PPC32Emulator::disassemble_one(a_fn_it->label->address + z * 4, a_op));
|
||||
if (use_color) {
|
||||
phosg::print_color_escape(stream, phosg::TerminalFormat::BOLD, phosg::TerminalFormat::FG_GREEN, phosg::TerminalFormat::END);
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "+ {:08X}->{:08X} {:08X} {}\n",
|
||||
a_fn_it->label->address + z * 4, b_fn_it->label->address + z * 4,
|
||||
b_op, ResourceDASM::PPC32Emulator::disassemble_one(b_fn_it->label->address + z * 4, b_op));
|
||||
if (use_color) {
|
||||
phosg::print_color_escape(stream, phosg::TerminalFormat::NORMAL, phosg::TerminalFormat::END);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
a_fn_it++;
|
||||
} while (a_fn_it != a_ana.functions.end() && a_ignore_functions.count(a_fn_it->label->address));
|
||||
do {
|
||||
b_fn_it++;
|
||||
} while (b_fn_it != b_ana.functions.end() && b_ignore_functions.count(b_fn_it->label->address));
|
||||
|
||||
} else if (a_fn_it != a_ana.functions.end()) {
|
||||
phosg::fwrite_fmt(stream, "FUNCTION: A:{:08X} B:(missing)\n", a_fn_it->label->address);
|
||||
for (size_t z = 0; z < a_fn_it->code.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:08X} {:08X} {}\n",
|
||||
a_fn_it->label->address + z * 4, a_fn_it->code[z].first,
|
||||
ResourceDASM::PPC32Emulator::disassemble_one(a_fn_it->label->address + z * 4, a_fn_it->code[z].first));
|
||||
}
|
||||
do {
|
||||
a_fn_it++;
|
||||
} while (a_fn_it != a_ana.functions.end() && a_ignore_functions.count(a_fn_it->label->address));
|
||||
|
||||
} else {
|
||||
phosg::fwrite_fmt(stream, "FUNCTION: A:(missing) B:{:08X}\n", b_fn_it->label->address);
|
||||
for (size_t z = 0; z < b_fn_it->code.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:08X} {:08X} {}\n",
|
||||
b_fn_it->label->address + z * 4, b_fn_it->code[z].first,
|
||||
ResourceDASM::PPC32Emulator::disassemble_one(b_fn_it->label->address + z * 4, b_fn_it->code[z].first));
|
||||
}
|
||||
do {
|
||||
b_fn_it++;
|
||||
} while (b_fn_it != b_ana.functions.end() && b_ignore_functions.count(b_fn_it->label->address));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DiffEntry> diff_xbe_files(const std::string& a_filename, const std::string& b_filename) {
|
||||
ResourceDASM::XBEFile a(a_filename.c_str());
|
||||
ResourceDASM::XBEFile b(b_filename.c_str());
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -13,5 +14,13 @@ struct DiffEntry {
|
||||
};
|
||||
|
||||
void run_address_translator(const std::string& directory, const std::string& use_filename, const std::string& command);
|
||||
|
||||
std::vector<DiffEntry> diff_dol_files(const std::string& a_filename, const std::string& b_filename);
|
||||
std::vector<DiffEntry> diff_xbe_files(const std::string& a_filename, const std::string& b_filename);
|
||||
|
||||
void diff_dol_files_semantic(
|
||||
FILE* stream,
|
||||
const std::string& a_filename,
|
||||
const std::string& b_filename,
|
||||
const std::unordered_set<uint32_t>& a_ignore_functions,
|
||||
const std::unordered_set<uint32_t>& b_ignore_functions);
|
||||
|
||||
@@ -950,171 +950,3 @@ JSONCommonItemSet::JSONCommonItemSet(const phosg::JSON& json) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RELFileSet::RELFileSet(std::shared_ptr<const std::string> data) : data(data), r(*this->data) {}
|
||||
|
||||
ArmorRandomSet::ArmorRandomSet(std::shared_ptr<const std::string> data) : RELFileSet(data) {
|
||||
// For some reason the footer tables are doubly indirect in this file
|
||||
uint32_t specs_offset_offset = this->r.pget_u32b(data->size() - 0x10);
|
||||
uint32_t specs_offset = this->r.pget_u32b(specs_offset_offset);
|
||||
this->tables = &this->r.pget<parray<TableSpec, 3>>(specs_offset);
|
||||
}
|
||||
|
||||
std::pair<const ArmorRandomSet::WeightTableEntry8*, size_t>
|
||||
ArmorRandomSet::get_armor_table(size_t index) const {
|
||||
return this->get_table<WeightTableEntry8>(this->tables->at(0), index);
|
||||
}
|
||||
|
||||
std::pair<const ArmorRandomSet::WeightTableEntry8*, size_t>
|
||||
ArmorRandomSet::get_shield_table(size_t index) const {
|
||||
return this->get_table<WeightTableEntry8>(this->tables->at(1), index);
|
||||
}
|
||||
|
||||
std::pair<const ArmorRandomSet::WeightTableEntry8*, size_t>
|
||||
ArmorRandomSet::get_unit_table(size_t index) const {
|
||||
return this->get_table<WeightTableEntry8>(this->tables->at(2), index);
|
||||
}
|
||||
|
||||
ToolRandomSet::ToolRandomSet(std::shared_ptr<const std::string> data) : RELFileSet(data) {
|
||||
uint32_t specs_offset = r.pget_u32b(data->size() - 0x10);
|
||||
this->common_recovery_table_spec = &r.pget<TableSpec>(r.pget_u32b(specs_offset));
|
||||
this->rare_recovery_table_spec = &r.pget<TableSpec>(r.pget_u32b(specs_offset + sizeof(uint32_t)), 2 * sizeof(TableSpec));
|
||||
this->tech_disk_table_spec = this->rare_recovery_table_spec + 1;
|
||||
this->tech_disk_level_table_spec = &r.pget<TableSpec>(r.pget_u32b(specs_offset + 2 * sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
std::pair<const uint8_t*, size_t> ToolRandomSet::get_common_recovery_table(size_t index) const {
|
||||
return this->get_table<uint8_t>(*this->common_recovery_table_spec, index);
|
||||
}
|
||||
|
||||
std::pair<const ToolRandomSet::WeightTableEntry8*, size_t>
|
||||
ToolRandomSet::get_rare_recovery_table(size_t index) const {
|
||||
return this->get_table<WeightTableEntry8>(*this->rare_recovery_table_spec, index);
|
||||
}
|
||||
|
||||
std::pair<const ToolRandomSet::WeightTableEntry8*, size_t>
|
||||
ToolRandomSet::get_tech_disk_table(size_t index) const {
|
||||
return this->get_table<WeightTableEntry8>(*this->tech_disk_table_spec, index);
|
||||
}
|
||||
|
||||
std::pair<const ToolRandomSet::TechDiskLevelEntry*, size_t>
|
||||
ToolRandomSet::get_tech_disk_level_table(size_t index) const {
|
||||
return this->get_table<TechDiskLevelEntry>(*this->tech_disk_level_table_spec, index);
|
||||
}
|
||||
|
||||
WeaponRandomSet::WeaponRandomSet(std::shared_ptr<const std::string> data) : RELFileSet(data) {
|
||||
uint32_t offsets_offset = this->r.pget_u32b(data->size() - 0x10);
|
||||
this->offsets = &this->r.pget<Offsets>(offsets_offset);
|
||||
}
|
||||
|
||||
std::pair<const WeaponRandomSet::WeightTableEntry8*, size_t>
|
||||
WeaponRandomSet::get_weapon_type_table(size_t index) const {
|
||||
const auto& spec = this->r.pget<TableSpec>(this->offsets->weapon_type_table + index * sizeof(TableSpec));
|
||||
const auto* data = &this->r.pget<WeightTableEntry8>(spec.offset, spec.entries_per_table * sizeof(WeightTableEntry8));
|
||||
return std::make_pair(data, spec.entries_per_table);
|
||||
}
|
||||
|
||||
const parray<WeaponRandomSet::WeightTableEntry32, 6>*
|
||||
WeaponRandomSet::get_bonus_type_table(size_t which, size_t index) const {
|
||||
uint32_t base_offset = which ? this->offsets->bonus_type_table2 : this->offsets->bonus_type_table1;
|
||||
return &this->r.pget<parray<WeightTableEntry32, 6>>(base_offset + sizeof(parray<WeightTableEntry32, 6>) * index);
|
||||
}
|
||||
|
||||
const WeaponRandomSet::RangeTableEntry*
|
||||
WeaponRandomSet::get_bonus_range(size_t which, size_t index) const {
|
||||
uint32_t base_offset = which ? this->offsets->bonus_range_table2 : this->offsets->bonus_range_table1;
|
||||
return &this->r.pget<RangeTableEntry>(base_offset + sizeof(RangeTableEntry) * index);
|
||||
}
|
||||
|
||||
const parray<WeaponRandomSet::WeightTableEntry32, 3>*
|
||||
WeaponRandomSet::get_special_mode_table(size_t index) const {
|
||||
return &this->r.pget<parray<WeightTableEntry32, 3>>(
|
||||
this->offsets->special_mode_table + sizeof(parray<WeightTableEntry32, 3>) * index);
|
||||
}
|
||||
|
||||
const WeaponRandomSet::RangeTableEntry*
|
||||
WeaponRandomSet::get_standard_grind_range(size_t index) const {
|
||||
return &this->r.pget<RangeTableEntry>(this->offsets->standard_grind_range_table + sizeof(RangeTableEntry) * index);
|
||||
}
|
||||
|
||||
const WeaponRandomSet::RangeTableEntry*
|
||||
WeaponRandomSet::get_favored_grind_range(size_t index) const {
|
||||
return &this->r.pget<RangeTableEntry>(this->offsets->favored_grind_range_table + sizeof(RangeTableEntry) * index);
|
||||
}
|
||||
|
||||
TekkerAdjustmentSet::TekkerAdjustmentSet(std::shared_ptr<const std::string> data) : data(data), r(*data) {
|
||||
this->offsets = &this->r.pget<Offsets>(this->r.pget_u32b(this->r.size() - 0x10));
|
||||
}
|
||||
|
||||
const ProbabilityTable<uint8_t, 100>& TekkerAdjustmentSet::get_table(
|
||||
std::array<ProbabilityTable<uint8_t, 100>, 10>& tables_default,
|
||||
std::array<ProbabilityTable<uint8_t, 100>, 10>& tables_favored,
|
||||
uint32_t offset_and_count_offset,
|
||||
bool favored,
|
||||
uint8_t section_id) const {
|
||||
if (section_id >= 10) {
|
||||
throw std::runtime_error("invalid section ID");
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100>& table = favored ? tables_favored[section_id] : tables_default[section_id];
|
||||
if (table.count == 0) {
|
||||
uint32_t offset = r.pget_u32b(offset_and_count_offset);
|
||||
uint32_t count_per_section_id = r.pget_u32b(offset_and_count_offset + 4);
|
||||
auto* entries = &r.pget<DeltaProbabilityEntry>(offset, sizeof(DeltaProbabilityEntry) * count_per_section_id * 10);
|
||||
for (size_t z = count_per_section_id * section_id; z < count_per_section_id * (section_id + 1); z++) {
|
||||
size_t count = favored ? entries[z].count_favored : entries[z].count_default;
|
||||
for (size_t w = 0; w < count; w++) {
|
||||
table.push(entries[z].delta_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
const ProbabilityTable<uint8_t, 100>& TekkerAdjustmentSet::get_special_upgrade_prob_table(uint8_t section_id, bool favored) const {
|
||||
return this->get_table(
|
||||
this->special_upgrade_prob_tables_default,
|
||||
this->special_upgrade_prob_tables_favored,
|
||||
this->offsets->special_upgrade_prob_table_offset,
|
||||
favored, section_id);
|
||||
}
|
||||
|
||||
const ProbabilityTable<uint8_t, 100>& TekkerAdjustmentSet::get_grind_delta_prob_table(uint8_t section_id, bool favored) const {
|
||||
return this->get_table(
|
||||
this->grind_delta_prob_tables_default,
|
||||
this->grind_delta_prob_tables_favored,
|
||||
this->offsets->grind_delta_prob_table_offset,
|
||||
favored, section_id);
|
||||
}
|
||||
|
||||
const ProbabilityTable<uint8_t, 100>& TekkerAdjustmentSet::get_bonus_delta_prob_table(uint8_t section_id, bool favored) const {
|
||||
return this->get_table(
|
||||
this->bonus_delta_prob_tables_default,
|
||||
this->bonus_delta_prob_tables_favored,
|
||||
this->offsets->bonus_delta_prob_table_offset,
|
||||
favored, section_id);
|
||||
}
|
||||
|
||||
int8_t TekkerAdjustmentSet::get_luck(uint32_t start_offset, uint8_t delta_index) const {
|
||||
phosg::StringReader sub_r = r.sub(start_offset);
|
||||
while (!sub_r.eof()) {
|
||||
const auto& entry = sub_r.get<LuckTableEntry>();
|
||||
if (entry.delta_index == 0xFF) {
|
||||
return 0;
|
||||
} else if (entry.delta_index == delta_index) {
|
||||
return entry.luck;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t TekkerAdjustmentSet::get_luck_for_special_upgrade(uint8_t delta_index) const {
|
||||
return this->get_luck(this->offsets->special_upgrade_luck_table_offset, delta_index);
|
||||
}
|
||||
|
||||
int8_t TekkerAdjustmentSet::get_luck_for_grind_delta(uint8_t delta_index) const {
|
||||
return this->get_luck(this->offsets->grind_delta_luck_table_offset, delta_index);
|
||||
}
|
||||
|
||||
int8_t TekkerAdjustmentSet::get_luck_for_bonus_delta(uint8_t delta_index) const {
|
||||
return this->get_luck(this->offsets->bonus_delta_luck_offset, delta_index);
|
||||
}
|
||||
|
||||
@@ -284,295 +284,3 @@ class JSONCommonItemSet : public CommonItemSet {
|
||||
public:
|
||||
explicit JSONCommonItemSet(const phosg::JSON& json);
|
||||
};
|
||||
|
||||
// Note: There are clearly better ways of doing this, but this implementation closely follows what the original code in
|
||||
// the client does.
|
||||
template <typename ItemT, size_t MaxCount>
|
||||
struct ProbabilityTable {
|
||||
ItemT items[MaxCount];
|
||||
size_t count;
|
||||
|
||||
ProbabilityTable() : count(0) {}
|
||||
|
||||
void push(ItemT item) {
|
||||
if (this->count == MaxCount) {
|
||||
throw std::runtime_error("push to full probability table");
|
||||
}
|
||||
this->items[this->count++] = item;
|
||||
}
|
||||
|
||||
ItemT pop() {
|
||||
if (this->count == 0) {
|
||||
throw std::runtime_error("pop from empty probability table");
|
||||
}
|
||||
return this->items[--this->count];
|
||||
}
|
||||
|
||||
void shuffle(std::shared_ptr<RandomGenerator> rand_crypt) {
|
||||
for (size_t z = 1; z < this->count; z++) {
|
||||
size_t other_z = rand_crypt->next() % (z + 1);
|
||||
ItemT t = this->items[z];
|
||||
this->items[z] = this->items[other_z];
|
||||
this->items[other_z] = t;
|
||||
}
|
||||
}
|
||||
|
||||
ItemT sample(std::shared_ptr<RandomGenerator> rand_crypt) const {
|
||||
if (this->count == 0) {
|
||||
throw std::runtime_error("sample from empty probability table");
|
||||
} else if (this->count == 1) {
|
||||
return this->items[0];
|
||||
} else {
|
||||
return this->items[rand_crypt->next() % this->count];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RELFileSet {
|
||||
public:
|
||||
template <typename ValueT, typename WeightT = ValueT>
|
||||
struct WeightTableEntry {
|
||||
ValueT value;
|
||||
WeightT weight;
|
||||
} __attribute__((packed));
|
||||
using WeightTableEntry8 = WeightTableEntry<uint8_t>;
|
||||
using WeightTableEntry32 = WeightTableEntry<be_uint32_t>;
|
||||
check_struct_size(WeightTableEntry8, 2);
|
||||
check_struct_size(WeightTableEntry32, 8);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const std::string> data;
|
||||
phosg::StringReader r;
|
||||
|
||||
struct TableSpec {
|
||||
be_uint32_t offset;
|
||||
uint8_t entries_per_table;
|
||||
parray<uint8_t, 3> unused;
|
||||
} __packed_ws__(TableSpec, 8);
|
||||
|
||||
RELFileSet(std::shared_ptr<const std::string> data);
|
||||
|
||||
template <typename T>
|
||||
std::pair<const T*, size_t> get_table(const TableSpec& spec, size_t index) const {
|
||||
const T* entries = &r.pget<T>(
|
||||
spec.offset + index * spec.entries_per_table * sizeof(T), spec.entries_per_table * sizeof(T));
|
||||
return std::make_pair(entries, spec.entries_per_table);
|
||||
}
|
||||
};
|
||||
|
||||
class ArmorRandomSet : public RELFileSet {
|
||||
public:
|
||||
// This class parses and accesses data from ArmorRandom.rel
|
||||
ArmorRandomSet(std::shared_ptr<const std::string> data);
|
||||
|
||||
std::pair<const WeightTableEntry8*, size_t> get_armor_table(size_t index) const;
|
||||
std::pair<const WeightTableEntry8*, size_t> get_shield_table(size_t index) const;
|
||||
std::pair<const WeightTableEntry8*, size_t> get_unit_table(size_t index) const;
|
||||
|
||||
private:
|
||||
const parray<TableSpec, 3>* tables;
|
||||
};
|
||||
|
||||
class ToolRandomSet : public RELFileSet {
|
||||
public:
|
||||
// This class parses and accesses data from ToolRandom.rel
|
||||
ToolRandomSet(std::shared_ptr<const std::string> data);
|
||||
|
||||
struct TechDiskLevelEntry {
|
||||
enum class Mode : uint8_t {
|
||||
LEVEL_1 = 0,
|
||||
PLAYER_LEVEL_DIVISOR = 1,
|
||||
RANDOM_IN_RANGE = 2,
|
||||
};
|
||||
Mode mode;
|
||||
uint8_t player_level_divisor_or_min_level;
|
||||
uint8_t max_level;
|
||||
} __packed_ws__(TechDiskLevelEntry, 3);
|
||||
|
||||
std::pair<const uint8_t*, size_t> get_common_recovery_table(size_t index) const;
|
||||
std::pair<const WeightTableEntry8*, size_t> get_rare_recovery_table(size_t index) const;
|
||||
std::pair<const WeightTableEntry8*, size_t> get_tech_disk_table(size_t index) const;
|
||||
std::pair<const TechDiskLevelEntry*, size_t> get_tech_disk_level_table(size_t index) const;
|
||||
|
||||
private:
|
||||
const TableSpec* common_recovery_table_spec;
|
||||
const TableSpec* rare_recovery_table_spec;
|
||||
const TableSpec* tech_disk_table_spec;
|
||||
const TableSpec* tech_disk_level_table_spec;
|
||||
};
|
||||
|
||||
class WeaponRandomSet : public RELFileSet {
|
||||
public:
|
||||
// This class parses and accesses data from WeaponRandom*.rel
|
||||
WeaponRandomSet(std::shared_ptr<const std::string> data);
|
||||
|
||||
struct RangeTableEntry {
|
||||
be_uint32_t min;
|
||||
be_uint32_t max;
|
||||
} __packed_ws__(RangeTableEntry, 8);
|
||||
|
||||
std::pair<const WeightTableEntry8*, size_t> get_weapon_type_table(size_t index) const;
|
||||
const parray<WeightTableEntry32, 6>* get_bonus_type_table(size_t which, size_t index) const;
|
||||
const RangeTableEntry* get_bonus_range(size_t which, size_t index) const;
|
||||
const parray<WeightTableEntry32, 3>* get_special_mode_table(size_t index) const;
|
||||
const RangeTableEntry* get_standard_grind_range(size_t index) const;
|
||||
const RangeTableEntry* get_favored_grind_range(size_t index) const;
|
||||
|
||||
private:
|
||||
struct Offsets {
|
||||
be_uint32_t weapon_type_table; // [{c, o -> (table)}](10)
|
||||
be_uint32_t bonus_type_table1; // [[{u32 value, u32 weight}](6)](9)
|
||||
be_uint32_t bonus_type_table2; // [[{u32 value, u32 weight}](6)](9)
|
||||
be_uint32_t bonus_range_table1; // [{u32 min_index, u32 max_index}](9)
|
||||
be_uint32_t bonus_range_table2; // [{u32 min_index, u32 max_index}](9)
|
||||
be_uint32_t special_mode_table; // [[{u32 value, u32 weight}](3)](8)
|
||||
be_uint32_t standard_grind_range_table; // [{u32 min, u32 max}](6)
|
||||
be_uint32_t favored_grind_range_table; // [{u32 min, u32 max}](6)
|
||||
} __packed_ws__(Offsets, 0x20);
|
||||
|
||||
const Offsets* offsets;
|
||||
};
|
||||
|
||||
class TekkerAdjustmentSet {
|
||||
public:
|
||||
// This class parses and accesses data from JudgeItem.rel
|
||||
TekkerAdjustmentSet(std::shared_ptr<const std::string> data);
|
||||
|
||||
const ProbabilityTable<uint8_t, 100>& get_special_upgrade_prob_table(uint8_t section_id, bool favored) const;
|
||||
const ProbabilityTable<uint8_t, 100>& get_grind_delta_prob_table(uint8_t section_id, bool favored) const;
|
||||
const ProbabilityTable<uint8_t, 100>& get_bonus_delta_prob_table(uint8_t section_id, bool favored) const;
|
||||
int8_t get_luck_for_special_upgrade(uint8_t delta_index) const;
|
||||
int8_t get_luck_for_grind_delta(uint8_t delta_index) const;
|
||||
int8_t get_luck_for_bonus_delta(uint8_t delta_index) const;
|
||||
|
||||
private:
|
||||
const ProbabilityTable<uint8_t, 100>& get_table(
|
||||
std::array<ProbabilityTable<uint8_t, 100>, 10>& tables_default,
|
||||
std::array<ProbabilityTable<uint8_t, 100>, 10>& tables_favored,
|
||||
uint32_t offset_and_count_offset,
|
||||
bool favored,
|
||||
uint8_t section_id) const;
|
||||
int8_t get_luck(uint32_t start_offset, uint8_t delta_index) const;
|
||||
|
||||
std::shared_ptr<const std::string> data;
|
||||
phosg::StringReader r;
|
||||
|
||||
struct DeltaProbabilityEntry {
|
||||
uint8_t delta_index;
|
||||
uint8_t count_default;
|
||||
uint8_t count_favored;
|
||||
} __packed_ws__(DeltaProbabilityEntry, 3);
|
||||
struct LuckTableEntry {
|
||||
uint8_t delta_index;
|
||||
int8_t luck;
|
||||
} __packed_ws__(LuckTableEntry, 2);
|
||||
|
||||
struct Offsets {
|
||||
// Each section ID's favored weapon class has different probabilities than those used for all other weapons. The
|
||||
// tables are labeled with (D) for the default values and (F) for the favored-class values.
|
||||
|
||||
// Note that the favored bonuses for Redria are all zero; these values are unused because Redria does not have a
|
||||
// favored weapon type. Curiously, Yellowboze also does not have a favored weapon type, but the values for
|
||||
// Yellowboze are not all zero.
|
||||
|
||||
// This table specifies how likely a special is to be upgraded or downgraded by one level.
|
||||
// In PSO V3, the special upgrade table is:
|
||||
// Viridia => (D) +1=10%, 0=60%, -1=30%
|
||||
// Viridia => (F) +1=25%, 0=50%, -1=25%
|
||||
// Greennill => (D) +1=25%, 0=65%, -1=10%
|
||||
// Greennill => (F) +1=40%, 0=55%, -1=5%
|
||||
// Skyly => (D) +1=15%, 0=70%, -1=15%
|
||||
// Skyly => (F) +1=30%, 0=60%, -1=10%
|
||||
// Bluefull => (D) +1=10%, 0=60%, -1=30%
|
||||
// Bluefull => (F) +1=25%, 0=50%, -1=25%
|
||||
// Purplenum => (D) +1=25%, 0=65%, -1=10%
|
||||
// Purplenum => (F) +1=40%, 0=55%, -1=5%
|
||||
// Pinkal => (D) +1=15%, 0=70%, -1=15%
|
||||
// Pinkal => (F) +1=30%, 0=60%, -1=10%
|
||||
// Redria => (D) +1=20%, 0=60%, -1=20%
|
||||
// Redria => (F) +1=0%, 0=0%, -1=0%
|
||||
// Oran => (D) +1=15%, 0=70%, -1=15%
|
||||
// Oran => (F) +1=30%, 0=60%, -1=10%
|
||||
// Yellowboze => (D) +1=25%, 0=65%, -1=10%
|
||||
// Yellowboze => (F) +1=40%, 0=55%, -1=5%
|
||||
// Whitill => (D) +1=10%, 0=60%, -1=30%
|
||||
// Whitill => (F) +1=25%, 0=50%, -1=25%
|
||||
be_uint32_t special_upgrade_prob_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// This table specifies how likely a weapon's grind is to be upgraded or downgraded, and by how much. The final
|
||||
// grind value is clamped to the range between 0 and the weapon's maximum grind from ItemPMT, inclusive.
|
||||
// In PSO V3, the grind delta table is:
|
||||
// Viridia => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Viridia => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
// Greennill => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Greennill => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Skyly => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Skyly => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Bluefull => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Bluefull => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
// Purplenum => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Purplenum => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Pinkal => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Pinkal => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Redria => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Redria => (F) +3=0%, +2=0%, +1=0%, 0=0%, -1=0%, -2=0%, -3=0%
|
||||
// Oran => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Oran => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Yellowboze => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Yellowboze => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Whitill => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Whitill => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
be_uint32_t grind_delta_prob_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// This table specifies how likely a weapon's bonuses are to be upgraded or downgraded, and by how much. The final
|
||||
// bonuses are capped above at 100, but there is no lower limit (so negative results are possible).
|
||||
// In PSO V3, the bonus delta table is:
|
||||
// Viridia => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Viridia => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
// Greennill => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Greennill => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Skyly => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Skyly => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Bluefull => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Bluefull => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
// Purplenum => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Purplenum => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Pinkal => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Pinkal => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Redria => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Redria => (F) +10=0%, +5=0%, 0=0%, -5=0%, -10=0%
|
||||
// Oran => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Oran => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Yellowboze => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Yellowboze => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Whitill => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Whitill => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
be_uint32_t bonus_delta_prob_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// There is a secondary computation done during weapon adjustment that appears to determine how "good" the
|
||||
// resulting weapon is compared to its original state. If the result of this computation is positive, the game
|
||||
// plays a jingle when the tekker result is accepted. These tables describe how much each delta affects this value,
|
||||
// which we call luck.
|
||||
|
||||
// In PSO V3, the special upgrade luck table is:
|
||||
// +1 => +20, 0 => 0, -1 => -20
|
||||
be_uint32_t special_upgrade_luck_table_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
|
||||
// In PSO V3, the grind delta luck table is:
|
||||
// +3 => +10, +2 => +5, +1 => +3, 0 => 0, -1 => -3, -2 => -5, -3 => -10
|
||||
be_uint32_t grind_delta_luck_table_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
|
||||
// In PSO V3, the bonus delta luck table is:
|
||||
// +10 => +15, +5 => +8, 0 => 0, -5 => -8, -10 => -15
|
||||
be_uint32_t bonus_delta_luck_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
} __packed_ws__(Offsets, 0x18);
|
||||
|
||||
const Offsets* offsets;
|
||||
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> special_upgrade_prob_tables_default;
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> special_upgrade_prob_tables_favored;
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> grind_delta_prob_tables_default;
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> grind_delta_prob_tables_favored;
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> bonus_delta_prob_tables_default;
|
||||
mutable std::array<ProbabilityTable<uint8_t, 100>, 10> bonus_delta_prob_tables_favored;
|
||||
};
|
||||
|
||||
+127
-51
@@ -28,29 +28,29 @@ const char* phosg::name_for_enum<CompressPhase>(CompressPhase v) {
|
||||
}
|
||||
|
||||
template <size_t WindowLength, size_t MaxMatchLength>
|
||||
struct WindowIndex {
|
||||
struct MapWindowIndex {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
size_t current_offset;
|
||||
std::set<size_t, std::function<bool(size_t, size_t)>> index;
|
||||
|
||||
WindowIndex(const void* data, size_t size)
|
||||
MapWindowIndex(const void* data, size_t size)
|
||||
: data(reinterpret_cast<const uint8_t*>(data)),
|
||||
size(size),
|
||||
offset(0),
|
||||
index(std::bind(&WindowIndex::set_comparator, this, std::placeholders::_1, std::placeholders::_2)) {}
|
||||
current_offset(0),
|
||||
index(std::bind(&MapWindowIndex::set_comparator, this, std::placeholders::_1, std::placeholders::_2)) {}
|
||||
|
||||
void advance() {
|
||||
if (this->offset >= WindowLength) {
|
||||
this->index.erase(this->offset - WindowLength);
|
||||
if (this->current_offset >= WindowLength) {
|
||||
this->index.erase(this->current_offset - WindowLength);
|
||||
}
|
||||
this->index.emplace(this->offset);
|
||||
this->offset++;
|
||||
this->index.emplace(this->current_offset);
|
||||
this->current_offset++;
|
||||
}
|
||||
|
||||
size_t get_match_length(size_t match_offset) const {
|
||||
size_t match_iter = match_offset;
|
||||
size_t offset_iter = this->offset;
|
||||
size_t offset_iter = this->current_offset;
|
||||
while ((match_iter < match_offset + MaxMatchLength) &&
|
||||
(match_iter < this->size) &&
|
||||
(offset_iter < this->size) &&
|
||||
@@ -81,14 +81,14 @@ struct WindowIndex {
|
||||
return a < b; // Maximum-length match; order them by offset
|
||||
};
|
||||
|
||||
std::pair<size_t, size_t> get_best_match() const {
|
||||
std::pair<size_t, size_t> match() const {
|
||||
// Find the best match from the index. It's unlikely that we'll get an exact match, so check the entry before the
|
||||
// upper_bound result too. Note: We use upper_bound rather than lower_bound because in PRS, a backreference can be
|
||||
// encoded with fewer bits if it's close to the decompression offset, and this makes us pick the latest match by
|
||||
// default.
|
||||
size_t match_offset = 0;
|
||||
size_t match_size = 0;
|
||||
auto it = this->index.upper_bound(this->offset);
|
||||
auto it = this->index.upper_bound(this->current_offset);
|
||||
if (it != this->index.end()) {
|
||||
size_t new_match_offset = *it;
|
||||
size_t new_match_size = this->get_match_length(new_match_offset);
|
||||
@@ -110,6 +110,82 @@ struct WindowIndex {
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t WindowLength, size_t MaxMatchLength>
|
||||
struct TreeWindowIndex {
|
||||
// This class is the result of an experiment to see if a prefix tree is faster for optimal compression. It turns out
|
||||
// it's not, even if the std::map in Node is replaced with a std::unordered_map or std::array. This structure is
|
||||
// easier to understand than MapWindowIndex, but is about 6-7x slower on average.
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
size_t current_offset;
|
||||
|
||||
struct Node {
|
||||
size_t start_offset = 0;
|
||||
std::map<uint8_t, Node> children;
|
||||
};
|
||||
Node root;
|
||||
|
||||
TreeWindowIndex(const void* data, size_t size)
|
||||
: data(reinterpret_cast<const uint8_t*>(data)), size(size), current_offset(0) {}
|
||||
|
||||
void advance() {
|
||||
// Delete the oldest string, if the current offset has passed the initial window
|
||||
if (this->current_offset >= WindowLength) {
|
||||
size_t start_offset = this->current_offset - WindowLength;
|
||||
size_t end_offset = std::min<size_t>(this->size, start_offset + MaxMatchLength);
|
||||
Node* current = &this->root;
|
||||
for (size_t offset = start_offset; offset < end_offset; offset++) {
|
||||
auto child_it = current->children.find(this->data[offset]);
|
||||
// The child should always be in the set - we should have added all of its nodes in a previous advance() call
|
||||
if (child_it == current->children.end()) {
|
||||
throw std::logic_error(std::format("Attempted to delete string at offset {:X} which was not in the set",
|
||||
start_offset));
|
||||
}
|
||||
if (child_it->second.start_offset == start_offset) {
|
||||
// If the child's start offset matches start_offset, then the rest of the nodes below it must also match
|
||||
// start_offset (they were never again visited by the second part of this function after the first time they
|
||||
// were added) so the entire subtree can be deleted. This means there are no other strings in the window that
|
||||
// share the first (start_offset + 1) bytes with this string.
|
||||
current->children.erase(child_it);
|
||||
break;
|
||||
} else {
|
||||
// If the start offset does not match start_offset, then this node belongs to a later string; we need to
|
||||
// check its subtree to see if anything should be deleted
|
||||
current = &child_it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create all nodes for the current string, or update their start_offsets if they already exist
|
||||
size_t end_offset = std::min<size_t>(size, this->current_offset + MaxMatchLength);
|
||||
Node* current = &this->root;
|
||||
for (size_t offset = this->current_offset; offset < end_offset; offset++) {
|
||||
current = ¤t->children[this->data[offset]];
|
||||
current->start_offset = this->current_offset;
|
||||
}
|
||||
|
||||
this->current_offset++;
|
||||
}
|
||||
|
||||
std::pair<size_t, size_t> match() const {
|
||||
size_t end_offset = std::min<size_t>(size, this->current_offset + MaxMatchLength);
|
||||
const Node* current = &this->root;
|
||||
size_t offset;
|
||||
for (offset = this->current_offset; offset < end_offset; offset++) {
|
||||
auto it = current->children.find(this->data[offset]);
|
||||
if (it == current->children.end()) {
|
||||
break;
|
||||
} else {
|
||||
current = &it->second;
|
||||
}
|
||||
}
|
||||
return std::make_pair(current->start_offset, offset - this->current_offset);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t WindowSize, size_t MaxMatchLength>
|
||||
using WindowIndex = MapWindowIndex<WindowSize, MaxMatchLength>;
|
||||
|
||||
struct LZSSInterleavedWriter {
|
||||
phosg::StringWriter w;
|
||||
size_t buf_offset;
|
||||
@@ -219,15 +295,15 @@ std::string prs_compress_optimal(const void* in_data_v, size_t in_size, Progress
|
||||
// Populate all possible short copies
|
||||
std::thread short_window_thread([&]() -> void {
|
||||
WindowIndex<0x100, 5> window(in_data_v, in_size);
|
||||
while (window.offset < in_size) {
|
||||
if (window.offset && (window.offset & 0xFFF) == 0 && progress_fn) {
|
||||
while (window.current_offset < in_size) {
|
||||
if (window.current_offset && (window.current_offset & 0xFFF) == 0 && progress_fn) {
|
||||
size_t progress = copy_progress.fetch_add(0x1000) + 0x1000;
|
||||
progress_fn(CompressPhase::INDEX, progress, copy_progress_max, 0);
|
||||
}
|
||||
auto& node = nodes[window.offset];
|
||||
auto match = window.get_best_match();
|
||||
auto& node = nodes[window.current_offset];
|
||||
auto match = window.match();
|
||||
if (match.second >= 2) {
|
||||
node.short_copy_offset = match.first - window.offset;
|
||||
node.short_copy_offset = match.first - window.current_offset;
|
||||
node.max_short_copy_size = match.second;
|
||||
}
|
||||
window.advance();
|
||||
@@ -237,15 +313,15 @@ std::string prs_compress_optimal(const void* in_data_v, size_t in_size, Progress
|
||||
// Populate all possible long copies
|
||||
std::thread long_window_thread([&]() -> void {
|
||||
WindowIndex<0x1FFF, 9> window(in_data_v, in_size);
|
||||
while (window.offset < in_size) {
|
||||
if (window.offset && (window.offset & 0xFFF) == 0 && progress_fn) {
|
||||
while (window.current_offset < in_size) {
|
||||
if (window.current_offset && (window.current_offset & 0xFFF) == 0 && progress_fn) {
|
||||
size_t progress = copy_progress.fetch_add(0x1000) + 0x1000;
|
||||
progress_fn(CompressPhase::INDEX, progress, copy_progress_max, 0);
|
||||
}
|
||||
auto& node = nodes[window.offset];
|
||||
auto match = window.get_best_match();
|
||||
auto& node = nodes[window.current_offset];
|
||||
auto match = window.match();
|
||||
if (match.second >= 3) {
|
||||
node.long_copy_offset = match.first - window.offset;
|
||||
node.long_copy_offset = match.first - window.current_offset;
|
||||
node.max_long_copy_size = match.second;
|
||||
}
|
||||
window.advance();
|
||||
@@ -255,15 +331,15 @@ std::string prs_compress_optimal(const void* in_data_v, size_t in_size, Progress
|
||||
// Populate all possible extended copies
|
||||
std::thread extended_window_thread([&]() -> void {
|
||||
WindowIndex<0x1FFF, 0x100> window(in_data_v, in_size);
|
||||
while (window.offset < in_size) {
|
||||
if (window.offset && (window.offset & 0xFFF) == 0 && progress_fn) {
|
||||
while (window.current_offset < in_size) {
|
||||
if (window.current_offset && (window.current_offset & 0xFFF) == 0 && progress_fn) {
|
||||
size_t progress = copy_progress.fetch_add(0x1000) + 0x1000;
|
||||
progress_fn(CompressPhase::INDEX, progress, copy_progress_max, 0);
|
||||
}
|
||||
auto& node = nodes[window.offset];
|
||||
auto match = window.get_best_match();
|
||||
auto& node = nodes[window.current_offset];
|
||||
auto match = window.match();
|
||||
if (match.second >= 1) {
|
||||
node.extended_copy_offset = match.first - window.offset;
|
||||
node.extended_copy_offset = match.first - window.current_offset;
|
||||
node.max_extended_copy_size = match.second;
|
||||
}
|
||||
window.advance();
|
||||
@@ -434,10 +510,10 @@ std::string prs_compress_pessimal(const void* vdata, size_t size) {
|
||||
WindowIndex<0x1FFF, 1> window(in_data, size);
|
||||
LZSSInterleavedWriter w;
|
||||
for (size_t z = 0; z < size; z++) {
|
||||
auto match = window.get_best_match();
|
||||
auto match = window.match();
|
||||
if (match.second >= 1) {
|
||||
// Write extended copy
|
||||
int16_t offset = match.first - window.offset;
|
||||
int16_t offset = match.first - window.current_offset;
|
||||
w.write_control(false);
|
||||
w.flush_if_ready();
|
||||
w.write_control(true);
|
||||
@@ -681,15 +757,15 @@ std::string prs_compress_indexed(const void* in_data_v, size_t in_size, Progress
|
||||
WindowIndex<0x1FFF, 0x100> w_extended(in_data_v, in_size);
|
||||
|
||||
size_t last_progress_fn_call_offset = 0;
|
||||
while (w_short.offset < in_size) {
|
||||
if (progress_fn && ((last_progress_fn_call_offset & ~0xFFF) != (w_short.offset & ~0xFFF))) {
|
||||
last_progress_fn_call_offset = w_short.offset;
|
||||
progress_fn(CompressPhase::GENERATE_RESULT, w_short.offset, in_size, w.size());
|
||||
while (w_short.current_offset < in_size) {
|
||||
if (progress_fn && ((last_progress_fn_call_offset & ~0xFFF) != (w_short.current_offset & ~0xFFF))) {
|
||||
last_progress_fn_call_offset = w_short.current_offset;
|
||||
progress_fn(CompressPhase::GENERATE_RESULT, w_short.current_offset, in_size, w.size());
|
||||
}
|
||||
|
||||
auto m_short = w_short.get_best_match();
|
||||
auto m_long = w_long.get_best_match();
|
||||
auto m_extended = w_extended.get_best_match();
|
||||
auto m_short = w_short.match();
|
||||
auto m_long = w_long.match();
|
||||
auto m_extended = w_extended.match();
|
||||
|
||||
// Write the match that achieves the best ratio of output bytes to compressed bits used. To do this without
|
||||
// floating-point math, we multiply the output byte count for each type of command by 468 / (command_bits), since
|
||||
@@ -735,11 +811,11 @@ std::string prs_compress_indexed(const void* in_data_v, size_t in_size, Progress
|
||||
switch (command_type) {
|
||||
case PRSPathNode::CommandType::LITERAL:
|
||||
w.write_control(true);
|
||||
w.write_data(in_data[w_short.offset]);
|
||||
w.write_data(in_data[w_short.current_offset]);
|
||||
bytes_consumed = 1;
|
||||
break;
|
||||
case PRSPathNode::CommandType::SHORT_COPY: {
|
||||
ssize_t backreference_offset = m_short.first - w_short.offset;
|
||||
ssize_t backreference_offset = m_short.first - w_short.current_offset;
|
||||
uint8_t encoded_size = m_short.second - 2;
|
||||
w.write_control(false);
|
||||
w.flush_if_ready();
|
||||
@@ -753,7 +829,7 @@ std::string prs_compress_indexed(const void* in_data_v, size_t in_size, Progress
|
||||
break;
|
||||
}
|
||||
case PRSPathNode::CommandType::LONG_COPY: {
|
||||
ssize_t backreference_offset = m_long.first - w_long.offset;
|
||||
ssize_t backreference_offset = m_long.first - w_long.current_offset;
|
||||
w.write_control(false);
|
||||
w.flush_if_ready();
|
||||
w.write_control(true);
|
||||
@@ -764,7 +840,7 @@ std::string prs_compress_indexed(const void* in_data_v, size_t in_size, Progress
|
||||
break;
|
||||
}
|
||||
case PRSPathNode::CommandType::EXTENDED_COPY: {
|
||||
ssize_t backreference_offset = m_extended.first - w_extended.offset;
|
||||
ssize_t backreference_offset = m_extended.first - w_extended.current_offset;
|
||||
w.write_control(false);
|
||||
w.flush_if_ready();
|
||||
w.write_control(true);
|
||||
@@ -1051,12 +1127,12 @@ std::string bc0_compress_optimal(const void* in_data_v, size_t in_size, Progress
|
||||
// Populate all possible backreferences
|
||||
{
|
||||
WindowIndex<0x1000, 0x12> window(in_data_v, in_size);
|
||||
while (window.offset < in_size) {
|
||||
if ((window.offset & 0xFFF) == 0 && progress_fn) {
|
||||
progress_fn(CompressPhase::INDEX, window.offset, in_size, 0);
|
||||
while (window.current_offset < in_size) {
|
||||
if ((window.current_offset & 0xFFF) == 0 && progress_fn) {
|
||||
progress_fn(CompressPhase::INDEX, window.current_offset, in_size, 0);
|
||||
}
|
||||
auto& node = nodes[window.offset];
|
||||
auto match = window.get_best_match();
|
||||
auto& node = nodes[window.current_offset];
|
||||
auto match = window.match();
|
||||
if (match.second >= 3) {
|
||||
node.memo_offset = (match.first - 0x12) & 0xFFF;
|
||||
node.max_copy_size = match.second;
|
||||
@@ -1148,13 +1224,13 @@ std::string bc0_compress(const void* in_data_v, size_t in_size, ProgressCallback
|
||||
WindowIndex<0x1000, 0x12> window(in_data_v, in_size);
|
||||
|
||||
size_t last_progress_fn_call_offset = 0;
|
||||
while (window.offset < in_size) {
|
||||
if (progress_fn && ((last_progress_fn_call_offset & ~0xFFF) != (window.offset & ~0xFFF))) {
|
||||
last_progress_fn_call_offset = window.offset;
|
||||
progress_fn(CompressPhase::GENERATE_RESULT, window.offset, in_size, w.size());
|
||||
while (window.current_offset < in_size) {
|
||||
if (progress_fn && ((last_progress_fn_call_offset & ~0xFFF) != (window.current_offset & ~0xFFF))) {
|
||||
last_progress_fn_call_offset = window.current_offset;
|
||||
progress_fn(CompressPhase::GENERATE_RESULT, window.current_offset, in_size, w.size());
|
||||
}
|
||||
|
||||
auto match = window.get_best_match();
|
||||
auto match = window.match();
|
||||
|
||||
// Write a backreference if a match was found; otherwise, write a literal
|
||||
if (match.second >= 3) {
|
||||
@@ -1164,7 +1240,7 @@ std::string bc0_compress(const void* in_data_v, size_t in_size, ProgressCallback
|
||||
w.write_data(((memo_offset >> 4) & 0xF0) | (match.second - 3));
|
||||
} else {
|
||||
w.write_control(true);
|
||||
w.write_data(in_data[window.offset]);
|
||||
w.write_data(in_data[window.current_offset]);
|
||||
match.second = 1;
|
||||
}
|
||||
w.flush_if_ready();
|
||||
|
||||
+142
-251
@@ -6,26 +6,72 @@
|
||||
#include "EnemyType.hh"
|
||||
#include "Loggers.hh"
|
||||
|
||||
// The favored weapon type table is hardcoded in the game client. The table is:
|
||||
// Viridia shots
|
||||
// Greennill rifles
|
||||
// Skyly swords
|
||||
// Bluefull partisans
|
||||
// Purplenum mechguns
|
||||
// Pinkal canes
|
||||
// Redria (none)
|
||||
// Oran daggers
|
||||
// Yellowboze (none)
|
||||
// Whitill slicers
|
||||
static const std::array<uint8_t, 10> favored_weapon_by_section_id = {
|
||||
0x09, 0x07, 0x02, 0x04, 0x08, 0x0A, 0xFF, 0x03, 0xFF, 0x05};
|
||||
// Note: There are clearly better ways of doing this, but this implementation closely follows what the original code in
|
||||
// the client does.
|
||||
template <typename ItemT, size_t MaxCount>
|
||||
struct ProbabilityTable {
|
||||
ItemT items[MaxCount];
|
||||
size_t count;
|
||||
|
||||
ProbabilityTable() : count(0) {}
|
||||
|
||||
ProbabilityTable(const std::vector<ShopRandomSetBase::IntPairT<ItemT>>& table) : ProbabilityTable() {
|
||||
for (const auto& entry : table) {
|
||||
for (size_t y = 0; y < entry.weight; y++) {
|
||||
this->push(entry.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t Count>
|
||||
ProbabilityTable(const std::array<ShopRandomSetBase::IntPairT<ItemT>, Count>& table) : ProbabilityTable() {
|
||||
for (const auto& entry : table) {
|
||||
for (size_t y = 0; y < entry.weight; y++) {
|
||||
this->push(entry.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void push(ItemT item) {
|
||||
if (this->count == MaxCount) {
|
||||
throw std::runtime_error("push to full probability table");
|
||||
}
|
||||
this->items[this->count++] = item;
|
||||
}
|
||||
|
||||
ItemT pop() {
|
||||
if (this->count == 0) {
|
||||
throw std::runtime_error("pop from empty probability table");
|
||||
}
|
||||
return this->items[--this->count];
|
||||
}
|
||||
|
||||
void shuffle(std::shared_ptr<RandomGenerator> rand_crypt) {
|
||||
for (size_t z = 1; z < this->count; z++) {
|
||||
size_t other_z = rand_crypt->next() % (z + 1);
|
||||
ItemT t = this->items[z];
|
||||
this->items[z] = this->items[other_z];
|
||||
this->items[other_z] = t;
|
||||
}
|
||||
}
|
||||
|
||||
ItemT sample(std::shared_ptr<RandomGenerator> rand_crypt) const {
|
||||
if (this->count == 0) {
|
||||
throw std::runtime_error("sample from empty probability table");
|
||||
} else if (this->count == 1) {
|
||||
return this->items[0];
|
||||
} else {
|
||||
return this->items[rand_crypt->next() % this->count];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ItemCreator::ItemCreator(
|
||||
std::shared_ptr<const CommonItemSet> common_item_set,
|
||||
std::shared_ptr<const RareItemSet> rare_item_set,
|
||||
std::shared_ptr<const ArmorRandomSet> armor_random_set,
|
||||
std::shared_ptr<const ToolRandomSet> tool_random_set,
|
||||
std::shared_ptr<const WeaponRandomSet> weapon_random_set,
|
||||
std::shared_ptr<const ArmorShopRandomSet> armor_random_set,
|
||||
std::shared_ptr<const ToolShopRandomSet> tool_random_set,
|
||||
std::shared_ptr<const WeaponShopRandomSet> weapon_random_set,
|
||||
std::shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set,
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table,
|
||||
std::shared_ptr<const ItemData::StackLimits> stack_limits,
|
||||
@@ -1059,13 +1105,7 @@ void ItemCreator::generate_armor_shop_armors(std::vector<ItemData>& shop, Episod
|
||||
}
|
||||
size_t table_index = this->get_table_index_for_armor_shop(player_level);
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
auto src_table = this->armor_random_set->get_armor_table(table_index);
|
||||
for (size_t z = 0; z < src_table.second; z++) {
|
||||
for (size_t y = 0; y < src_table.first[z].weight; y++) {
|
||||
pt.push(src_table.first[z].value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->armor_random_set->armor_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
for (size_t items_generated = 0; items_generated < num_items;) {
|
||||
@@ -1103,13 +1143,7 @@ void ItemCreator::generate_armor_shop_shields(std::vector<ItemData>& shop, size_
|
||||
}
|
||||
size_t table_index = this->get_table_index_for_armor_shop(player_level);
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
auto src_table = this->armor_random_set->get_shield_table(table_index);
|
||||
for (size_t z = 0; z < src_table.second; z++) {
|
||||
for (size_t y = 0; y < src_table.first[z].weight; y++) {
|
||||
pt.push(src_table.first[z].value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->armor_random_set->shield_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
for (size_t items_generated = 0; items_generated < num_items;) {
|
||||
@@ -1146,13 +1180,7 @@ void ItemCreator::generate_armor_shop_units(std::vector<ItemData>& shop, size_t
|
||||
}
|
||||
size_t table_index = this->get_table_index_for_armor_shop(player_level);
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
auto src_table = this->armor_random_set->get_unit_table(table_index);
|
||||
for (size_t z = 0; z < src_table.second; z++) {
|
||||
for (size_t y = 0; y < src_table.first[z].weight; y++) {
|
||||
pt.push(src_table.first[z].value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->armor_random_set->unit_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
for (size_t items_generated = 0; items_generated < num_items;) {
|
||||
@@ -1190,10 +1218,6 @@ size_t ItemCreator::get_table_index_for_tool_shop(size_t player_level) {
|
||||
}
|
||||
}
|
||||
|
||||
static const std::vector<std::pair<uint8_t, uint8_t>> tool_item_defs{
|
||||
{0x00, 0x00}, {0x00, 0x01}, {0x00, 0x02}, {0x01, 0x00}, {0x01, 0x01}, {0x01, 0x02}, {0x06, 0x00}, {0x06, 0x01},
|
||||
{0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x07, 0x00}, {0x08, 0x00}, {0x09, 0x00}, {0x0A, 0x00}, {0xFF, 0xFF}};
|
||||
|
||||
void ItemCreator::generate_common_tool_shop_recovery_items(std::vector<ItemData>& shop, size_t player_level) {
|
||||
size_t table_index;
|
||||
if (player_level < 11) {
|
||||
@@ -1210,17 +1234,15 @@ void ItemCreator::generate_common_tool_shop_recovery_items(std::vector<ItemData>
|
||||
table_index = 5;
|
||||
}
|
||||
|
||||
auto table = this->tool_random_set->get_common_recovery_table(table_index);
|
||||
for (size_t z = 0; z < table.second; z++) {
|
||||
uint8_t type = table.first[z];
|
||||
if (type == 0x0F) {
|
||||
for (const auto& entry : this->tool_random_set->common_recovery_table.at(table_index)) {
|
||||
if (entry == 0x0F) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& item = shop.emplace_back();
|
||||
item.data1[0] = 3;
|
||||
item.data1[1] = tool_item_defs[type].first;
|
||||
item.data1[2] = tool_item_defs[type].second;
|
||||
item.data1[1] = ToolShopRandomSet::item_defs[entry].first;
|
||||
item.data1[2] = ToolShopRandomSet::item_defs[entry].second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,15 +1252,8 @@ void ItemCreator::generate_rare_tool_shop_recovery_items(std::vector<ItemData>&
|
||||
}
|
||||
static constexpr size_t num_items = 2;
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
size_t table_index = this->get_table_index_for_tool_shop(player_level);
|
||||
auto table = this->tool_random_set->get_rare_recovery_table(table_index);
|
||||
for (size_t z = 0; z < table.second; z++) {
|
||||
const auto& e = table.first[z];
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->tool_random_set->rare_recovery_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
size_t effective_num_items = num_items;
|
||||
@@ -1252,8 +1267,8 @@ void ItemCreator::generate_rare_tool_shop_recovery_items(std::vector<ItemData>&
|
||||
} else {
|
||||
ItemData item;
|
||||
item.data1[0] = 3;
|
||||
item.data1[1] = tool_item_defs[type].first;
|
||||
item.data1[2] = tool_item_defs[type].second;
|
||||
item.data1[1] = ToolShopRandomSet::item_defs[type].first;
|
||||
item.data1[2] = ToolShopRandomSet::item_defs[type].second;
|
||||
if (this->shop_does_not_contain_duplicate_item_by_data1_0_1_2(shop, item)) {
|
||||
shop.emplace_back(std::move(item));
|
||||
items_generated++;
|
||||
@@ -1273,28 +1288,16 @@ void ItemCreator::generate_tool_shop_tech_disks(std::vector<ItemData>& shop, siz
|
||||
}
|
||||
|
||||
size_t table_index = this->get_table_index_for_tool_shop(player_level);
|
||||
auto table = this->tool_random_set->get_tech_disk_table(table_index);
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
for (size_t z = 0; z < table.second; z++) {
|
||||
const auto& e = table.first[z];
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->tool_random_set->tech_disk_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
static const std::array<uint8_t, 0x13> tech_num_map = {
|
||||
0x00, 0x03, 0x06, 0x0F, 0x10, 0x0D, 0x0A, 0x0B, 0x0C, 0x01, 0x04, 0x07,
|
||||
0x0E, 0x11, 0x02, 0x05, 0x08, 0x09, 0x12};
|
||||
|
||||
size_t items_generated = 0;
|
||||
while (items_generated < num_items) {
|
||||
uint8_t tech_num_index = pt.pop();
|
||||
ItemData item;
|
||||
item.data1[0] = 3;
|
||||
item.data1[1] = 2;
|
||||
item.data1[4] = tech_num_map.at(tech_num_index);
|
||||
item.data1[4] = ToolShopRandomSet::tech_num_map.at(tech_num_index);
|
||||
this->choose_tech_disk_level_for_tool_shop(item, player_level, tech_num_index);
|
||||
if (this->shop_does_not_contain_duplicate_tech_disk(shop, item)) {
|
||||
shop.emplace_back(std::move(item));
|
||||
@@ -1305,22 +1308,22 @@ void ItemCreator::generate_tool_shop_tech_disks(std::vector<ItemData>& shop, siz
|
||||
|
||||
void ItemCreator::choose_tech_disk_level_for_tool_shop(ItemData& item, size_t player_level, uint8_t tech_num_index) {
|
||||
size_t table_index = this->get_table_index_for_tool_shop(player_level);
|
||||
auto table = this->tool_random_set->get_tech_disk_level_table(table_index);
|
||||
if (tech_num_index >= table.second) {
|
||||
auto table = this->tool_random_set->tech_disk_level_table.at(table_index);
|
||||
if (tech_num_index >= table.size()) {
|
||||
throw std::runtime_error("technique number out of range");
|
||||
}
|
||||
const auto& e = table.first[tech_num_index];
|
||||
const auto& e = table[tech_num_index];
|
||||
|
||||
switch (e.mode) {
|
||||
case ToolRandomSet::TechDiskLevelEntry::Mode::LEVEL_1:
|
||||
case ToolShopRandomSet::TechDiskLevelEntry::Mode::LEVEL_1:
|
||||
item.data1[2] = 0;
|
||||
break;
|
||||
case ToolRandomSet::TechDiskLevelEntry::Mode::PLAYER_LEVEL_DIVISOR:
|
||||
case ToolShopRandomSet::TechDiskLevelEntry::Mode::PLAYER_LEVEL_DIVISOR:
|
||||
item.data1[2] = std::clamp<ssize_t>(
|
||||
(std::min<size_t>(player_level, 99) / e.player_level_divisor_or_min_level) - 1, 0, 14);
|
||||
break;
|
||||
case ToolRandomSet::TechDiskLevelEntry::Mode::RANDOM_IN_RANGE: {
|
||||
// Note: This logic does not give a uniform distribution - if the minimumlevel is not zero (level 1), then the
|
||||
case ToolShopRandomSet::TechDiskLevelEntry::Mode::RANDOM_IN_RANGE: {
|
||||
// Note: This logic does not give a uniform distribution - if the minimum level is not zero (level 1), then the
|
||||
// minimum level is more likely than all the other levels. This behavior matches the client's logic, though it's
|
||||
// unclear if this nonuniformity was intentional.
|
||||
int16_t min_level = std::max<int16_t>(e.player_level_divisor_or_min_level - 1, 0);
|
||||
@@ -1373,119 +1376,25 @@ std::vector<ItemData> ItemCreator::generate_weapon_shop_contents(size_t player_l
|
||||
}
|
||||
}
|
||||
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
auto table = this->weapon_random_set->get_weapon_type_table(table_index);
|
||||
for (size_t z = 0; z < table.second; z++) {
|
||||
const auto& e = table.first[z];
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint8_t, 100> pt{this->weapon_random_set->weapon_type_weight_tables.at(table_index).at(section_id)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
std::vector<ItemData> shop;
|
||||
while (shop.size() < num_items) {
|
||||
ItemData item;
|
||||
|
||||
const std::pair<uint8_t, uint8_t>* def;
|
||||
uint8_t which = pt.pop();
|
||||
if (which == 0x39) {
|
||||
static const std::vector<std::pair<uint8_t, uint8_t>> defs{
|
||||
{0x28, 0x00}, {0x2A, 0x00}, {0x2B, 0x00}, {0x35, 0x00}, {0x52, 0x00}, {0x48, 0x00}, {0x64, 0x00},
|
||||
{0x59, 0x00}, {0x8A, 0x00}, {0x99, 0x00}};
|
||||
const auto& def = defs.at(this->section_id);
|
||||
item.data1[0] = 0;
|
||||
item.data1[1] = def.first;
|
||||
item.data1[2] = def.second;
|
||||
|
||||
def = &WeaponShopRandomSet::type_defs_39.at(this->section_id);
|
||||
} else if (which == 0x3A) {
|
||||
static const std::vector<std::pair<uint8_t, uint8_t>> defs{
|
||||
{0x99, 0x00}, {0x64, 0x00}, {0x8A, 0x00}, {0x28, 0x00}, {0x59, 0x00}, {0x2B, 0x00}, {0x52, 0x00},
|
||||
{0x2A, 0x00}, {0x48, 0x00}, {0x35, 0x00}};
|
||||
const auto& def = defs.at(this->section_id);
|
||||
item.data1[0] = 0;
|
||||
item.data1[1] = def.first;
|
||||
item.data1[2] = def.second;
|
||||
|
||||
def = &WeaponShopRandomSet::type_defs_3A.at(this->section_id);
|
||||
} else {
|
||||
static const std::vector<std::pair<uint8_t, uint8_t>> defs({
|
||||
/* 00 */ {0x01, 0x00},
|
||||
/* 01 */ {0x01, 0x01},
|
||||
/* 02 */ {0x01, 0x02},
|
||||
/* 03 */ {0x01, 0x03},
|
||||
/* 04 */ {0x01, 0x04},
|
||||
/* 05 */ {0x03, 0x00},
|
||||
/* 06 */ {0x03, 0x01},
|
||||
/* 07 */ {0x03, 0x02},
|
||||
/* 08 */ {0x03, 0x03},
|
||||
/* 09 */ {0x03, 0x04},
|
||||
/* 0A */ {0x02, 0x00},
|
||||
/* 0B */ {0x02, 0x01},
|
||||
/* 0C */ {0x02, 0x02},
|
||||
/* 0D */ {0x02, 0x03},
|
||||
/* 0E */ {0x02, 0x04},
|
||||
/* 0F */ {0x05, 0x00},
|
||||
/* 10 */ {0x05, 0x01},
|
||||
/* 11 */ {0x05, 0x02},
|
||||
/* 12 */ {0x05, 0x03},
|
||||
/* 13 */ {0x05, 0x04},
|
||||
/* 14 */ {0x04, 0x00},
|
||||
/* 15 */ {0x04, 0x01},
|
||||
/* 16 */ {0x04, 0x02},
|
||||
/* 17 */ {0x04, 0x03},
|
||||
/* 18 */ {0x04, 0x04},
|
||||
/* 19 */ {0x06, 0x00},
|
||||
/* 1A */ {0x06, 0x01},
|
||||
/* 1B */ {0x06, 0x02},
|
||||
/* 1C */ {0x06, 0x03},
|
||||
/* 1D */ {0x06, 0x04},
|
||||
/* 1E */ {0x07, 0x00},
|
||||
/* 1F */ {0x07, 0x01},
|
||||
/* 20 */ {0x07, 0x02},
|
||||
/* 21 */ {0x07, 0x03},
|
||||
/* 22 */ {0x07, 0x04},
|
||||
/* 23 */ {0x08, 0x00},
|
||||
/* 24 */ {0x08, 0x01},
|
||||
/* 25 */ {0x08, 0x02},
|
||||
/* 26 */ {0x08, 0x03},
|
||||
/* 27 */ {0x08, 0x04},
|
||||
/* 28 */ {0x09, 0x00},
|
||||
/* 29 */ {0x09, 0x01},
|
||||
/* 2A */ {0x09, 0x02},
|
||||
/* 2B */ {0x09, 0x03},
|
||||
/* 2C */ {0x09, 0x04},
|
||||
/* 2D */ {0x0A, 0x00},
|
||||
/* 2E */ {0x0A, 0x01},
|
||||
/* 2F */ {0x0A, 0x02},
|
||||
/* 30 */ {0x0A, 0x03},
|
||||
/* 31 */ {0x0B, 0x00},
|
||||
/* 32 */ {0x0B, 0x01},
|
||||
/* 33 */ {0x0B, 0x02},
|
||||
/* 34 */ {0x0B, 0x03},
|
||||
/* 35 */ {0x0C, 0x00},
|
||||
/* 36 */ {0x0C, 0x01},
|
||||
/* 37 */ {0x0C, 0x02},
|
||||
/* 38 */ {0x0C, 0x03},
|
||||
/* 39 */ {0xFF, 0xFF}, // Special-cased above
|
||||
/* 3A */ {0xFF, 0xFF}, // Special-cased above
|
||||
/* 3B */ {0x01, 0x05},
|
||||
/* 3C */ {0x02, 0x05},
|
||||
/* 3D */ {0x06, 0x05},
|
||||
/* 3E */ {0x08, 0x05},
|
||||
/* 3F */ {0x0A, 0x04},
|
||||
/* 40 */ {0x0C, 0x04},
|
||||
/* 41 */ {0x0B, 0x04},
|
||||
/* 42 */ {0x01, 0x06},
|
||||
/* 43 */ {0x03, 0x05},
|
||||
/* 44 */ {0x07, 0x05},
|
||||
/* 45 */ {0x0A, 0x05},
|
||||
/* 46 */ {0x0C, 0x05},
|
||||
/* 47 */ {0x0B, 0x05},
|
||||
});
|
||||
const auto& def = defs.at(which);
|
||||
item.data1[0] = 0;
|
||||
item.data1[1] = def.first;
|
||||
item.data1[2] = def.second;
|
||||
def = &WeaponShopRandomSet::type_defs.at(which);
|
||||
}
|
||||
item.data1[0] = 0;
|
||||
item.data1[1] = def->first;
|
||||
item.data1[2] = def->second;
|
||||
|
||||
this->generate_weapon_shop_item_grind(item, player_level);
|
||||
this->generate_weapon_shop_item_special(item, player_level);
|
||||
@@ -1519,18 +1428,17 @@ void ItemCreator::generate_weapon_shop_item_grind(ItemData& item, size_t player_
|
||||
table_index = 5;
|
||||
}
|
||||
|
||||
uint8_t favored_weapon = favored_weapon_by_section_id.at(this->section_id);
|
||||
uint8_t favored_weapon = TekkerAdjustmentSet::favored_weapon_type_for_section_id(this->section_id);
|
||||
bool is_favored = (favored_weapon != 0xFF) && (item.data1[1] == favored_weapon);
|
||||
const auto* range = is_favored
|
||||
? this->weapon_random_set->get_favored_grind_range(table_index)
|
||||
: this->weapon_random_set->get_standard_grind_range(table_index);
|
||||
const auto& range = is_favored
|
||||
? this->weapon_random_set->favored_grind_range_table.at(table_index)
|
||||
: this->weapon_random_set->default_grind_range_table.at(table_index);
|
||||
|
||||
const auto& weapon_def = this->item_parameter_table->get_weapon(item.data1[1], item.data1[2]);
|
||||
item.data1[3] = std::clamp<uint8_t>(this->rand_int(range->max + 1), range->min, weapon_def.max_grind);
|
||||
item.data1[3] = std::clamp<uint8_t>(this->rand_int(range.max + 1), range.min, weapon_def.max_grind);
|
||||
}
|
||||
|
||||
void ItemCreator::generate_weapon_shop_item_special(ItemData& item, size_t player_level) {
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
|
||||
size_t table_index;
|
||||
if (player_level < 11) {
|
||||
@@ -1551,13 +1459,8 @@ void ItemCreator::generate_weapon_shop_item_special(ItemData& item, size_t playe
|
||||
table_index = 7;
|
||||
}
|
||||
|
||||
const auto* table = this->weapon_random_set->get_special_mode_table(table_index);
|
||||
for (size_t z = 0; z < table->size(); z++) {
|
||||
const auto& e = table->at(z);
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint32_t, 100> pt{this->weapon_random_set->special_mode_table.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
// Note: The original code shuffles pt and then pops a single value from it. For simplicity, we just sample a single
|
||||
// value instead.
|
||||
@@ -1576,9 +1479,6 @@ void ItemCreator::generate_weapon_shop_item_special(ItemData& item, size_t playe
|
||||
}
|
||||
}
|
||||
|
||||
static const std::array<int8_t, 20> bonus_values = {
|
||||
-50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
|
||||
|
||||
void ItemCreator::generate_weapon_shop_item_bonus1(ItemData& item, size_t player_level) {
|
||||
size_t table_index;
|
||||
if (player_level < 4) {
|
||||
@@ -1601,14 +1501,8 @@ void ItemCreator::generate_weapon_shop_item_bonus1(ItemData& item, size_t player
|
||||
table_index = 8;
|
||||
}
|
||||
|
||||
const auto* type_table = this->weapon_random_set->get_bonus_type_table(0, table_index);
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
for (size_t z = 0; z < type_table->size(); z++) {
|
||||
const auto& e = type_table->at(z);
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint32_t, 100> pt{this->weapon_random_set->bonus_type_table1.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
// Note: The original code shuffles pt and then pops a single value from it. For simplicity, we just sample a single
|
||||
// value instead.
|
||||
@@ -1616,8 +1510,8 @@ void ItemCreator::generate_weapon_shop_item_bonus1(ItemData& item, size_t player
|
||||
if (item.data1[6] == 0) {
|
||||
item.data1[7] = 0;
|
||||
} else {
|
||||
const auto* range = this->weapon_random_set->get_bonus_range(0, table_index);
|
||||
item.data1[7] = bonus_values.at(std::max<size_t>(this->rand_int(range->max + 1), range->min));
|
||||
const auto& range = this->weapon_random_set->bonus_range_table1.at(table_index);
|
||||
item.data1[7] = WeaponShopRandomSet::bonus_values.at(std::max<size_t>(this->rand_int(range.max + 1), range.min));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1643,14 +1537,7 @@ void ItemCreator::generate_weapon_shop_item_bonus2(ItemData& item, size_t player
|
||||
table_index = 8;
|
||||
}
|
||||
|
||||
const auto* type_table = this->weapon_random_set->get_bonus_type_table(1, table_index);
|
||||
ProbabilityTable<uint8_t, 100> pt;
|
||||
for (size_t z = 0; z < type_table->size(); z++) {
|
||||
const auto& e = type_table->at(z);
|
||||
for (size_t y = 0; y < e.weight; y++) {
|
||||
pt.push(e.value);
|
||||
}
|
||||
}
|
||||
ProbabilityTable<uint32_t, 100> pt{this->weapon_random_set->bonus_type_table2.at(table_index)};
|
||||
pt.shuffle(this->rand_crypt);
|
||||
|
||||
do {
|
||||
@@ -1660,8 +1547,8 @@ void ItemCreator::generate_weapon_shop_item_bonus2(ItemData& item, size_t player
|
||||
if (item.data1[8] == 0) {
|
||||
item.data1[9] = 0;
|
||||
} else {
|
||||
const auto* range = this->weapon_random_set->get_bonus_range(1, table_index);
|
||||
item.data1[9] = bonus_values.at(std::max<size_t>(this->rand_int(range->max + 1), range->min));
|
||||
const auto& range = this->weapon_random_set->bonus_range_table2.at(table_index);
|
||||
item.data1[9] = WeaponShopRandomSet::bonus_values.at(std::max<size_t>(this->rand_int(range.max + 1), range.min));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1724,56 +1611,61 @@ ssize_t ItemCreator::apply_tekker_deltas(ItemData& item, uint8_t section_id) {
|
||||
throw std::runtime_error("tekker deltas can only be applied to weapons");
|
||||
}
|
||||
|
||||
static const std::array<int8_t, 11> delta_table = {-10, -5, -3, -2, -1, 0, 1, 2, 3, 5, 10};
|
||||
|
||||
bool favored = item.data1[1] == favored_weapon_by_section_id[section_id];
|
||||
bool favored = (item.data1[1] == TekkerAdjustmentSet::favored_weapon_type_for_section_id(section_id));
|
||||
ssize_t luck = 0;
|
||||
|
||||
this->log.info_f("Applying tekker deltas for {} weapon", favored ? "favored" : "non-favored");
|
||||
|
||||
auto sample_prob_table = [this](const TekkerAdjustmentSet::Table& table) -> int8_t {
|
||||
size_t sample = this->rand_crypt->next() % table.total;
|
||||
for (const auto& [k, v] : table.probs) {
|
||||
if (sample < v) {
|
||||
return k;
|
||||
}
|
||||
sample -= v;
|
||||
}
|
||||
throw std::logic_error("Table total is incorrect");
|
||||
};
|
||||
|
||||
// Adjust the weapon's special
|
||||
{
|
||||
const auto& prob_table = this->tekker_adjustment_set->get_special_upgrade_prob_table(section_id, favored);
|
||||
uint8_t delta_index = prob_table.sample(this->rand_crypt);
|
||||
int8_t delta = delta_table.at(delta_index);
|
||||
this->log.info_f("(Special) Delta index {}, delta {}", delta_index, delta);
|
||||
// Note: The original code checks specifically for -1 and +1 here, but the data files only include delta_indexes 4,
|
||||
// 5, and 6 (which correspond to -1, 0, and 1) anyway, so we just check for positive and negative numbers instead.
|
||||
// When using the original JudgeItem.rel file, the behavior should be the same, but this feels more correct.
|
||||
try {
|
||||
uint8_t new_special;
|
||||
if (delta < 0) {
|
||||
new_special = item.data1[4] - 1;
|
||||
} else if (delta > 0) {
|
||||
new_special = item.data1[4] + 1;
|
||||
} else {
|
||||
new_special = item.data1[4];
|
||||
}
|
||||
if (new_special != item.data1[4]) {
|
||||
int8_t delta = sample_prob_table(favored
|
||||
? this->tekker_adjustment_set->favored_special_delta_table[section_id]
|
||||
: this->tekker_adjustment_set->default_special_delta_table[section_id]);
|
||||
this->log.info_f("(Special) Delta {} chosen", delta);
|
||||
for (; delta != 0; delta += (delta < 0) - (0 < delta)) {
|
||||
try {
|
||||
// Note: The original code checks specifically for -1 and +1 here and only increments or decrements the special
|
||||
// by 1, and the data files only include delta_indexes 4, 5, and 6 (which correspond to -1, 0, and 1). But we
|
||||
// want to support other levels of delta indexes, so we simply add delta instead. When using the original
|
||||
// JudgeItem.rel file, the behavior should be the same, but this logic feels more correct.
|
||||
uint8_t new_special = item.data1[4] + delta;
|
||||
if (this->item_parameter_table->get_special(item.data1[4]).type ==
|
||||
this->item_parameter_table->get_special(new_special).type) {
|
||||
item.data1[4] = new_special;
|
||||
this->log.info_f("(Special) Delta {} applied", delta);
|
||||
break;
|
||||
} else {
|
||||
this->log.info_f("(Special) Delta canceled because it would change special category");
|
||||
this->log.info_f("(Special) Delta {} canceled because it would change special category", delta);
|
||||
}
|
||||
} catch (const std::out_of_range&) {
|
||||
// Invalid special number passed to get_special; treat it as if delta == 0
|
||||
}
|
||||
} catch (const std::out_of_range&) {
|
||||
// Invalid special number passed to get_special; just ignore it
|
||||
}
|
||||
luck += this->tekker_adjustment_set->get_luck_for_special_upgrade(delta_index);
|
||||
luck += this->tekker_adjustment_set->special_luck_table.at(delta);
|
||||
this->log.info_f("(Special) Luck is now {}", luck);
|
||||
}
|
||||
|
||||
// Adjust the weapon's grind if it's not rare
|
||||
if (!this->item_parameter_table->is_item_rare(item)) {
|
||||
const auto& weapon_def = this->item_parameter_table->get_weapon(item.data1[1], item.data1[2]);
|
||||
const auto& prob_table = this->tekker_adjustment_set->get_grind_delta_prob_table(section_id, favored);
|
||||
uint8_t delta_index = prob_table.sample(this->rand_crypt);
|
||||
int8_t delta = delta_table.at(delta_index);
|
||||
this->log.info_f("(Grind) Delta index {}, delta {}", delta_index, delta);
|
||||
int8_t delta = sample_prob_table(favored
|
||||
? this->tekker_adjustment_set->favored_grind_delta_table[section_id]
|
||||
: this->tekker_adjustment_set->default_grind_delta_table[section_id]);
|
||||
this->log.info_f("(Grind) Delta {} chosen", delta);
|
||||
int16_t new_grind = static_cast<int16_t>(item.data1[3]) + static_cast<int16_t>(delta);
|
||||
item.data1[3] = std::clamp<int16_t>(new_grind, 0, weapon_def.max_grind);
|
||||
luck += this->tekker_adjustment_set->get_luck_for_grind_delta(delta_index);
|
||||
luck += this->tekker_adjustment_set->grind_luck_table.at(delta);
|
||||
this->log.info_f("(Grind) Luck is now {}", luck);
|
||||
} else {
|
||||
this->log.info_f("(Grind) Item is rare; skipping grind adjustment");
|
||||
@@ -1781,11 +1673,10 @@ ssize_t ItemCreator::apply_tekker_deltas(ItemData& item, uint8_t section_id) {
|
||||
|
||||
// Adjust the weapon's bonuses
|
||||
{
|
||||
const auto& prob_table = this->tekker_adjustment_set->get_bonus_delta_prob_table(section_id, favored);
|
||||
// Note: The original code really does use the same delta for all three bonuses.
|
||||
uint8_t delta_index = prob_table.sample(this->rand_crypt);
|
||||
int8_t delta = delta_table.at(delta_index);
|
||||
this->log.info_f("(Bonuses) Delta index {}, delta {}", delta_index, delta);
|
||||
int8_t delta = sample_prob_table(favored
|
||||
? this->tekker_adjustment_set->favored_bonus_delta_table[section_id]
|
||||
: this->tekker_adjustment_set->default_bonus_delta_table[section_id]);
|
||||
this->log.info_f("(Bonuses) Delta {} chosen", delta);
|
||||
// Note: The original code doesn't check if there's actually a bonus in each slot before incrementing the values.
|
||||
// Presumably there's a check later that will clear any invalid bonuses, but we don't have such a check, so we need
|
||||
// to check here if each bonus is actually present.
|
||||
@@ -1794,7 +1685,7 @@ ssize_t ItemCreator::apply_tekker_deltas(ItemData& item, uint8_t section_id) {
|
||||
item.data1[z + 1] = std::min<int8_t>(item.data1[z + 1] + delta, 100);
|
||||
}
|
||||
}
|
||||
luck += this->tekker_adjustment_set->get_luck_for_bonus_delta(delta_index);
|
||||
luck += this->tekker_adjustment_set->bonus_luck_table.at(delta);
|
||||
this->log.info_f("(Bonuses) Luck is now {}", luck);
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -7,7 +7,9 @@
|
||||
#include "PSOEncryption.hh"
|
||||
#include "PlayerSubordinates.hh"
|
||||
#include "RareItemSet.hh"
|
||||
#include "ShopRandomSets.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "TekkerAdjustmentSet.hh"
|
||||
|
||||
// This file and ItemCreator.cc are essentially a direct reverse-engineering of the item creation algorithm in PSO GC.
|
||||
// Only minor changes have been made to support BB (as described in the comments in the implementation) and to support
|
||||
@@ -19,9 +21,9 @@ public:
|
||||
ItemCreator(
|
||||
std::shared_ptr<const CommonItemSet> common_item_set,
|
||||
std::shared_ptr<const RareItemSet> rare_item_set,
|
||||
std::shared_ptr<const ArmorRandomSet> armor_random_set,
|
||||
std::shared_ptr<const ToolRandomSet> tool_random_set,
|
||||
std::shared_ptr<const WeaponRandomSet> weapon_random_set,
|
||||
std::shared_ptr<const ArmorShopRandomSet> armor_random_set,
|
||||
std::shared_ptr<const ToolShopRandomSet> tool_random_set,
|
||||
std::shared_ptr<const WeaponShopRandomSet> weapon_random_set,
|
||||
std::shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set,
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table,
|
||||
std::shared_ptr<const ItemData::StackLimits> stack_limits,
|
||||
@@ -84,9 +86,9 @@ private:
|
||||
Difficulty difficulty;
|
||||
uint8_t section_id;
|
||||
std::shared_ptr<const RareItemSet> rare_item_set;
|
||||
std::shared_ptr<const ArmorRandomSet> armor_random_set;
|
||||
std::shared_ptr<const ToolRandomSet> tool_random_set;
|
||||
std::shared_ptr<const WeaponRandomSet> weapon_random_set;
|
||||
std::shared_ptr<const ArmorShopRandomSet> armor_random_set;
|
||||
std::shared_ptr<const ToolShopRandomSet> tool_random_set;
|
||||
std::shared_ptr<const WeaponShopRandomSet> weapon_random_set;
|
||||
std::shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set;
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table;
|
||||
std::shared_ptr<const CommonItemSet> common_item_set;
|
||||
|
||||
@@ -142,6 +142,26 @@ public:
|
||||
uint16_t feed_table = 0;
|
||||
uint8_t photon_blast = 0;
|
||||
uint8_t activation = 0;
|
||||
// Internally, when a mag effect is about to activate, the game computes a byte with the following flags:
|
||||
// 01 = HP low (causes effect in mag's on_low_hp if eligible, priority 2)
|
||||
// 02 = died (causes effect in mag's on_death if eligible, priority 3)
|
||||
// 04 = synchro < 30 (causes effect 5, priority 7)
|
||||
// 08 = synchro > 100 (causes effect 4, priority 8)
|
||||
// 10 = TODO (3OE1:80112B24) (causes effect 3, priority 6)
|
||||
// 20 = player leveled up (causes effect 2, priority 5)
|
||||
// 40 = PB meter filled (causes effect in mag's on_pb_full if eligible, priority 1)
|
||||
// 80 = entered boss arena (causes effect in mag's on_boss if eligible, priority 4)
|
||||
// Values for on_* trigger fields:
|
||||
// 0 = no effect
|
||||
// 1 = TODO (used internally; not synced via 6x61; possibly just cancel previous effect?)
|
||||
// 2 = TODO (used internally; seems to be effect 1, but delayed by 45 frames?)
|
||||
// 3 = TODO (used internally; seems to be effect 1, but delayed by 90 frames?)
|
||||
// 4 = Shifta + Deband (level = (IQ / 40) + 1; delayed by 90 frames)
|
||||
// 5 = TODO (used internally; seems to be effect 1, but delayed by 90 frames?)
|
||||
// 6 = Resta (not synced via 6x61; level = (IQ / 40) + 1; delayed by 90 frames)
|
||||
// 7 = Reverser (not synced via 6x61; delayed by 90 frames)
|
||||
// 8 = invincibility (duration = (((IQ + synchro) / 3) + 40) * 30 frames, but this is capped at 30 seconds, so in
|
||||
// practice it's always just 30 seconds regardless of IQ and synchro)
|
||||
uint8_t on_pb_full = 0;
|
||||
uint8_t on_low_hp = 0;
|
||||
uint8_t on_death = 0;
|
||||
|
||||
+4
-4
@@ -131,7 +131,7 @@ void player_use_item(std::shared_ptr<Client> c, size_t item_index, std::shared_p
|
||||
|
||||
} else if ((primary_identifier & 0xFFFF0000) == 0x030C0000) { // Non-combo mag cells
|
||||
auto& mag = player->inventory.items[player->inventory.find_equipped_item(EquipSlot::MAG)];
|
||||
uint8_t evolution_number = s->mag_evolution_table(c->version())->get_evolution_number(mag.data.data1[1]);
|
||||
uint8_t evolution_number = s->mag_metadata_table(c->version())->get_evolution_number(mag.data.data1[1]);
|
||||
if (evolution_number < 4) {
|
||||
switch (item.data.data1[2]) {
|
||||
case 0x00: // Cell of MAG 502
|
||||
@@ -268,7 +268,7 @@ void apply_mag_feed_result(
|
||||
ItemData& mag_item,
|
||||
const ItemData& fed_item,
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table,
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table,
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table,
|
||||
uint8_t char_class,
|
||||
uint8_t section_id,
|
||||
bool version_has_rare_mags) {
|
||||
@@ -314,7 +314,7 @@ void apply_mag_feed_result(
|
||||
|
||||
uint8_t mag_level = mag_item.compute_mag_level();
|
||||
mag_item.data1[2] = mag_level;
|
||||
uint8_t evolution_number = mag_evolution_table->get_evolution_number(mag_item.data1[1]);
|
||||
uint8_t evolution_number = mag_metadata_table->get_evolution_number(mag_item.data1[1]);
|
||||
uint8_t mag_number = mag_item.data1[1];
|
||||
|
||||
// Note: Sega really did just hardcode all these rules into the client. There is no data file describing these
|
||||
@@ -489,7 +489,7 @@ void player_feed_mag(std::shared_ptr<Client> c, size_t mag_item_index, size_t fe
|
||||
player->inventory.items[mag_item_index].data,
|
||||
player->inventory.items[fed_item_index].data,
|
||||
s->item_parameter_table(c->version()),
|
||||
s->mag_evolution_table(c->version()),
|
||||
s->mag_metadata_table(c->version()),
|
||||
player->disp.visual.sh.char_class,
|
||||
player->disp.visual.sh.section_id,
|
||||
!is_v1_or_v2(c->version()));
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ void apply_mag_feed_result(
|
||||
ItemData& mag_item,
|
||||
const ItemData& fed_item,
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table,
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table,
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table,
|
||||
uint8_t char_class,
|
||||
uint8_t section_id,
|
||||
bool version_has_rare_mags);
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
#include "MagEvolutionTable.hh"
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
|
||||
template <bool BE>
|
||||
struct MotionReferenceTables {
|
||||
// It seems that there are two definition tables, but only the first is used on any version of PSO. On v3 and later,
|
||||
// the two offsets point to the same table, but on v2 they don't and the second table contains different data.
|
||||
// TODO: Figure out what the deal is with the different v2 tables.
|
||||
U32T<BE> ref_table;
|
||||
U32T<BE> unused_ref_table;
|
||||
} __packed_ws_be__(MotionReferenceTables, 0x08);
|
||||
|
||||
template <bool BE>
|
||||
struct ColorEntry {
|
||||
// Colors are specified as 4 floats, each in the range [0, 1], for each color channel. The default colors are:
|
||||
// alpha red green blue color (see StaticGameData.cc)
|
||||
// 00 => 1.0 1.0 0.2 0.1 red
|
||||
// 01 => 1.0 0.2 0.2 1.0 blue
|
||||
// 02 => 1.0 1.0 0.9 0.1 yellow
|
||||
// 03 => 1.0 0.1 1.0 0.1 green
|
||||
// 04 => 1.0 0.8 0.1 1.0 purple
|
||||
// 05 => 1.0 0.1 0.1 0.2 black
|
||||
// 06 => 1.0 0.9 1.0 1.0 white
|
||||
// 07 => 1.0 0.1 0.9 1.0 cyan
|
||||
// 08 => 1.0 0.5 0.3 0.2 brown
|
||||
// 09 => 1.0 1.0 0.4 0.0 orange (v3+)
|
||||
// 0A => 1.0 0.502 0.545 0.977 light-blue (v3+)
|
||||
// 0B => 1.0 0.502 0.502 0.0 olive (v3+)
|
||||
// 0C => 1.0 0.0 0.941 0.714 turquoise (v3+)
|
||||
// 0D => 1.0 0.8 0.098 0.392 fuchsia (v3+)
|
||||
// 0E => 1.0 0.498 0.498 0.498 grey (v3+)
|
||||
// 0F => 1.0 0.996 0.996 0.832 cream (v3+)
|
||||
// 10 => 1.0 0.996 0.498 0.784 pink (v3+)
|
||||
// 11 => 1.0 0.0 0.498 0.322 dark-green (v3+)
|
||||
// If a mag's color index is invalid (>= 0x12), it is reassigned at equip time using the following logic:
|
||||
// - Set base_index to player->visual.skin if player is an android, or player->visual.costume otherwise
|
||||
// - If (base_index % 9) < 7 (that is, if their costume or body color is one of the colored slots on the character
|
||||
// creation screen), then set the mag color to either (base_index % 9) or (base_index % 9) + 9, with equal
|
||||
// probability.
|
||||
// - If (base_index % 9) >= 7 (that is, if their costume or body color is one of the last two blank-colored slots
|
||||
// on the character creation screen), then set the mag color to any of the available colors, chosen at random.
|
||||
F32T<BE> alpha;
|
||||
F32T<BE> red;
|
||||
F32T<BE> green;
|
||||
F32T<BE> blue;
|
||||
ColorEntry(const VectorXYZTF& c) : alpha(c.t), red(c.x), green(c.y), blue(c.z) {}
|
||||
operator VectorXYZTF() const {
|
||||
return VectorXYZTF{this->red.load(), this->green.load(), this->blue.load(), this->alpha.load()};
|
||||
}
|
||||
} __packed_ws_be__(ColorEntry, 0x10);
|
||||
|
||||
template <bool BE>
|
||||
struct UnknownA3EntryT {
|
||||
uint8_t flags;
|
||||
uint8_t unknown_a2;
|
||||
U16T<BE> unknown_a3;
|
||||
U16T<BE> unknown_a4;
|
||||
U16T<BE> unknown_a5;
|
||||
UnknownA3EntryT(const MagEvolutionTable::UnknownA3Entry& e)
|
||||
: flags(e.flags),
|
||||
unknown_a2(e.unknown_a2),
|
||||
unknown_a3(e.unknown_a3),
|
||||
unknown_a4(e.unknown_a4),
|
||||
unknown_a5(e.unknown_a5) {}
|
||||
operator MagEvolutionTable::UnknownA3Entry() const {
|
||||
return MagEvolutionTable::UnknownA3Entry{
|
||||
this->flags, this->unknown_a2, this->unknown_a3, this->unknown_a4, this->unknown_a5};
|
||||
}
|
||||
} __packed_ws_be__(UnknownA3EntryT, 0x08);
|
||||
|
||||
struct HeaderV1 {
|
||||
parray<uint8_t, 4> unknown_a1 = {0x0F, 0xF0, 0x00, 0x00};
|
||||
le_uint32_t unknown_a2 = 0x00000003;
|
||||
le_uint16_t unknown_a3 = 0x00C8;
|
||||
le_uint16_t unknown_a4 = 0x0078;
|
||||
// unknown_a5 added in V2
|
||||
le_float unknown_a6 = 0.25;
|
||||
le_float unknown_a7 = 0.1;
|
||||
le_uint32_t unknown_a8 = 0x00000C00;
|
||||
} __packed_ws__(HeaderV1, 0x18);
|
||||
|
||||
template <bool BE>
|
||||
struct HeaderV2V3V4 {
|
||||
parray<uint8_t, 4> unknown_a1 = {0x0F, 0xF0, 0x00, 0x00};
|
||||
U32T<BE> unknown_a2 = 0x00000003;
|
||||
U16T<BE> unknown_a3 = 0x00C8;
|
||||
U16T<BE> unknown_a4 = 0x0078;
|
||||
parray<uint8_t, 4> unknown_a5 = {0xC8, 0x00, 0x00, 0x00};
|
||||
F32T<BE> unknown_a6 = 0.25;
|
||||
F32T<BE> unknown_a7 = 0.1;
|
||||
U32T<BE> unknown_a8 = 0x00000C00;
|
||||
} __packed_ws_be__(HeaderV2V3V4, 0x1C);
|
||||
|
||||
// Fields:
|
||||
// 112K / V1 / V2 / V3 / BB R
|
||||
// 0018 / 0018 / 001C / 001C / 001C motion_tables.ref_table // -> MotionReference[NumMags]
|
||||
// 0228 / 0228 / 02D4 / 001C / 001C motion_tables.unused_ref_table // -> MotionReference[NumMags]
|
||||
// 0438 / 0438 / 05BC / 0340 / 0400 * motion_tables; // -> MotionReferenceTables
|
||||
// 0440 / 0440 / 0594 / 0348 / 0408 * unknown_a2; // -> (uint8_t[2])[NumMags] (references into unknown_a3)
|
||||
// 0498 / 0498 / 0608 / 03CE / 04AE * unknown_a3; // -> UnknownA3Entry[max(unknown_a2) + 1]
|
||||
// 0510 / 0520 / 06B0 / 0476 / 0556 * unknown_a4; // -> uint8_t[NumMags]
|
||||
// 053C / 054C / 06EC / 04BC / 05AC * color_table; // -> ColorEntry[NumColors]
|
||||
// ---- / ---- / 077C / 05DC / 06CC * evolution_number_table; // -> uint8_t[NumMags]
|
||||
|
||||
template <bool BE>
|
||||
struct RootV1 {
|
||||
U32T<BE> motion_tables;
|
||||
U32T<BE> unknown_a2;
|
||||
U32T<BE> unknown_a3;
|
||||
U32T<BE> unknown_a4;
|
||||
U32T<BE> color_table;
|
||||
} __packed_ws_be__(RootV1, 0x14);
|
||||
|
||||
template <bool BE>
|
||||
struct RootV2V3V4 : RootV1<BE> {
|
||||
U32T<BE> evolution_number_table;
|
||||
} __packed_ws_be__(RootV2V3V4, 0x18);
|
||||
|
||||
static uint8_t get_v1_mag_evolution_number(uint8_t data1_1) {
|
||||
static const std::array<uint8_t, 0x2C> v1_evolution_number_table{
|
||||
/* 00 */ 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 2,
|
||||
/* 10 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 2, 3, 4, 3, 3,
|
||||
/* 20 */ 3, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 4};
|
||||
if (data1_1 >= v1_evolution_number_table.size()) {
|
||||
throw std::runtime_error("invalid mag number");
|
||||
}
|
||||
return v1_evolution_number_table[data1_1];
|
||||
}
|
||||
|
||||
template <typename HeaderT, typename RootT, size_t NumMags, size_t NumColors, bool BE>
|
||||
class BinaryMagEvolutionTableT : public MagEvolutionTable {
|
||||
public:
|
||||
explicit BinaryMagEvolutionTableT(std::shared_ptr<const std::string> data)
|
||||
: data(data), r(*data), root(&r.pget<RootT>(this->r.pget_u32l(this->data->size() - 0x10))) {}
|
||||
virtual ~BinaryMagEvolutionTableT() = default;
|
||||
|
||||
template <typename RawT, typename ParsedT>
|
||||
const ParsedT& add_to_vector_cache(std::vector<ParsedT>& cache, size_t base_offset, size_t index) const {
|
||||
while (cache.size() <= index) {
|
||||
cache.emplace_back(this->r.pget<RawT>(base_offset + sizeof(RawT) * cache.size()));
|
||||
}
|
||||
return cache[index];
|
||||
}
|
||||
|
||||
virtual size_t num_mags() const {
|
||||
return NumMags;
|
||||
}
|
||||
|
||||
virtual size_t num_motion_entries(bool use_second_table) const {
|
||||
const auto& tables = this->r.pget<MotionReferenceTables<BE>>(this->root->motion_tables);
|
||||
return get_rel_array_count<MotionReference>(
|
||||
this->all_start_offsets(), use_second_table ? tables.unused_ref_table : tables.ref_table);
|
||||
}
|
||||
|
||||
virtual const MotionReference& get_motion_reference(bool use_second_table, size_t index) const {
|
||||
if (index >= this->num_motion_entries(use_second_table)) {
|
||||
throw std::logic_error("Invalid motion reference index");
|
||||
}
|
||||
const auto& tables = this->r.pget<MotionReferenceTables<BE>>(this->root->motion_tables);
|
||||
uint32_t array_offset = use_second_table ? tables.unused_ref_table : tables.ref_table;
|
||||
return this->r.pget<MotionReference>(array_offset + sizeof(MotionReference) * index);
|
||||
}
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t index) const {
|
||||
if (index >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid unknown_a2 index");
|
||||
}
|
||||
uint32_t base_offset = this->root->unknown_a2 + (index * 2);
|
||||
return std::make_pair(this->r.pget_u8(base_offset), this->r.pget_u8(base_offset + 1));
|
||||
}
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const {
|
||||
return get_rel_array_count<UnknownA3EntryT<BE>>(this->all_start_offsets(), this->root->unknown_a3);
|
||||
}
|
||||
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t index) const {
|
||||
if (index >= this->num_unknown_a3_entries()) {
|
||||
throw std::logic_error("Invalid unknown_a2 index");
|
||||
}
|
||||
return this->add_to_vector_cache<UnknownA3EntryT<BE>>(this->unknown_a3_entries, this->root->unknown_a3, index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_unknown_a4(size_t index) const {
|
||||
if (index >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid unknown_a4 index");
|
||||
}
|
||||
return this->r.pget_u8(this->root->unknown_a2 + index);
|
||||
}
|
||||
|
||||
virtual size_t num_colors() const {
|
||||
return NumColors;
|
||||
}
|
||||
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t index) const {
|
||||
if (index >= NumColors) {
|
||||
throw std::runtime_error("invalid mag color index");
|
||||
}
|
||||
return this->add_to_vector_cache<ColorEntry<BE>>(this->colors, this->root->color_table, index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const {
|
||||
if (data1_1 >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid unknown_a4 index");
|
||||
}
|
||||
if constexpr (requires { this->root->evolution_number_table; }) {
|
||||
return this->r.pget_u8(this->root->evolution_number_table + data1_1);
|
||||
} else {
|
||||
return get_v1_mag_evolution_number(data1_1);
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<uint32_t>& all_start_offsets() const {
|
||||
if (this->start_offsets.empty()) {
|
||||
this->start_offsets = all_relocation_offsets_for_rel_file<BE>(r.pgetv(0, r.size()), r.size());
|
||||
}
|
||||
return this->start_offsets;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const std::string> data;
|
||||
phosg::StringReader r;
|
||||
const RootT* root;
|
||||
mutable std::set<uint32_t> start_offsets;
|
||||
mutable std::vector<UnknownA3Entry> unknown_a3_entries;
|
||||
mutable std::vector<VectorXYZTF> colors;
|
||||
};
|
||||
|
||||
class MagEvolutionTableDCNTE : public MagEvolutionTable {
|
||||
public:
|
||||
MagEvolutionTableDCNTE() = default;
|
||||
virtual ~MagEvolutionTableDCNTE() = default;
|
||||
|
||||
virtual size_t num_mags() const {
|
||||
return 0x2C;
|
||||
}
|
||||
|
||||
virtual size_t num_motion_entries(bool) const {
|
||||
return 0;
|
||||
}
|
||||
virtual const MotionReference& get_motion_reference(bool, size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const {
|
||||
return 0;
|
||||
}
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual uint8_t get_unknown_a4(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual size_t num_colors() const {
|
||||
return 0;
|
||||
}
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const {
|
||||
return get_v1_mag_evolution_number(data1_1);
|
||||
}
|
||||
};
|
||||
|
||||
using MagEvolutionTableDC112000 = BinaryMagEvolutionTableT<HeaderV1, RootV1<false>, 0x28, 0x09, false>;
|
||||
using MagEvolutionTableV1 = BinaryMagEvolutionTableT<HeaderV1, RootV1<false>, 0x28, 0x09, false>;
|
||||
using MagEvolutionTableV2 = BinaryMagEvolutionTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x3A, 0x09, false>;
|
||||
using MagEvolutionTableGCNTE = BinaryMagEvolutionTableT<HeaderV2V3V4<true>, RootV2V3V4<true>, 0x3A, 0x09, true>;
|
||||
using MagEvolutionTableGC = BinaryMagEvolutionTableT<HeaderV2V3V4<true>, RootV2V3V4<true>, 0x43, 0x12, true>;
|
||||
using MagEvolutionTableXB = BinaryMagEvolutionTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x43, 0x12, false>;
|
||||
using MagEvolutionTableV4 = BinaryMagEvolutionTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x53, 0x12, false>;
|
||||
|
||||
std::shared_ptr<MagEvolutionTable> MagEvolutionTable::create(
|
||||
std::shared_ptr<const std::string> data, Version version) {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
return std::make_shared<MagEvolutionTableDCNTE>();
|
||||
case Version::DC_11_2000:
|
||||
return std::make_shared<MagEvolutionTableDC112000>(data);
|
||||
case Version::DC_V1:
|
||||
return std::make_shared<MagEvolutionTableV1>(data);
|
||||
case Version::DC_V2:
|
||||
case Version::PC_NTE:
|
||||
case Version::PC_V2:
|
||||
return std::make_shared<MagEvolutionTableV2>(data);
|
||||
case Version::GC_NTE:
|
||||
return std::make_shared<MagEvolutionTableGCNTE>(data);
|
||||
case Version::GC_V3:
|
||||
case Version::GC_EP3:
|
||||
case Version::GC_EP3_NTE:
|
||||
return std::make_shared<MagEvolutionTableGC>(data);
|
||||
case Version::XB_V3:
|
||||
return std::make_shared<MagEvolutionTableXB>(data);
|
||||
case Version::BB_V4:
|
||||
return std::make_shared<MagEvolutionTableV4>(data);
|
||||
default:
|
||||
throw std::logic_error("Cannot create mag evolution table for this version");
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "WindowsPlatform.hh"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
#include "Text.hh"
|
||||
#include "Types.hh"
|
||||
#include "Version.hh"
|
||||
|
||||
class MagEvolutionTable {
|
||||
public:
|
||||
struct MotionReference {
|
||||
struct Side {
|
||||
// This specifies which entry in ItemMagMotion.dat is used. The file is just a list of 0x64-byte structures.
|
||||
// 0xFF = no TItemMagSub is created
|
||||
uint8_t motion_table_entry = 0xFF;
|
||||
parray<uint8_t, 5> unknown_a1 = 0;
|
||||
} __packed_ws__(Side, 0x06);
|
||||
parray<Side, 2> sides; // [0] = right side, [1] = left side
|
||||
} __packed_ws__(MotionReference, 0x0C);
|
||||
|
||||
struct UnknownA3Entry {
|
||||
uint8_t flags;
|
||||
uint8_t unknown_a2;
|
||||
uint16_t unknown_a3;
|
||||
uint16_t unknown_a4;
|
||||
uint16_t unknown_a5;
|
||||
};
|
||||
|
||||
virtual ~MagEvolutionTable() = default;
|
||||
|
||||
static std::shared_ptr<MagEvolutionTable> create(std::shared_ptr<const std::string> data, Version version);
|
||||
|
||||
virtual size_t num_mags() const = 0;
|
||||
|
||||
virtual size_t num_motion_entries(bool use_second_table) const = 0;
|
||||
virtual const MotionReference& get_motion_reference(bool use_second_table, size_t index) const = 0;
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t index) const = 0;
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const = 0;
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t index) const = 0;
|
||||
|
||||
virtual uint8_t get_unknown_a4(size_t index) const = 0;
|
||||
|
||||
virtual size_t num_colors() const = 0;
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t index) const = 0;
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const = 0;
|
||||
|
||||
protected:
|
||||
MagEvolutionTable() = default;
|
||||
};
|
||||
@@ -0,0 +1,580 @@
|
||||
#include "MagMetadataTable.hh"
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
|
||||
MagMetadataTable::MotionReferences MagMetadataTable::MotionReferences::from_json(const phosg::JSON& json) {
|
||||
auto parse_side = [](Side& side, const phosg::JSON& side_json) -> void {
|
||||
side.eff_1 = side_json.at("Eff1").as_int();
|
||||
side.eff_2 = side_json.at("Eff2").as_int();
|
||||
side.eff_3 = side_json.at("Eff3").as_int();
|
||||
side.eff_4_8 = side_json.at("Eff48").as_int();
|
||||
side.eff_5 = side_json.at("Eff5").as_int();
|
||||
side.eff_6_7 = side_json.at("Eff67").as_int();
|
||||
};
|
||||
MagMetadataTable::MotionReferences ret;
|
||||
parse_side(ret.sides[0], json.at("Left"));
|
||||
parse_side(ret.sides[1], json.at("Right"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
phosg::JSON MagMetadataTable::MotionReferences::json() const {
|
||||
auto serialize_side = [](const Side& side) -> phosg::JSON {
|
||||
return phosg::JSON::dict({
|
||||
{"Eff1", side.eff_1},
|
||||
{"Eff2", side.eff_2},
|
||||
{"Eff3", side.eff_3},
|
||||
{"Eff48", side.eff_4_8},
|
||||
{"Eff5", side.eff_5},
|
||||
{"Eff67", side.eff_6_7},
|
||||
});
|
||||
};
|
||||
return phosg::JSON::dict({{"Left", serialize_side(this->sides[0])}, {"Right", serialize_side(this->sides[1])}});
|
||||
}
|
||||
|
||||
MagMetadataTable::UnknownA3Entry MagMetadataTable::UnknownA3Entry::from_json(const phosg::JSON& json) {
|
||||
return UnknownA3Entry{
|
||||
.flags = static_cast<uint8_t>(json.get_int("Flags")),
|
||||
.unknown_a2 = static_cast<uint8_t>(json.get_int("UnknownA2")),
|
||||
.unknown_a3 = static_cast<int16_t>(json.get_int("UnknownA3")),
|
||||
.unknown_a4 = static_cast<int16_t>(json.get_int("UnknownA4")),
|
||||
.unknown_a5 = static_cast<int16_t>(json.get_int("UnknownA5")),
|
||||
};
|
||||
}
|
||||
|
||||
phosg::JSON MagMetadataTable::UnknownA3Entry::json() const {
|
||||
return phosg::JSON::dict({
|
||||
{"Flags", this->flags},
|
||||
{"UnknownA2", this->unknown_a2},
|
||||
{"UnknownA3", this->unknown_a3},
|
||||
{"UnknownA4", this->unknown_a4},
|
||||
{"UnknownA5", this->unknown_a5},
|
||||
});
|
||||
}
|
||||
|
||||
static VectorXYZTF color_for_json(const phosg::JSON& json) {
|
||||
return VectorXYZTF{
|
||||
.x = json.get_float(0),
|
||||
.y = json.get_float(1),
|
||||
.z = json.get_float(2),
|
||||
.t = json.get_float(3),
|
||||
};
|
||||
}
|
||||
|
||||
static phosg::JSON json_for_color(const VectorXYZTF& color) {
|
||||
return phosg::JSON::list({color.x.load(), color.y.load(), color.z.load(), color.t.load()});
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
struct MotionReferenceTables {
|
||||
// It seems that there are two definition tables, but only the first is used on any version of PSO. On v3 and later,
|
||||
// the two offsets point to the same table, but on v2 they don't and the second table contains different data.
|
||||
// TODO: Figure out what the deal is with the different v2 tables.
|
||||
U32T<BE> first_ref_table;
|
||||
U32T<BE> second_ref_table;
|
||||
} __packed_ws_be__(MotionReferenceTables, 0x08);
|
||||
|
||||
template <bool BE>
|
||||
struct ColorEntry {
|
||||
// Colors are specified as 4 floats, each in the range [0, 1], for each color channel. The default colors are:
|
||||
// alpha red green blue color (see StaticGameData.cc)
|
||||
// 00 => 1.0 1.0 0.2 0.1 red
|
||||
// 01 => 1.0 0.2 0.2 1.0 blue
|
||||
// 02 => 1.0 1.0 0.9 0.1 yellow
|
||||
// 03 => 1.0 0.1 1.0 0.1 green
|
||||
// 04 => 1.0 0.8 0.1 1.0 purple
|
||||
// 05 => 1.0 0.1 0.1 0.2 black
|
||||
// 06 => 1.0 0.9 1.0 1.0 white
|
||||
// 07 => 1.0 0.1 0.9 1.0 cyan
|
||||
// 08 => 1.0 0.5 0.3 0.2 brown
|
||||
// 09 => 1.0 1.0 0.4 0.0 orange (v3+)
|
||||
// 0A => 1.0 0.502 0.545 0.977 light-blue (v3+)
|
||||
// 0B => 1.0 0.502 0.502 0.0 olive (v3+)
|
||||
// 0C => 1.0 0.0 0.941 0.714 turquoise (v3+)
|
||||
// 0D => 1.0 0.8 0.098 0.392 fuchsia (v3+)
|
||||
// 0E => 1.0 0.498 0.498 0.498 grey (v3+)
|
||||
// 0F => 1.0 0.996 0.996 0.832 cream (v3+)
|
||||
// 10 => 1.0 0.996 0.498 0.784 pink (v3+)
|
||||
// 11 => 1.0 0.0 0.498 0.322 dark-green (v3+)
|
||||
// If a mag's color index is invalid (>= 0x12), it is reassigned at equip time using the following logic:
|
||||
// - Set base_index to player->visual.sh.skin if player is an android, or player->visual.costume otherwise
|
||||
// - If (base_index % 9) < 7 (that is, if their costume or body color is one of the colored slots on the character
|
||||
// creation screen), then set the mag color to either (base_index % 9) or (base_index % 9) + 9, with equal
|
||||
// probability.
|
||||
// - If (base_index % 9) >= 7 (that is, if their costume or body color is one of the last two blank-colored slots
|
||||
// on the character creation screen), then set the mag color to any of the available colors, chosen at random.
|
||||
F32T<BE> alpha;
|
||||
F32T<BE> red;
|
||||
F32T<BE> green;
|
||||
F32T<BE> blue;
|
||||
ColorEntry(const VectorXYZTF& c) : alpha(c.t), red(c.x), green(c.y), blue(c.z) {}
|
||||
operator VectorXYZTF() const {
|
||||
return VectorXYZTF{this->red.load(), this->green.load(), this->blue.load(), this->alpha.load()};
|
||||
}
|
||||
} __packed_ws_be__(ColorEntry, 0x10);
|
||||
|
||||
template <bool BE>
|
||||
struct UnknownA3EntryT {
|
||||
uint8_t flags;
|
||||
uint8_t unknown_a2;
|
||||
S16T<BE> unknown_a3;
|
||||
S16T<BE> unknown_a4;
|
||||
S16T<BE> unknown_a5;
|
||||
UnknownA3EntryT(const MagMetadataTable::UnknownA3Entry& e)
|
||||
: flags(e.flags),
|
||||
unknown_a2(e.unknown_a2),
|
||||
unknown_a3(e.unknown_a3),
|
||||
unknown_a4(e.unknown_a4),
|
||||
unknown_a5(e.unknown_a5) {}
|
||||
operator MagMetadataTable::UnknownA3Entry() const {
|
||||
return MagMetadataTable::UnknownA3Entry{
|
||||
this->flags, this->unknown_a2, this->unknown_a3, this->unknown_a4, this->unknown_a5};
|
||||
}
|
||||
} __packed_ws_be__(UnknownA3EntryT, 0x08);
|
||||
|
||||
class JSONMagMetadataTable : public MagMetadataTable {
|
||||
public:
|
||||
explicit JSONMagMetadataTable(const phosg::JSON& json) {
|
||||
for (const auto& mag_json : json.at("Mags").as_list()) {
|
||||
const auto& unknown_a2_json = mag_json->at("UnknownA2").as_list();
|
||||
auto& mag = this->mags.emplace_back();
|
||||
mag.first_motion_refs = MotionReferences::from_json(mag_json->at("MotionRefs1"));
|
||||
mag.second_motion_refs = MotionReferences::from_json(mag_json->at("MotionRefs2"));
|
||||
mag.unknown_a2 = std::make_pair(unknown_a2_json.at(0)->as_int(), unknown_a2_json.at(1)->as_int());
|
||||
mag.render_flags = mag_json->at("RenderFlags").as_int();
|
||||
mag.evolution_number = mag_json->at("EvolutionNumber").as_int();
|
||||
}
|
||||
for (const auto& a3_json : json.at("UnknownA3").as_list()) {
|
||||
this->unknown_a3.emplace_back(UnknownA3Entry::from_json(*a3_json));
|
||||
}
|
||||
for (const auto& color_json : json.at("Colors").as_list()) {
|
||||
this->colors.emplace_back(color_for_json(*color_json));
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~JSONMagMetadataTable() = default;
|
||||
|
||||
virtual size_t num_mags() const {
|
||||
return this->mags.size();
|
||||
}
|
||||
|
||||
virtual size_t num_motion_entries(bool) const {
|
||||
return this->mags.size();
|
||||
}
|
||||
virtual const MotionReferences& get_motion_references(bool use_second_table, size_t data1_1) const {
|
||||
const auto& mag = this->mags.at(data1_1);
|
||||
return use_second_table ? mag.second_motion_refs : mag.first_motion_refs;
|
||||
}
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t data1_1) const {
|
||||
return this->mags.at(data1_1).unknown_a2;
|
||||
}
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const {
|
||||
return this->unknown_a3.size();
|
||||
}
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t index) const {
|
||||
return this->unknown_a3.at(index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_render_flags(size_t data1_1) const {
|
||||
return this->mags.at(data1_1).render_flags;
|
||||
}
|
||||
|
||||
virtual size_t num_colors() const {
|
||||
return this->colors.size();
|
||||
}
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t index) const {
|
||||
return this->colors.at(index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const {
|
||||
return this->mags.at(data1_1).evolution_number;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct Mag {
|
||||
MotionReferences first_motion_refs;
|
||||
MotionReferences second_motion_refs;
|
||||
std::pair<uint8_t, uint8_t> unknown_a2 = std::make_pair(0, 0);
|
||||
uint8_t render_flags = 0;
|
||||
uint8_t evolution_number = 0;
|
||||
};
|
||||
std::vector<Mag> mags;
|
||||
std::vector<UnknownA3Entry> unknown_a3;
|
||||
std::vector<VectorXYZTF> colors;
|
||||
};
|
||||
|
||||
struct HeaderV1 {
|
||||
parray<uint8_t, 4> unknown_a1 = {0x0F, 0xF0, 0x00, 0x00};
|
||||
le_uint32_t unknown_a2 = 0x00000003;
|
||||
le_uint16_t unknown_a3 = 0x00C8;
|
||||
le_uint16_t unknown_a4 = 0x0078;
|
||||
// unknown_a5 added in V2
|
||||
le_float unknown_a6 = 0.25; // 3E800000
|
||||
le_float unknown_a7 = 0.099999994; // 3DCCCCCC
|
||||
le_uint32_t unknown_a8 = 0x00000C00;
|
||||
} __packed_ws__(HeaderV1, 0x18);
|
||||
|
||||
template <bool BE>
|
||||
struct HeaderV2V3V4 {
|
||||
parray<uint8_t, 4> unknown_a1 = {0x0F, 0xF0, 0x00, 0x00};
|
||||
U32T<BE> unknown_a2 = 0x00000003;
|
||||
U16T<BE> unknown_a3 = 0x00C8;
|
||||
U16T<BE> unknown_a4 = 0x0078;
|
||||
parray<uint8_t, 4> unknown_a5 = {0xC8, 0x00, 0x00, 0x00};
|
||||
F32T<BE> unknown_a6 = 0.25; // 3E800000
|
||||
F32T<BE> unknown_a7 = 0.099999994; // 3DCCCCCC
|
||||
U32T<BE> unknown_a8 = 0x00000C00;
|
||||
} __packed_ws_be__(HeaderV2V3V4, 0x1C);
|
||||
|
||||
// Fields:
|
||||
// 112K / V1 / V2 / V3 / BB R
|
||||
// 0018 / 0018 / 001C / 001C / 001C motion_tables.first_ref_table // -> MotionReferences[NumMags]
|
||||
// 0228 / 0228 / 02D4 / 001C / 001C motion_tables.second_ref_table // -> MotionReferences[NumMags]
|
||||
// 0438 / 0438 / 05BC / 0340 / 0400 * motion_tables; // -> MotionReferenceTables
|
||||
// 0440 / 0440 / 0594 / 0348 / 0408 * unknown_a2; // -> (uint8_t[2])[NumMags] (references into unknown_a3)
|
||||
// 0498 / 0498 / 0608 / 03CE / 04AE * unknown_a3; // -> UnknownA3Entry[max(unknown_a2) + 1]
|
||||
// 0510 / 0520 / 06B0 / 0476 / 0556 * render_flags; // -> uint8_t[NumMags]
|
||||
// 053C / 054C / 06EC / 04BC / 05AC * color_table; // -> ColorEntry[NumColors]
|
||||
// ---- / ---- / 077C / 05DC / 06CC * evolution_number_table; // -> uint8_t[NumMags]
|
||||
|
||||
template <bool BE>
|
||||
struct RootV1 {
|
||||
U32T<BE> motion_tables;
|
||||
U32T<BE> unknown_a2;
|
||||
U32T<BE> unknown_a3;
|
||||
U32T<BE> render_flags;
|
||||
U32T<BE> color_table;
|
||||
} __packed_ws_be__(RootV1, 0x14);
|
||||
|
||||
template <bool BE>
|
||||
struct RootV2V3V4 : RootV1<BE> {
|
||||
U32T<BE> evolution_number_table;
|
||||
} __packed_ws_be__(RootV2V3V4, 0x18);
|
||||
|
||||
static uint8_t get_v1_mag_evolution_number(uint8_t data1_1) {
|
||||
static const std::array<uint8_t, 0x2C> v1_evolution_number_table{
|
||||
/* 00 */ 0, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 2,
|
||||
/* 10 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 2, 3, 4, 3, 3,
|
||||
/* 20 */ 3, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 4};
|
||||
if (data1_1 >= v1_evolution_number_table.size()) {
|
||||
throw std::runtime_error("invalid mag number");
|
||||
}
|
||||
return v1_evolution_number_table[data1_1];
|
||||
}
|
||||
|
||||
template <typename HeaderT, typename RootT, size_t NumMags, size_t NumColors, bool BE>
|
||||
class BinaryMagMetadataTableT : public MagMetadataTable {
|
||||
public:
|
||||
explicit BinaryMagMetadataTableT(std::shared_ptr<const std::string> data)
|
||||
: data(data), r(*data), root(&r.pget<RootT>(this->r.pget<U32T<BE>>(this->data->size() - 0x10))) {}
|
||||
virtual ~BinaryMagMetadataTableT() = default;
|
||||
|
||||
template <typename RawT, typename ParsedT>
|
||||
const ParsedT& add_to_vector_cache(std::vector<ParsedT>& cache, size_t base_offset, size_t index) const {
|
||||
while (cache.size() <= index) {
|
||||
cache.emplace_back(this->r.pget<RawT>(base_offset + sizeof(RawT) * cache.size()));
|
||||
}
|
||||
return cache[index];
|
||||
}
|
||||
|
||||
virtual size_t num_mags() const {
|
||||
return NumMags;
|
||||
}
|
||||
|
||||
virtual size_t num_motion_entries(bool use_second_table) const {
|
||||
const auto& tables = this->r.pget<MotionReferenceTables<BE>>(this->root->motion_tables);
|
||||
return get_rel_array_count<MotionReferences>(
|
||||
this->all_start_offsets(), use_second_table ? tables.second_ref_table : tables.first_ref_table);
|
||||
}
|
||||
|
||||
virtual const MotionReferences& get_motion_references(bool use_second_table, size_t index) const {
|
||||
if (index >= this->num_motion_entries(use_second_table)) {
|
||||
throw std::logic_error("Invalid motion reference index");
|
||||
}
|
||||
const auto& tables = this->r.pget<MotionReferenceTables<BE>>(this->root->motion_tables);
|
||||
uint32_t array_offset = use_second_table ? tables.second_ref_table : tables.first_ref_table;
|
||||
return this->r.pget<MotionReferences>(array_offset + sizeof(MotionReferences) * index);
|
||||
}
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t index) const {
|
||||
if (index >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid unknown_a2 index");
|
||||
}
|
||||
uint32_t base_offset = this->root->unknown_a2 + (index * 2);
|
||||
return std::make_pair(this->r.pget_u8(base_offset), this->r.pget_u8(base_offset + 1));
|
||||
}
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const {
|
||||
return get_rel_array_count<UnknownA3EntryT<BE>>(this->all_start_offsets(), this->root->unknown_a3);
|
||||
}
|
||||
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t index) const {
|
||||
if (index >= this->num_unknown_a3_entries()) {
|
||||
throw std::logic_error("Invalid unknown_a2 index");
|
||||
}
|
||||
return this->add_to_vector_cache<UnknownA3EntryT<BE>>(this->unknown_a3_entries, this->root->unknown_a3, index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_render_flags(size_t index) const {
|
||||
if (index >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid render_flags index");
|
||||
}
|
||||
return this->r.pget_u8(this->root->render_flags + index);
|
||||
}
|
||||
|
||||
virtual size_t num_colors() const {
|
||||
return NumColors;
|
||||
}
|
||||
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t index) const {
|
||||
if (index >= NumColors) {
|
||||
throw std::runtime_error("invalid mag color index");
|
||||
}
|
||||
return this->add_to_vector_cache<ColorEntry<BE>>(this->colors, this->root->color_table, index);
|
||||
}
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const {
|
||||
if (data1_1 >= this->num_mags()) {
|
||||
throw std::logic_error("Invalid evolution_number index");
|
||||
}
|
||||
if constexpr (requires { this->root->evolution_number_table; }) {
|
||||
return this->r.pget_u8(this->root->evolution_number_table + data1_1);
|
||||
} else {
|
||||
return get_v1_mag_evolution_number(data1_1);
|
||||
}
|
||||
}
|
||||
|
||||
const std::set<uint32_t>& all_start_offsets() const {
|
||||
if (this->start_offsets.empty()) {
|
||||
this->start_offsets = all_relocation_offsets_for_rel_file<BE>(r.pgetv(0, r.size()), r.size());
|
||||
}
|
||||
return this->start_offsets;
|
||||
}
|
||||
|
||||
static std::string serialize(const MagMetadataTable& table) {
|
||||
RELFileWriter<BE> rel;
|
||||
RootT root;
|
||||
|
||||
rel.template put<HeaderT>(HeaderT());
|
||||
|
||||
MotionReferenceTables<BE> motion_ref_tables;
|
||||
motion_ref_tables.first_ref_table = rel.w.size();
|
||||
bool alias_motion_ref_tables = true;
|
||||
for (size_t z = 0; z < table.num_motion_entries(false); z++) {
|
||||
const auto& refs = table.get_motion_references(false, z);
|
||||
rel.template put<MotionReferences>(refs);
|
||||
if (refs != table.get_motion_references(true, z)) {
|
||||
alias_motion_ref_tables = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (alias_motion_ref_tables) {
|
||||
motion_ref_tables.second_ref_table = motion_ref_tables.first_ref_table;
|
||||
} else {
|
||||
motion_ref_tables.second_ref_table = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_motion_entries(true); z++) {
|
||||
rel.template put<MotionReferences>(table.get_motion_references(true, z));
|
||||
}
|
||||
}
|
||||
|
||||
root.motion_tables = rel.w.size();
|
||||
rel.template put<MotionReferenceTables<BE>>(motion_ref_tables);
|
||||
rel.relocations.emplace(root.motion_tables);
|
||||
rel.relocations.emplace(root.motion_tables + 4);
|
||||
|
||||
root.unknown_a2 = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_mags(); z++) {
|
||||
auto [left, right] = table.get_unknown_a2(z);
|
||||
rel.template put<uint8_t>(left);
|
||||
rel.template put<uint8_t>(right);
|
||||
}
|
||||
|
||||
root.unknown_a3 = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_unknown_a3_entries(); z++) {
|
||||
rel.template put<UnknownA3EntryT<BE>>(table.get_unknown_a3(z));
|
||||
}
|
||||
|
||||
root.render_flags = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_mags(); z++) {
|
||||
rel.template put<uint8_t>(table.get_render_flags(z));
|
||||
}
|
||||
|
||||
rel.align(4);
|
||||
root.color_table = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_colors(); z++) {
|
||||
rel.template put<ColorEntry<BE>>(table.get_color_rgba(z));
|
||||
}
|
||||
|
||||
if constexpr (requires { root.evolution_number_table; }) {
|
||||
root.evolution_number_table = rel.w.size();
|
||||
for (size_t z = 0; z < table.num_mags(); z++) {
|
||||
rel.template put<uint8_t>(table.get_evolution_number(z));
|
||||
}
|
||||
}
|
||||
|
||||
rel.align(4);
|
||||
uint32_t root_offset = rel.template put<RootT>(root);
|
||||
for (size_t z = 1; z <= sizeof(RootT) / 4; z++) {
|
||||
rel.relocations.emplace(rel.w.size() - (z * 4));
|
||||
}
|
||||
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const std::string> data;
|
||||
phosg::StringReader r;
|
||||
const RootT* root;
|
||||
mutable std::set<uint32_t> start_offsets;
|
||||
mutable std::vector<UnknownA3Entry> unknown_a3_entries;
|
||||
mutable std::vector<VectorXYZTF> colors;
|
||||
};
|
||||
|
||||
class MagMetadataTableDCNTE : public MagMetadataTable {
|
||||
public:
|
||||
MagMetadataTableDCNTE() = default;
|
||||
virtual ~MagMetadataTableDCNTE() = default;
|
||||
|
||||
virtual size_t num_mags() const {
|
||||
return 0x2C;
|
||||
}
|
||||
|
||||
virtual size_t num_motion_entries(bool) const {
|
||||
return 0;
|
||||
}
|
||||
virtual const MotionReferences& get_motion_references(bool, size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const {
|
||||
return 0;
|
||||
}
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual uint8_t get_render_flags(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual size_t num_colors() const {
|
||||
return 0;
|
||||
}
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t) const {
|
||||
throw std::runtime_error("Mag tables not available on DC NTE");
|
||||
}
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const {
|
||||
return get_v1_mag_evolution_number(data1_1);
|
||||
}
|
||||
};
|
||||
|
||||
using MagMetadataTableDC112000 = BinaryMagMetadataTableT<HeaderV1, RootV1<false>, 0x2C, 0x09, false>;
|
||||
using MagMetadataTableV1 = BinaryMagMetadataTableT<HeaderV1, RootV1<false>, 0x2C, 0x09, false>;
|
||||
using MagMetadataTableV2 = BinaryMagMetadataTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x3A, 0x09, false>;
|
||||
using MagMetadataTableGCNTE = BinaryMagMetadataTableT<HeaderV2V3V4<true>, RootV2V3V4<true>, 0x3A, 0x09, true>;
|
||||
using MagMetadataTableGC = BinaryMagMetadataTableT<HeaderV2V3V4<true>, RootV2V3V4<true>, 0x43, 0x12, true>;
|
||||
using MagMetadataTableXB = BinaryMagMetadataTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x43, 0x12, false>;
|
||||
using MagMetadataTableV4 = BinaryMagMetadataTableT<HeaderV2V3V4<false>, RootV2V3V4<false>, 0x53, 0x12, false>;
|
||||
|
||||
std::shared_ptr<MagMetadataTable> MagMetadataTable::from_binary(
|
||||
std::shared_ptr<const std::string> data, Version version) {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
return std::make_shared<MagMetadataTableDCNTE>();
|
||||
case Version::DC_11_2000:
|
||||
return std::make_shared<MagMetadataTableDC112000>(data);
|
||||
case Version::DC_V1:
|
||||
return std::make_shared<MagMetadataTableV1>(data);
|
||||
case Version::DC_V2:
|
||||
case Version::PC_NTE:
|
||||
case Version::PC_V2:
|
||||
return std::make_shared<MagMetadataTableV2>(data);
|
||||
case Version::GC_NTE:
|
||||
return std::make_shared<MagMetadataTableGCNTE>(data);
|
||||
case Version::GC_V3:
|
||||
case Version::GC_EP3:
|
||||
case Version::GC_EP3_NTE:
|
||||
return std::make_shared<MagMetadataTableGC>(data);
|
||||
case Version::XB_V3:
|
||||
return std::make_shared<MagMetadataTableXB>(data);
|
||||
case Version::BB_V4:
|
||||
return std::make_shared<MagMetadataTableV4>(data);
|
||||
default:
|
||||
throw std::logic_error("Cannot create mag metadata table for this version");
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<MagMetadataTable> MagMetadataTable::from_json(const phosg::JSON& json) {
|
||||
return std::make_shared<JSONMagMetadataTable>(json);
|
||||
}
|
||||
|
||||
phosg::JSON MagMetadataTable::json() const {
|
||||
if (this->num_motion_entries(true) != this->num_motion_entries(false)) {
|
||||
throw std::runtime_error("Motion entry counts differ across tables");
|
||||
}
|
||||
if (this->num_motion_entries(false) != this->num_mags()) {
|
||||
throw std::runtime_error(std::format("Motion entry count {} does not match mag count {}",
|
||||
this->num_motion_entries(false), this->num_mags()));
|
||||
}
|
||||
|
||||
auto mags_json = phosg::JSON::list();
|
||||
for (size_t z = 0; z < this->num_mags(); z++) {
|
||||
auto mag_json = phosg::JSON::dict();
|
||||
mag_json.emplace("MotionRefs1", this->get_motion_references(false, z).json());
|
||||
mag_json.emplace("MotionRefs2", this->get_motion_references(true, z).json());
|
||||
auto unknown_a2 = this->get_unknown_a2(z);
|
||||
mag_json.emplace("UnknownA2", phosg::JSON::list({unknown_a2.first, unknown_a2.second}));
|
||||
mag_json.emplace("RenderFlags", this->get_render_flags(z));
|
||||
mag_json.emplace("EvolutionNumber", this->get_evolution_number(z));
|
||||
mags_json.emplace_back(std::move(mag_json));
|
||||
}
|
||||
|
||||
auto unknown_a3_json = phosg::JSON::list();
|
||||
for (size_t z = 0; z < this->num_unknown_a3_entries(); z++) {
|
||||
unknown_a3_json.emplace_back(this->get_unknown_a3(z).json());
|
||||
}
|
||||
|
||||
auto colors_json = phosg::JSON::list();
|
||||
for (size_t z = 0; z < this->num_colors(); z++) {
|
||||
colors_json.emplace_back(json_for_color(this->get_color_rgba(z)));
|
||||
}
|
||||
|
||||
return phosg::JSON::dict({
|
||||
{"Mags", std::move(mags_json)},
|
||||
{"UnknownA3", std::move(unknown_a3_json)},
|
||||
{"Colors", std::move(colors_json)},
|
||||
});
|
||||
}
|
||||
|
||||
std::string MagMetadataTable::serialize_binary(Version version) const {
|
||||
switch (version) {
|
||||
case Version::DC_NTE:
|
||||
throw std::runtime_error("DC NTE does not have a an ItemMagEdit format");
|
||||
case Version::DC_11_2000:
|
||||
return MagMetadataTableDC112000::serialize(*this);
|
||||
case Version::DC_V1:
|
||||
return MagMetadataTableV1::serialize(*this);
|
||||
case Version::DC_V2:
|
||||
case Version::PC_NTE:
|
||||
case Version::PC_V2:
|
||||
return MagMetadataTableV2::serialize(*this);
|
||||
case Version::GC_NTE:
|
||||
return MagMetadataTableGCNTE::serialize(*this);
|
||||
case Version::GC_V3:
|
||||
case Version::GC_EP3:
|
||||
case Version::GC_EP3_NTE:
|
||||
return MagMetadataTableGC::serialize(*this);
|
||||
case Version::XB_V3:
|
||||
return MagMetadataTableXB::serialize(*this);
|
||||
case Version::BB_V4:
|
||||
return MagMetadataTableV4::serialize(*this);
|
||||
default:
|
||||
throw std::logic_error("Cannot create item parameter table for this version");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include "WindowsPlatform.hh"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
#include "Text.hh"
|
||||
#include "Types.hh"
|
||||
#include "Version.hh"
|
||||
|
||||
class MagMetadataTable {
|
||||
public:
|
||||
struct MotionReferences {
|
||||
// These entries specify which entry in ItemMagMotion.dat is used. The file is just a list of 0x64-byte structures.
|
||||
// 0xFF = no TItemMagSub is created
|
||||
struct Side {
|
||||
uint8_t eff_1;
|
||||
uint8_t eff_2;
|
||||
uint8_t eff_3;
|
||||
uint8_t eff_4_8;
|
||||
uint8_t eff_5;
|
||||
uint8_t eff_6_7;
|
||||
|
||||
bool operator==(const Side&) const = default;
|
||||
bool operator!=(const Side&) const = default;
|
||||
} __packed_ws__(Side, 6);
|
||||
parray<Side, 2> sides; // [0] = right side, [1] = left side
|
||||
|
||||
bool operator==(const MotionReferences&) const = default;
|
||||
bool operator!=(const MotionReferences&) const = default;
|
||||
|
||||
static MotionReferences from_json(const phosg::JSON& json);
|
||||
phosg::JSON json() const;
|
||||
} __packed_ws__(MotionReferences, 0x0C);
|
||||
|
||||
struct UnknownA3Entry {
|
||||
uint8_t flags;
|
||||
uint8_t unknown_a2;
|
||||
int16_t unknown_a3;
|
||||
int16_t unknown_a4;
|
||||
int16_t unknown_a5;
|
||||
|
||||
static UnknownA3Entry from_json(const phosg::JSON& json);
|
||||
phosg::JSON json() const;
|
||||
};
|
||||
|
||||
virtual ~MagMetadataTable() = default;
|
||||
|
||||
virtual size_t num_mags() const = 0;
|
||||
|
||||
virtual size_t num_motion_entries(bool use_second_table) const = 0;
|
||||
virtual const MotionReferences& get_motion_references(bool use_second_table, size_t index) const = 0;
|
||||
|
||||
virtual std::pair<uint8_t, uint8_t> get_unknown_a2(size_t index) const = 0;
|
||||
|
||||
virtual size_t num_unknown_a3_entries() const = 0;
|
||||
virtual const UnknownA3Entry& get_unknown_a3(size_t index) const = 0;
|
||||
|
||||
virtual uint8_t get_render_flags(size_t index) const = 0;
|
||||
|
||||
virtual size_t num_colors() const = 0;
|
||||
virtual const VectorXYZTF& get_color_rgba(size_t index) const = 0;
|
||||
|
||||
virtual uint8_t get_evolution_number(uint8_t data1_1) const = 0;
|
||||
|
||||
static std::shared_ptr<MagMetadataTable> from_binary(std::shared_ptr<const std::string> data, Version version);
|
||||
static std::shared_ptr<MagMetadataTable> from_json(const phosg::JSON& json);
|
||||
|
||||
phosg::JSON json() const;
|
||||
std::string serialize_binary(Version version) const;
|
||||
|
||||
protected:
|
||||
MagMetadataTable() = default;
|
||||
};
|
||||
+179
-15
@@ -2396,6 +2396,136 @@ Action a_encode_item_parameter_table(
|
||||
write_output_data(args, data, nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_mag_metadata_table(
|
||||
"decode-mag-metadata-table", "\
|
||||
decode-mag-metadata-table [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
|
||||
Converts an ItemMagEdit file into a JSON mag metadata file. A version\n\
|
||||
option is required. Expects compressed input (a .prs file) by default; use\n\
|
||||
--decompressed if the input is not compressed.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto input_data = read_input_data(args);
|
||||
if (!args.get<bool>("decompressed")) {
|
||||
input_data = prs_decompress(input_data);
|
||||
}
|
||||
auto data = std::make_shared<std::string>(std::move(input_data));
|
||||
auto table = MagMetadataTable::from_binary(data, get_cli_version(args, Version::BB_V4));
|
||||
auto json = table->json();
|
||||
auto serialized = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS);
|
||||
write_output_data(args, serialized, nullptr);
|
||||
});
|
||||
|
||||
Action a_encode_mag_metadata_table(
|
||||
"encode-mag-metadata-table", "\
|
||||
encode-mag-metadata-table [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
|
||||
Converts a JSON mag metadata file into an ItemMagEdit file compatible with\n\
|
||||
the game client. A version option is required. By default the output will\n\
|
||||
be compressed, as the client expects; use --decompressed to get\n\
|
||||
uncompressed output.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto json = phosg::JSON::parse(read_input_data(args));
|
||||
auto table = MagMetadataTable::from_json(json);
|
||||
std::string data = table->serialize_binary(get_cli_version(args, Version::BB_V4));
|
||||
if (!args.get<bool>("decompressed")) {
|
||||
data = prs_compress_optimal(data);
|
||||
}
|
||||
write_output_data(args, data, nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_tekker_adjustment_set(
|
||||
"decode-tekker-adjustment-set", "\
|
||||
decode-tekker-adjustment-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a JudgeItem.rel file into a JSON tekker adjustment set. Use\n\
|
||||
--big-endian if the .rel file is from PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto input_data = read_input_data(args);
|
||||
TekkerAdjustmentSet table(input_data, args.get<bool>("big-endian"));
|
||||
auto json = table.json();
|
||||
auto serialized = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS);
|
||||
write_output_data(args, serialized, nullptr);
|
||||
});
|
||||
|
||||
Action a_encode_tekker_adjustment_set(
|
||||
"encode-tekker-adjustment-set", "\
|
||||
encode-tekker-adjustment-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a JSON tekker adjustment set into a JudgeItem.rel file compatible\n\
|
||||
with the game client. Use --big-endian if the .rel file is for PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
TekkerAdjustmentSet table(phosg::JSON::parse(read_input_data(args)));
|
||||
write_output_data(args, table.serialize_binary(args.get<bool>("big-endian")), nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_armor_shop_random_set(
|
||||
"decode-armor-shop-random-set", "\
|
||||
decode-armor-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a ArmorRandom.rel file into a JSON armor shop random set. Use\n\
|
||||
--big-endian if the .rel file is from PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto input_data = read_input_data(args);
|
||||
ArmorShopRandomSet table(input_data, args.get<bool>("big-endian"));
|
||||
auto json = table.json();
|
||||
auto serialized = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS);
|
||||
write_output_data(args, serialized, nullptr);
|
||||
});
|
||||
|
||||
Action a_encode_armor_shop_random_set(
|
||||
"encode-armor-shop-random-set", "\
|
||||
encode-armor-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a JSON armo shop random set into an ArmorRandom.rel file\n\
|
||||
compatible with the game client. Use --big-endian if the .rel file is for\n\
|
||||
PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
ArmorShopRandomSet table(phosg::JSON::parse(read_input_data(args)));
|
||||
write_output_data(args, table.serialize_binary(args.get<bool>("big-endian")), nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_tool_shop_random_set(
|
||||
"decode-tool-shop-random-set", "\
|
||||
decode-tool-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a ToolRandom.rel file into a JSON tool shop random set. Use\n\
|
||||
--big-endian if the .rel file is from PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto input_data = read_input_data(args);
|
||||
ToolShopRandomSet table(input_data, args.get<bool>("big-endian"));
|
||||
auto json = table.json();
|
||||
auto serialized = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS);
|
||||
write_output_data(args, serialized, nullptr);
|
||||
});
|
||||
|
||||
Action a_encode_tool_shop_random_set(
|
||||
"encode-tool-shop-random-set", "\
|
||||
encode-tool-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a JSON armo shop random set into an ToolRandom.rel file\n\
|
||||
compatible with the game client. Use --big-endian if the .rel file is for\n\
|
||||
PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
ToolShopRandomSet table(phosg::JSON::parse(read_input_data(args)));
|
||||
write_output_data(args, table.serialize_binary(args.get<bool>("big-endian")), nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_weapon_shop_random_set(
|
||||
"decode-weapon-shop-random-set", "\
|
||||
decode-weapon-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a WeaponRandom.rel file into a JSON weapon shop random set. Use\n\
|
||||
--big-endian if the .rel file is from PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto input_data = read_input_data(args);
|
||||
WeaponShopRandomSet table(input_data, args.get<bool>("big-endian"));
|
||||
auto json = table.json();
|
||||
auto serialized = json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::SORT_DICT_KEYS);
|
||||
write_output_data(args, serialized, nullptr);
|
||||
});
|
||||
|
||||
Action a_encode_weapon_shop_random_set(
|
||||
"encode-weapon-shop-random-set", "\
|
||||
encode-weapon-shop-random-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS]\n\
|
||||
Converts a JSON armo shop random set into an WeaponRandom.rel file\n\
|
||||
compatible with the game client. Use --big-endian if the .rel file is for\n\
|
||||
PSO GC.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
WeaponShopRandomSet table(phosg::JSON::parse(read_input_data(args)));
|
||||
write_output_data(args, table.serialize_binary(args.get<bool>("big-endian")), nullptr);
|
||||
});
|
||||
|
||||
Action a_decode_level_table(
|
||||
"decode-level-table", nullptr,
|
||||
+[](phosg::Arguments& args) {
|
||||
@@ -2646,7 +2776,7 @@ Action a_name_all_items(
|
||||
Action a_print_level_stats(
|
||||
"show-level-tables", "\
|
||||
show-level-tables\n\
|
||||
Print the level tables for each version in a semi-human-reatable format.\n",
|
||||
Print the level tables for each version in a semi-human-readable format.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto s = std::make_shared<ServerState>(get_config_filename(args));
|
||||
s->load_config_early();
|
||||
@@ -2732,7 +2862,7 @@ Action a_print_level_stats(
|
||||
Action a_show_item_parameter_tables(
|
||||
"show-item-parameter-tables", "\
|
||||
show-item-parameter-tables\n\
|
||||
Print the item parameter tables for each version in a semi-human-reatable\n\
|
||||
Print the item parameter tables for each version in a semi-human-readable\n\
|
||||
format.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto s = std::make_shared<ServerState>(get_config_filename(args));
|
||||
@@ -2746,6 +2876,27 @@ Action a_show_item_parameter_tables(
|
||||
}
|
||||
});
|
||||
|
||||
Action a_show_shop_random_sets(
|
||||
"show-shop-random-sets", "\
|
||||
show-shop-random-sets\n\
|
||||
Print the tekker and shop generation tables in a semi-human-readable\n\
|
||||
format.\n",
|
||||
+[](phosg::Arguments& args) {
|
||||
auto s = std::make_shared<ServerState>(get_config_filename(args));
|
||||
s->load_all(false);
|
||||
s->tekker_adjustment_set->print(stdout);
|
||||
s->armor_random_set->print(stdout);
|
||||
s->tool_random_set->print(stdout);
|
||||
phosg::fwrite_fmt(stdout, "(Normal) ");
|
||||
s->weapon_random_set(Difficulty::NORMAL)->print(stdout);
|
||||
phosg::fwrite_fmt(stdout, "(Hard) ");
|
||||
s->weapon_random_set(Difficulty::HARD)->print(stdout);
|
||||
phosg::fwrite_fmt(stdout, "(Very Hard) ");
|
||||
s->weapon_random_set(Difficulty::VERY_HARD)->print(stdout);
|
||||
phosg::fwrite_fmt(stdout, "(Ultimate) ");
|
||||
s->weapon_random_set(Difficulty::ULTIMATE)->print(stdout);
|
||||
});
|
||||
|
||||
Action a_show_ep3_cards(
|
||||
"show-ep3-cards", "\
|
||||
show-ep3-cards\n\
|
||||
@@ -3775,21 +3926,34 @@ Action a_diff_executables(
|
||||
bool b_is_dol = b_filename.ends_with(".dol");
|
||||
bool a_is_xbe = a_filename.ends_with(".xbe");
|
||||
bool b_is_xbe = b_filename.ends_with(".xbe");
|
||||
std::vector<DiffEntry> result;
|
||||
if (a_is_dol && b_is_dol) {
|
||||
result = diff_dol_files(a_filename, b_filename);
|
||||
} else if (a_is_xbe && b_is_xbe) {
|
||||
result = diff_xbe_files(a_filename, b_filename);
|
||||
|
||||
if (a_is_dol && b_is_dol && args.get<bool>("semantic")) {
|
||||
std::unordered_set<uint32_t> a_ignore_functions, b_ignore_functions;
|
||||
for (const auto& addr : args.get_multi<uint32_t>("a-ignore-function", phosg::Arguments::IntFormat::HEX)) {
|
||||
a_ignore_functions.emplace(addr);
|
||||
}
|
||||
for (const auto& addr : args.get_multi<uint32_t>("b-ignore-function", phosg::Arguments::IntFormat::HEX)) {
|
||||
b_ignore_functions.emplace(addr);
|
||||
}
|
||||
diff_dol_files_semantic(stdout, a_filename, b_filename, a_ignore_functions, b_ignore_functions);
|
||||
|
||||
} else {
|
||||
throw std::runtime_error("the two files are not the same type of executable, or are neither dol nor xbe");
|
||||
}
|
||||
for (const auto& it : result) {
|
||||
std::string b_str = phosg::format_data_string(it.b_data, nullptr, phosg::FormatDataStringFlags::HEX_ONLY);
|
||||
if (show_pre) {
|
||||
std::string a_str = phosg::format_data_string(it.a_data, nullptr, phosg::FormatDataStringFlags::HEX_ONLY);
|
||||
phosg::fwrite_fmt(stdout, "{:08X}: {} => {}\n", it.address, a_str, b_str);
|
||||
std::vector<DiffEntry> result;
|
||||
if (a_is_dol && b_is_dol) {
|
||||
result = diff_dol_files(a_filename, b_filename);
|
||||
} else if (a_is_xbe && b_is_xbe) {
|
||||
result = diff_xbe_files(a_filename, b_filename);
|
||||
} else {
|
||||
phosg::fwrite_fmt(stdout, "{:08X} {}\n", it.address, b_str);
|
||||
throw std::runtime_error("the two files are not the same type of executable, or are neither dol nor xbe");
|
||||
}
|
||||
for (const auto& it : result) {
|
||||
std::string b_str = phosg::format_data_string(it.b_data, nullptr, phosg::FormatDataStringFlags::HEX_ONLY);
|
||||
if (show_pre) {
|
||||
std::string a_str = phosg::format_data_string(it.a_data, nullptr, phosg::FormatDataStringFlags::HEX_ONLY);
|
||||
phosg::fwrite_fmt(stdout, "{:08X}: {} => {}\n", it.address, a_str, b_str);
|
||||
} else {
|
||||
phosg::fwrite_fmt(stdout, "{:08X} {}\n", it.address, b_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5630,12 +5630,16 @@ static void on_quest_F95E_result_bb(std::shared_ptr<Client> c, SubcommandMessage
|
||||
auto s = c->require_server_state();
|
||||
|
||||
size_t count = (cmd.type > 0x03) ? 1 : (static_cast<size_t>(l->difficulty) + 1);
|
||||
c->log.info_f("Creating {} F95E result items", count);
|
||||
for (size_t z = 0; z < count; z++) {
|
||||
const auto& results = s->quest_F95E_results.at(cmd.type).at(static_cast<size_t>(l->difficulty));
|
||||
if (results.empty()) {
|
||||
throw std::runtime_error("invalid result type");
|
||||
}
|
||||
ItemData item = (results.size() == 1) ? results[0] : results[l->rand_crypt->next() % results.size()];
|
||||
if (c->log.should_log(phosg::LogLevel::L_INFO)) {
|
||||
c->log.info_f("Chose F95E result item {}", item.hex());
|
||||
}
|
||||
if (item.data1[0] == 0x04) { // Meseta
|
||||
// TODO: What is the right amount of Meseta to use here? Presumably it should be random within a certain range,
|
||||
// but it's not obvious what that range should be.
|
||||
@@ -5649,6 +5653,10 @@ static void on_quest_F95E_result_bb(std::shared_ptr<Client> c, SubcommandMessage
|
||||
item.id = l->generate_item_id(0xFF);
|
||||
l->add_item(cmd.floor, item, cmd.pos, nullptr, nullptr, 0x100F);
|
||||
|
||||
if (c->log.should_log(phosg::LogLevel::L_INFO)) {
|
||||
c->log.info_f("Item created as {}", item.hex());
|
||||
}
|
||||
|
||||
send_drop_stacked_item_to_lobby(l, item, cmd.floor, cmd.pos);
|
||||
}
|
||||
}
|
||||
@@ -5908,7 +5916,7 @@ static void on_upgrade_weapon_attribute_bb(std::shared_ptr<Client> c, Subcommand
|
||||
send_destroy_item_to_lobby(c, payment_item.id, cmd.payment_count);
|
||||
|
||||
item.data1[attribute_index] = cmd.attribute;
|
||||
item.data1[attribute_index + 1] += new_attr_value;
|
||||
item.data1[attribute_index + 1] = new_attr_value;
|
||||
|
||||
send_destroy_item_to_lobby(c, item.id, 1);
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
||||
|
||||
+52
-47
@@ -490,15 +490,19 @@ std::shared_ptr<const ItemParameterTable> ServerState::item_parameter_table_for_
|
||||
return this->item_parameter_table(is_v1(version) ? Version::PC_V2 : version);
|
||||
}
|
||||
|
||||
std::shared_ptr<const MagEvolutionTable> ServerState::mag_evolution_table(Version version) const {
|
||||
if (is_v1(version)) {
|
||||
return this->mag_evolution_table_v1;
|
||||
std::shared_ptr<const MagMetadataTable> ServerState::mag_metadata_table(Version version) const {
|
||||
if (version == Version::DC_NTE) {
|
||||
return this->mag_metadata_table_dc_nte;
|
||||
} else if (version == Version::DC_11_2000) {
|
||||
return this->mag_metadata_table_dc_11_2000;
|
||||
} else if (is_v1(version)) {
|
||||
return this->mag_metadata_table_v1;
|
||||
} else if (is_v2(version)) {
|
||||
return this->mag_evolution_table_v2;
|
||||
return this->mag_metadata_table_v2;
|
||||
} else if (!is_v4(version)) {
|
||||
return this->mag_evolution_table_v3;
|
||||
return this->mag_metadata_table_v3;
|
||||
} else {
|
||||
return this->mag_evolution_table_v4;
|
||||
return this->mag_metadata_table_v4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2136,28 +2140,28 @@ void ServerState::load_drop_tables() {
|
||||
}
|
||||
|
||||
config_log.info_f("Loading armor table");
|
||||
auto armor_data = std::make_shared<std::string>(phosg::load_file("system/tables/ArmorRandom-gc-v3.rel"));
|
||||
auto new_armor_random_set = std::make_shared<ArmorRandomSet>(armor_data);
|
||||
auto armor_json = phosg::JSON::parse(phosg::load_file("system/tables/armor-shop-random-set.json"));
|
||||
auto new_armor_random_set = std::make_shared<ArmorShopRandomSet>(armor_json);
|
||||
|
||||
config_log.info_f("Loading tool table");
|
||||
auto tool_data = std::make_shared<std::string>(phosg::load_file("system/tables/ToolRandom-gc-v3.rel"));
|
||||
auto new_tool_random_set = std::make_shared<ToolRandomSet>(tool_data);
|
||||
auto tool_json = phosg::JSON::parse(phosg::load_file("system/tables/tool-shop-random-set.json"));
|
||||
auto new_tool_random_set = std::make_shared<ToolShopRandomSet>(tool_json);
|
||||
|
||||
config_log.info_f("Loading weapon tables");
|
||||
std::array<std::shared_ptr<const WeaponRandomSet>, 4> new_weapon_random_sets;
|
||||
std::array<std::shared_ptr<const WeaponShopRandomSet>, 4> new_weapon_random_sets;
|
||||
const char* filenames[4] = {
|
||||
"system/tables/WeaponRandomNormal-gc-v3.rel",
|
||||
"system/tables/WeaponRandomHard-gc-v3.rel",
|
||||
"system/tables/WeaponRandomVeryHard-gc-v3.rel",
|
||||
"system/tables/WeaponRandomUltimate-gc-v3.rel",
|
||||
"system/tables/weapon-shop-random-set-normal.json",
|
||||
"system/tables/weapon-shop-random-set-hard.json",
|
||||
"system/tables/weapon-shop-random-set-very-hard.json",
|
||||
"system/tables/weapon-shop-random-set-ultimate.json",
|
||||
};
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto weapon_data = std::make_shared<std::string>(phosg::load_file(filenames[z]));
|
||||
new_weapon_random_sets[z] = std::make_shared<WeaponRandomSet>(weapon_data);
|
||||
new_weapon_random_sets[z] = std::make_shared<WeaponShopRandomSet>(
|
||||
phosg::JSON::parse(phosg::load_file(filenames[z])));
|
||||
}
|
||||
|
||||
config_log.info_f("Loading tekker adjustment table");
|
||||
auto tekker_data = std::make_shared<std::string>(phosg::load_file("system/tables/JudgeItem-gc-v3.rel"));
|
||||
config_log.info_f("Loading tekker adjustment set");
|
||||
auto tekker_data = phosg::JSON::parse(phosg::load_file("system/tables/tekker-adjustment-set.json"));
|
||||
auto new_tekker_adjustment_set = std::make_shared<TekkerAdjustmentSet>(tekker_data);
|
||||
|
||||
this->rare_item_sets = std::move(new_rare_item_sets);
|
||||
@@ -2188,25 +2192,32 @@ void ServerState::load_item_definitions() {
|
||||
auto json = phosg::JSON::parse(phosg::load_file("system/tables/translation-table.json"));
|
||||
auto new_item_translation_table = std::make_shared<ItemTranslationTable>(json, new_item_parameter_tables);
|
||||
|
||||
config_log.info_f("Loading v1 mag evolution table");
|
||||
auto mag_data_v1 = std::make_shared<std::string>(prs_decompress(phosg::load_file("system/tables/ItemMagEdit-dc-v1.prs")));
|
||||
auto new_table_v1 = MagEvolutionTable::create(mag_data_v1, Version::DC_V1);
|
||||
config_log.info_f("Loading v2 mag evolution table");
|
||||
auto mag_data_v2 = std::make_shared<std::string>(prs_decompress(phosg::load_file("system/tables/ItemMagEdit-dc-v2.prs")));
|
||||
auto new_table_v2 = MagEvolutionTable::create(mag_data_v2, Version::DC_V2);
|
||||
config_log.info_f("Loading v3 mag evolution table");
|
||||
auto mag_data_v3 = std::make_shared<std::string>(prs_decompress(phosg::load_file("system/tables/ItemMagEdit-xb-v3.prs")));
|
||||
auto new_table_v3 = MagEvolutionTable::create(mag_data_v3, Version::XB_V3);
|
||||
config_log.info_f("Loading v4 mag evolution table");
|
||||
auto mag_data_v4 = std::make_shared<std::string>(prs_decompress(phosg::load_file("system/tables/ItemMagEdit-bb-v4.prs")));
|
||||
auto new_table_v4 = MagEvolutionTable::create(mag_data_v4, Version::BB_V4);
|
||||
config_log.info_f("Creating DC NTE mag metadata table");
|
||||
auto new_table_dc_nte = MagMetadataTable::from_binary(nullptr, Version::DC_NTE);
|
||||
config_log.info_f("Loading DC 11/2000 mag metadata table");
|
||||
auto new_table_11_2000 = MagMetadataTable::from_json(phosg::JSON::parse(phosg::load_file(
|
||||
"system/tables/mag-metadata-table-dc-11-2000.json")));
|
||||
config_log.info_f("Loading v1 mag metadata table");
|
||||
auto new_table_v1 = MagMetadataTable::from_json(phosg::JSON::parse(phosg::load_file(
|
||||
"system/tables/mag-metadata-table-v1.json")));
|
||||
config_log.info_f("Loading v2 mag metadata table");
|
||||
auto new_table_v2 = MagMetadataTable::from_json(phosg::JSON::parse(phosg::load_file(
|
||||
"system/tables/mag-metadata-table-v2.json")));
|
||||
config_log.info_f("Loading v3 mag metadata table");
|
||||
auto new_table_v3 = MagMetadataTable::from_json(phosg::JSON::parse(phosg::load_file(
|
||||
"system/tables/mag-metadata-table-v3.json")));
|
||||
config_log.info_f("Loading v4 mag metadata table");
|
||||
auto new_table_v4 = MagMetadataTable::from_json(phosg::JSON::parse(phosg::load_file(
|
||||
"system/tables/mag-metadata-table-v4.json")));
|
||||
|
||||
this->item_parameter_tables = std::move(new_item_parameter_tables);
|
||||
this->item_translation_table = std::move(new_item_translation_table);
|
||||
this->mag_evolution_table_v1 = std::move(new_table_v1);
|
||||
this->mag_evolution_table_v2 = std::move(new_table_v2);
|
||||
this->mag_evolution_table_v3 = std::move(new_table_v3);
|
||||
this->mag_evolution_table_v4 = std::move(new_table_v4);
|
||||
this->mag_metadata_table_dc_nte = std::move(new_table_dc_nte);
|
||||
this->mag_metadata_table_dc_11_2000 = std::move(new_table_11_2000);
|
||||
this->mag_metadata_table_v1 = std::move(new_table_v1);
|
||||
this->mag_metadata_table_v2 = std::move(new_table_v2);
|
||||
this->mag_metadata_table_v3 = std::move(new_table_v3);
|
||||
this->mag_metadata_table_v4 = std::move(new_table_v4);
|
||||
}
|
||||
|
||||
void ServerState::load_ep3_cards() {
|
||||
@@ -2262,20 +2273,13 @@ void ServerState::generate_bb_stream_file() {
|
||||
config_log.info_f("Generating BB stream file");
|
||||
auto sf = std::make_shared<BBStreamFile>();
|
||||
|
||||
auto add_file = [&](const std::string& filename, const void* data = nullptr, size_t size = 0) -> void {
|
||||
auto add_file = [&](const std::string& filename, const void* data, size_t size) -> void {
|
||||
auto& e = sf->entries.emplace_back();
|
||||
e.offset = sf->data.size();
|
||||
e.filename = filename;
|
||||
if (!data) {
|
||||
std::string file_data = phosg::load_file("system/blueburst/" + filename);
|
||||
e.size = file_data.size();
|
||||
e.checksum = phosg::crc32(file_data.data(), file_data.size());
|
||||
sf->data += file_data;
|
||||
} else {
|
||||
e.size = size;
|
||||
e.checksum = phosg::crc32(data, size);
|
||||
sf->data.append(reinterpret_cast<const char*>(data), size);
|
||||
}
|
||||
e.size = size;
|
||||
e.checksum = phosg::crc32(data, size);
|
||||
sf->data.append(reinterpret_cast<const char*>(data), size);
|
||||
config_log.debug_f(
|
||||
"[BBStreamFile] Added file {} at offset {:08X} ({:08X} bytes) with checksum {:08X}; total size is now {:08X}",
|
||||
filename, e.offset, e.size, e.checksum, sf->data.size());
|
||||
@@ -2283,6 +2287,7 @@ void ServerState::generate_bb_stream_file() {
|
||||
|
||||
auto level_table_data = prs_compress_optimal(this->level_table_v4->serialize_binary_v4());
|
||||
auto pmt_data = prs_compress_optimal(this->item_parameter_table(Version::BB_V4)->serialize_binary(Version::BB_V4));
|
||||
auto mag_data = prs_compress_optimal(this->mag_metadata_table(Version::BB_V4)->serialize_binary(Version::BB_V4));
|
||||
|
||||
const auto& bps = *this->battle_params;
|
||||
add_file("BattleParamEntry.dat", &bps.get_table(true, Episode::EP1), sizeof(BattleParamsIndex::Table));
|
||||
@@ -2292,7 +2297,7 @@ void ServerState::generate_bb_stream_file() {
|
||||
add_file("BattleParamEntry_lab_on.dat", &bps.get_table(false, Episode::EP2), sizeof(BattleParamsIndex::Table));
|
||||
add_file("BattleParamEntry_ep4_on.dat", &bps.get_table(false, Episode::EP4), sizeof(BattleParamsIndex::Table));
|
||||
add_file("PlyLevelTbl.prs", level_table_data.data(), level_table_data.size());
|
||||
add_file("ItemMagEdit.prs");
|
||||
add_file("ItemMagEdit.prs", mag_data.data(), mag_data.size());
|
||||
add_file("ItemPMT.prs", pmt_data.data(), pmt_data.size());
|
||||
|
||||
this->bb_stream_file = sf;
|
||||
|
||||
+14
-10
@@ -24,10 +24,12 @@
|
||||
#include "ItemTranslationTable.hh"
|
||||
#include "LevelTable.hh"
|
||||
#include "Lobby.hh"
|
||||
#include "MagEvolutionTable.hh"
|
||||
#include "MagMetadataTable.hh"
|
||||
#include "Menu.hh"
|
||||
#include "Quest.hh"
|
||||
#include "ShopRandomSets.hh"
|
||||
#include "TeamIndex.hh"
|
||||
#include "TekkerAdjustmentSet.hh"
|
||||
#include "WordSelectTable.hh"
|
||||
|
||||
// Forward declarations due to reference cycles
|
||||
@@ -219,19 +221,21 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
std::shared_ptr<const GSLArchive> bb_data_gsl;
|
||||
std::unordered_map<std::string, std::shared_ptr<const CommonItemSet>> common_item_sets;
|
||||
std::unordered_map<std::string, std::shared_ptr<const RareItemSet>> rare_item_sets;
|
||||
std::shared_ptr<const ArmorRandomSet> armor_random_set;
|
||||
std::shared_ptr<const ToolRandomSet> tool_random_set;
|
||||
std::array<std::shared_ptr<const WeaponRandomSet>, 4> weapon_random_sets; // Keyed oin difficulty
|
||||
std::shared_ptr<const ArmorShopRandomSet> armor_random_set;
|
||||
std::shared_ptr<const ToolShopRandomSet> tool_random_set;
|
||||
std::array<std::shared_ptr<const WeaponShopRandomSet>, 4> weapon_random_sets; // Keyed on difficulty
|
||||
std::shared_ptr<const TekkerAdjustmentSet> tekker_adjustment_set;
|
||||
std::array<std::shared_ptr<const ItemParameterTable>, NUM_VERSIONS> item_parameter_tables;
|
||||
std::shared_ptr<const ItemTranslationTable> item_translation_table;
|
||||
std::array<std::shared_ptr<const ItemData::StackLimits>, NUM_VERSIONS> item_stack_limits_tables;
|
||||
size_t bb_max_bank_items = 200;
|
||||
size_t bb_max_bank_meseta = 999999;
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table_v1;
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table_v2;
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table_v3;
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table_v4;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_dc_nte;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_dc_11_2000;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_v1;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_v2;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_v3;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table_v4;
|
||||
std::shared_ptr<const TextIndex> text_index;
|
||||
std::array<std::shared_ptr<const ItemNameIndex>, NUM_VERSIONS> item_name_indexes;
|
||||
std::shared_ptr<const WordSelectTable> word_select_table;
|
||||
@@ -371,7 +375,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
|
||||
std::shared_ptr<const SetDataTableBase> set_data_table(Version version, Episode episode, GameMode mode, Difficulty difficulty) const;
|
||||
|
||||
inline std::shared_ptr<const WeaponRandomSet> weapon_random_set(Difficulty difficulty) const {
|
||||
inline std::shared_ptr<const WeaponShopRandomSet> weapon_random_set(Difficulty difficulty) const {
|
||||
return this->weapon_random_sets.at(static_cast<size_t>(difficulty));
|
||||
}
|
||||
inline std::shared_ptr<const MapState::RareEnemyRates> rare_enemy_rates(Difficulty difficulty) const {
|
||||
@@ -381,7 +385,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
||||
std::shared_ptr<const LevelTable> level_table(Version version) const;
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table(Version version) const;
|
||||
std::shared_ptr<const ItemParameterTable> item_parameter_table_for_encode(Version version) const;
|
||||
std::shared_ptr<const MagEvolutionTable> mag_evolution_table(Version version) const;
|
||||
std::shared_ptr<const MagMetadataTable> mag_metadata_table(Version version) const;
|
||||
std::shared_ptr<const ItemData::StackLimits> item_stack_limits(Version version) const;
|
||||
std::shared_ptr<const ItemNameIndex> item_name_index_opt(Version version) const; // Returns null if missing
|
||||
std::shared_ptr<const ItemNameIndex> item_name_index(Version version) const; // Throws if missing
|
||||
|
||||
@@ -0,0 +1,834 @@
|
||||
#include "ShopRandomSets.hh"
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "Types.hh"
|
||||
|
||||
template <bool BE>
|
||||
struct TableSpecT {
|
||||
U32T<BE> offset;
|
||||
uint8_t row_size;
|
||||
parray<uint8_t, 3> unused;
|
||||
} __packed_ws_be__(TableSpecT, 8);
|
||||
|
||||
template <typename T>
|
||||
void print_table_2d(FILE* stream, const std::vector<std::vector<T>>& table) {
|
||||
for (size_t z = 0; z < table.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", z);
|
||||
for (const auto& cell : table[z]) {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}", cell);
|
||||
} else {
|
||||
// It should be ShopRandomSetBase::IntPairT<...>
|
||||
phosg::fwrite_fmt(stream, " {:02X} @ {:03}", cell.first, cell.second);
|
||||
}
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ParsedT, typename StoredT = ParsedT>
|
||||
std::vector<std::vector<ParsedT>> parse_table_t(
|
||||
const phosg::StringReader& r, uint32_t offset, size_t row_size, const std::set<uint32_t> start_offsets) {
|
||||
auto end_offset_it = start_offsets.upper_bound(offset);
|
||||
if (end_offset_it == start_offsets.end()) {
|
||||
throw std::runtime_error("Cannot determine table end offset");
|
||||
}
|
||||
uint32_t end_offset = *end_offset_it;
|
||||
|
||||
size_t row_bytes = row_size * sizeof(StoredT);
|
||||
size_t row_count = (end_offset - offset) / row_bytes;
|
||||
auto sub_r = r.sub(offset, row_bytes * row_count);
|
||||
|
||||
std::vector<std::vector<ParsedT>> ret;
|
||||
while (ret.size() < row_count) {
|
||||
auto& row = ret.emplace_back();
|
||||
while (row.size() < row_size) {
|
||||
row.emplace_back(sub_r.get<StoredT>());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename StoredT, typename ParsedT = StoredT, bool BE>
|
||||
TableSpecT<BE> serialize_table_t(RELFileWriter<BE>& rel, const std::vector<std::vector<ParsedT>>& table) {
|
||||
if (table.empty()) {
|
||||
throw std::runtime_error("Table is empty");
|
||||
}
|
||||
|
||||
TableSpecT<BE> ret;
|
||||
ret.offset = rel.w.size();
|
||||
ret.row_size = table[0].size();
|
||||
for (const auto& row : table) {
|
||||
if (row.size() != ret.row_size) {
|
||||
throw std::runtime_error("Table has different row sizes");
|
||||
}
|
||||
for (const auto& cell : row) {
|
||||
rel.template put<StoredT>(cell);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <size_t RowCount, size_t RowSize, typename ParsedT, typename StoredT = ParsedT>
|
||||
std::array<std::array<ParsedT, RowSize>, RowCount> parse_fixed_table_t(const phosg::StringReader& r, uint32_t offset) {
|
||||
auto sub_r = r.sub(offset, RowSize * RowCount * sizeof(StoredT));
|
||||
std::array<std::array<ParsedT, RowSize>, RowCount> ret;
|
||||
for (size_t y = 0; y < RowCount; y++) {
|
||||
for (size_t x = 0; x < RowSize; x++) {
|
||||
ret[y][x] = sub_r.get<StoredT>();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <size_t RowCount, size_t RowSize, typename ParsedT, typename StoredT = ParsedT, bool BE>
|
||||
uint32_t serialize_fixed_table_t(
|
||||
RELFileWriter<BE>& rel, const std::array<std::array<ParsedT, RowSize>, RowCount>& table) {
|
||||
uint32_t ret = rel.w.size();
|
||||
for (const auto& row : table) {
|
||||
for (const auto& cell : row) {
|
||||
rel.template put<StoredT>(cell);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<std::vector<T>> table_for_json_t(const phosg::JSON& table_json) {
|
||||
std::vector<std::vector<T>> ret;
|
||||
for (const auto& row_json : table_json.as_list()) {
|
||||
auto& row = ret.emplace_back();
|
||||
for (const auto& cell_json : row_json->as_list()) {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
row.emplace_back(cell_json->as_int());
|
||||
} else {
|
||||
row.emplace_back(*cell_json);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
phosg::JSON json_for_table_t(const std::vector<std::vector<T>>& table) {
|
||||
auto table_json = phosg::JSON::list();
|
||||
for (const auto& row : table) {
|
||||
auto row_json = phosg::JSON::list();
|
||||
for (const auto& cell : row) {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
row_json.emplace_back(cell);
|
||||
} else {
|
||||
row_json.emplace_back(cell.json());
|
||||
}
|
||||
}
|
||||
table_json.emplace_back(std::move(row_json));
|
||||
}
|
||||
return table_json;
|
||||
}
|
||||
|
||||
template <typename T, size_t Count>
|
||||
std::array<T, Count> fixed_table_for_json_t(const phosg::JSON& table_json) {
|
||||
std::array<T, Count> ret;
|
||||
for (size_t y = 0; y < Count; y++) {
|
||||
ret[y] = table_json.at(y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, size_t RowCount, size_t RowSize>
|
||||
std::array<std::array<T, RowSize>, RowCount> fixed_table_for_json_t(const phosg::JSON& table_json) {
|
||||
std::array<std::array<T, RowSize>, RowCount> ret;
|
||||
for (size_t y = 0; y < RowCount; y++) {
|
||||
const auto& row_json = table_json.at(y);
|
||||
for (size_t x = 0; x < RowSize; x++) {
|
||||
ret[y][x] = row_json.at(x);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, size_t Count>
|
||||
phosg::JSON json_for_fixed_table_t(const std::array<T, Count>& table) {
|
||||
auto ret = phosg::JSON::list();
|
||||
for (const auto& cell : table) {
|
||||
ret.emplace_back(cell.json());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, size_t RowCount, size_t RowSize>
|
||||
phosg::JSON json_for_fixed_table_t(const std::array<std::array<T, RowSize>, RowCount>& table) {
|
||||
auto table_json = phosg::JSON::list();
|
||||
for (const auto& row : table) {
|
||||
auto row_json = phosg::JSON::list();
|
||||
for (const auto& cell : row) {
|
||||
row_json.emplace_back(cell.json());
|
||||
}
|
||||
table_json.emplace_back(std::move(row_json));
|
||||
}
|
||||
return table_json;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Armor shop set
|
||||
|
||||
template <bool BE>
|
||||
struct ArmorSubRootT {
|
||||
TableSpecT<BE> armor_table; // -> WeightTableEntry8[...][...]
|
||||
TableSpecT<BE> shield_table; // -> WeightTableEntry8[...][...]
|
||||
TableSpecT<BE> unit_table; // -> WeightTableEntry8[...][...]
|
||||
} __packed_ws_be__(ArmorSubRootT, 0x18);
|
||||
|
||||
template <bool BE>
|
||||
struct ArmorRootT {
|
||||
U32T<BE> subroot; // -> ArmorSubRootT<BE>
|
||||
} __packed_ws_be__(ArmorRootT, 4);
|
||||
|
||||
ArmorShopRandomSet::ArmorShopRandomSet(const void* data, size_t size, bool big_endian) {
|
||||
if (big_endian) {
|
||||
this->parse_t<true>(data, size);
|
||||
} else {
|
||||
this->parse_t<false>(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
ArmorShopRandomSet::ArmorShopRandomSet(const std::string& data, bool big_endian)
|
||||
: ArmorShopRandomSet(data.data(), data.size(), big_endian) {}
|
||||
|
||||
ArmorShopRandomSet::ArmorShopRandomSet(const phosg::JSON& json) {
|
||||
this->armor_table = table_for_json_t<IntPairT<uint8_t>>(json.at("ArmorTable"));
|
||||
this->shield_table = table_for_json_t<IntPairT<uint8_t>>(json.at("ShieldTable"));
|
||||
this->unit_table = table_for_json_t<IntPairT<uint8_t>>(json.at("UnitTable"));
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
void ArmorShopRandomSet::parse_t(const void* data, size_t size) {
|
||||
std::set<uint32_t> start_offsets;
|
||||
|
||||
phosg::StringReader r(data, size);
|
||||
uint32_t root_offset = r.pget<U32T<BE>>(size - 0x10);
|
||||
start_offsets.emplace(root_offset);
|
||||
const auto& root = r.pget<ArmorRootT<BE>>(root_offset);
|
||||
start_offsets.emplace(root.subroot);
|
||||
const auto& subroot = r.pget<ArmorSubRootT<BE>>(root.subroot);
|
||||
start_offsets.emplace(subroot.armor_table.offset);
|
||||
start_offsets.emplace(subroot.shield_table.offset);
|
||||
start_offsets.emplace(subroot.unit_table.offset);
|
||||
|
||||
this->armor_table = parse_table_t<IntPairT<uint8_t>>(
|
||||
r, subroot.armor_table.offset, subroot.armor_table.row_size, start_offsets);
|
||||
this->shield_table = parse_table_t<IntPairT<uint8_t>>(
|
||||
r, subroot.shield_table.offset, subroot.shield_table.row_size, start_offsets);
|
||||
this->unit_table = parse_table_t<IntPairT<uint8_t>>(
|
||||
r, subroot.unit_table.offset, subroot.unit_table.row_size, start_offsets);
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
std::string ArmorShopRandomSet::serialize_binary_t() const {
|
||||
RELFileWriter<BE> rel;
|
||||
|
||||
ArmorSubRootT<BE> subroot;
|
||||
subroot.armor_table = serialize_table_t<IntPairT<uint8_t>>(rel, this->armor_table);
|
||||
subroot.shield_table = serialize_table_t<IntPairT<uint8_t>>(rel, this->shield_table);
|
||||
subroot.unit_table = serialize_table_t<IntPairT<uint8_t>>(rel, this->unit_table);
|
||||
|
||||
ArmorRootT<BE> root;
|
||||
rel.align(4);
|
||||
root.subroot = rel.put(subroot);
|
||||
rel.relocations.emplace(rel.w.size() - 0x18);
|
||||
rel.relocations.emplace(rel.w.size() - 0x10);
|
||||
rel.relocations.emplace(rel.w.size() - 0x08);
|
||||
|
||||
uint32_t root_offset = rel.put(root);
|
||||
rel.relocations.emplace(rel.w.size() - 4);
|
||||
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
std::string ArmorShopRandomSet::serialize_binary(bool big_endian) const {
|
||||
return big_endian ? this->serialize_binary_t<true>() : this->serialize_binary_t<false>();
|
||||
}
|
||||
|
||||
phosg::JSON ArmorShopRandomSet::json() const {
|
||||
return phosg::JSON::dict({
|
||||
{"ArmorTable", json_for_table_t(this->armor_table)},
|
||||
{"ShieldTable", json_for_table_t(this->shield_table)},
|
||||
{"UnitTable", json_for_table_t(this->unit_table)},
|
||||
});
|
||||
}
|
||||
|
||||
void ArmorShopRandomSet::print(FILE* stream) const {
|
||||
phosg::fwrite_fmt(stream, "ArmorShopRandomSet\n");
|
||||
phosg::fwrite_fmt(stream, " Armor table\n");
|
||||
print_table_2d(stream, this->armor_table);
|
||||
phosg::fwrite_fmt(stream, " Shield table\n");
|
||||
print_table_2d(stream, this->shield_table);
|
||||
phosg::fwrite_fmt(stream, " Unit table\n");
|
||||
print_table_2d(stream, this->unit_table);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tool shop set
|
||||
|
||||
ToolShopRandomSet::TechDiskLevelEntry::TechDiskLevelEntry(const phosg::JSON& json) {
|
||||
if (json.contains("PlayerLevelDivisor")) {
|
||||
this->mode = Mode::PLAYER_LEVEL_DIVISOR;
|
||||
this->player_level_divisor_or_min_level = json.get_int("PlayerLevelDivisor");
|
||||
this->max_level = 0;
|
||||
} else if (json.contains("MinLevel")) {
|
||||
this->mode = Mode::RANDOM_IN_RANGE;
|
||||
this->player_level_divisor_or_min_level = json.get_int("MinLevel");
|
||||
this->max_level = json.get_int("MaxLevel");
|
||||
} else {
|
||||
this->mode = Mode::LEVEL_1;
|
||||
this->player_level_divisor_or_min_level = 0;
|
||||
this->max_level = 0;
|
||||
}
|
||||
}
|
||||
|
||||
phosg::JSON ToolShopRandomSet::TechDiskLevelEntry::json() const {
|
||||
switch (this->mode) {
|
||||
case Mode::LEVEL_1:
|
||||
return phosg::JSON::dict();
|
||||
case Mode::PLAYER_LEVEL_DIVISOR:
|
||||
return phosg::JSON::dict({{"PlayerLevelDivisor", this->player_level_divisor_or_min_level}});
|
||||
case Mode::RANDOM_IN_RANGE:
|
||||
return phosg::JSON::dict({{"MinLevel", this->player_level_divisor_or_min_level}, {"MaxLevel", this->max_level}});
|
||||
default:
|
||||
throw std::runtime_error("Invalid TechDiskLevelEntry mode");
|
||||
}
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
struct ToolSubRootT {
|
||||
TableSpecT<BE> rare_recovery_table; // -> WeightTableEntry8[...][...]
|
||||
TableSpecT<BE> tech_disk_table; // -> WeightTableEntry8[...][...]
|
||||
} __packed_ws_be__(ToolSubRootT, 0x10);
|
||||
|
||||
template <bool BE>
|
||||
struct ToolRootT {
|
||||
U32T<BE> common_recovery_table; // -> TableSpecT<BE> -> WeightTableEntry8[...][...]
|
||||
U32T<BE> subroot; // -> ToolSubRootT<BE>
|
||||
U32T<BE> tech_disk_level_table; // -> TableSpecT<BE> -> TechDiskLevelEntry[...][...]
|
||||
} __packed_ws_be__(ToolRootT, 0x0C);
|
||||
|
||||
ToolShopRandomSet::ToolShopRandomSet(const void* data, size_t size, bool big_endian) {
|
||||
if (big_endian) {
|
||||
this->parse_t<true>(data, size);
|
||||
} else {
|
||||
this->parse_t<false>(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::pair<uint8_t, uint8_t>> ToolShopRandomSet::item_defs{
|
||||
{0x00, 0x00}, // 00 -> Monomate
|
||||
{0x00, 0x01}, // 01 -> Dimate
|
||||
{0x00, 0x02}, // 02 -> Trimate
|
||||
{0x01, 0x00}, // 03 -> Monofluid
|
||||
{0x01, 0x01}, // 04 -> Difluid
|
||||
{0x01, 0x02}, // 05 -> Trifluid
|
||||
{0x06, 0x00}, // 06 -> Antidote
|
||||
{0x06, 0x01}, // 07 -> Antiparalysis
|
||||
{0x03, 0x00}, // 08 -> Sol Atomizer
|
||||
{0x04, 0x00}, // 09 -> Moon Atomizer
|
||||
{0x05, 0x00}, // 0A -> Star Atomizer
|
||||
{0x07, 0x00}, // 0B -> Telepipe
|
||||
{0x08, 0x00}, // 0C -> Trap Vision
|
||||
{0x09, 0x00}, // 0D -> Scape Doll
|
||||
{0x0A, 0x00}, // 0E -> Monogrinder
|
||||
{0xFF, 0xFF}, // 0F -> Nothing
|
||||
};
|
||||
|
||||
const std::array<uint8_t, 0x13> ToolShopRandomSet::tech_num_map{
|
||||
0x00, 0x03, 0x06, 0x0F, 0x10, 0x0D, 0x0A, 0x0B, 0x0C, 0x01, 0x04, 0x07, 0x0E, 0x11, 0x02, 0x05, 0x08, 0x09, 0x12};
|
||||
|
||||
ToolShopRandomSet::ToolShopRandomSet(const std::string& data, bool big_endian)
|
||||
: ToolShopRandomSet(data.data(), data.size(), big_endian) {}
|
||||
|
||||
ToolShopRandomSet::ToolShopRandomSet(const phosg::JSON& json) {
|
||||
this->common_recovery_table = table_for_json_t<uint8_t>(json.at("CommonRecoveryTable"));
|
||||
this->rare_recovery_table = table_for_json_t<IntPairT<uint8_t>>(json.at("RareRecoveryTable"));
|
||||
this->tech_disk_table = table_for_json_t<IntPairT<uint8_t>>(json.at("TechDiskTable"));
|
||||
this->tech_disk_level_table = table_for_json_t<TechDiskLevelEntry>(json.at("TechDiskLevelTable"));
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
void ToolShopRandomSet::parse_t(const void* data, size_t size) {
|
||||
std::set<uint32_t> start_offsets;
|
||||
|
||||
phosg::StringReader r(data, size);
|
||||
uint32_t root_offset = r.pget<U32T<BE>>(size - 0x10);
|
||||
start_offsets.emplace(root_offset);
|
||||
|
||||
const auto& root = r.pget<ToolRootT<BE>>(root_offset);
|
||||
start_offsets.emplace(root.common_recovery_table);
|
||||
start_offsets.emplace(root.subroot);
|
||||
start_offsets.emplace(root.tech_disk_level_table);
|
||||
|
||||
const auto& common_recovery_table_spec = r.pget<TableSpecT<BE>>(root.common_recovery_table);
|
||||
start_offsets.emplace(common_recovery_table_spec.offset);
|
||||
|
||||
const auto& subroot = r.pget<ToolSubRootT<BE>>(root.subroot);
|
||||
start_offsets.emplace(subroot.rare_recovery_table.offset);
|
||||
start_offsets.emplace(subroot.tech_disk_table.offset);
|
||||
|
||||
const auto& tech_disk_level_table_spec = r.pget<TableSpecT<BE>>(root.tech_disk_level_table);
|
||||
start_offsets.emplace(tech_disk_level_table_spec.offset);
|
||||
|
||||
this->common_recovery_table = parse_table_t<uint8_t>(
|
||||
r, common_recovery_table_spec.offset, common_recovery_table_spec.row_size, start_offsets);
|
||||
this->rare_recovery_table = parse_table_t<IntPairT<uint8_t>>(
|
||||
r, subroot.rare_recovery_table.offset, subroot.rare_recovery_table.row_size, start_offsets);
|
||||
this->tech_disk_table = parse_table_t<IntPairT<uint8_t>>(
|
||||
r, subroot.tech_disk_table.offset, subroot.tech_disk_table.row_size, start_offsets);
|
||||
this->tech_disk_level_table = parse_table_t<TechDiskLevelEntry>(
|
||||
r, tech_disk_level_table_spec.offset, tech_disk_level_table_spec.row_size, start_offsets);
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
std::string ToolShopRandomSet::serialize_binary_t() const {
|
||||
RELFileWriter<BE> rel;
|
||||
|
||||
ToolSubRootT<BE> subroot;
|
||||
auto common_recovery_table_spec = serialize_table_t<uint8_t>(rel, this->common_recovery_table);
|
||||
subroot.rare_recovery_table = serialize_table_t<IntPairT<uint8_t>>(rel, this->rare_recovery_table);
|
||||
subroot.tech_disk_table = serialize_table_t<IntPairT<uint8_t>>(rel, this->tech_disk_table);
|
||||
auto tech_disk_level_table_spec = serialize_table_t<TechDiskLevelEntry>(rel, this->tech_disk_level_table);
|
||||
|
||||
rel.align(4);
|
||||
ToolRootT<BE> root;
|
||||
root.subroot = rel.put(subroot);
|
||||
rel.relocations.emplace(rel.w.size() - 0x10);
|
||||
rel.relocations.emplace(rel.w.size() - 0x08);
|
||||
root.common_recovery_table = rel.put(common_recovery_table_spec);
|
||||
rel.relocations.emplace(rel.w.size() - 0x08);
|
||||
root.tech_disk_level_table = rel.put(tech_disk_level_table_spec);
|
||||
rel.relocations.emplace(rel.w.size() - 0x08);
|
||||
|
||||
uint32_t root_offset = rel.put(root);
|
||||
rel.relocations.emplace(rel.w.size() - 0x0C);
|
||||
rel.relocations.emplace(rel.w.size() - 0x08);
|
||||
rel.relocations.emplace(rel.w.size() - 0x04);
|
||||
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
std::string ToolShopRandomSet::serialize_binary(bool big_endian) const {
|
||||
return big_endian ? this->serialize_binary_t<true>() : this->serialize_binary_t<false>();
|
||||
}
|
||||
|
||||
phosg::JSON ToolShopRandomSet::json() const {
|
||||
return phosg::JSON::dict({
|
||||
{"CommonRecoveryTable", json_for_table_t(this->common_recovery_table)},
|
||||
{"RareRecoveryTable", json_for_table_t(this->rare_recovery_table)},
|
||||
{"TechDiskTable", json_for_table_t(this->tech_disk_table)},
|
||||
{"TechDiskLevelTable", json_for_table_t(this->tech_disk_level_table)},
|
||||
});
|
||||
}
|
||||
|
||||
void ToolShopRandomSet::print(FILE* stream) const {
|
||||
phosg::fwrite_fmt(stream, "ToolShopRandomSet\n");
|
||||
|
||||
phosg::fwrite_fmt(stream, " Common recovery table\n");
|
||||
for (size_t z = 0; z < this->common_recovery_table.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", z);
|
||||
for (uint8_t cell : this->common_recovery_table[z]) {
|
||||
if (cell == 0x0F) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} (------)", cell);
|
||||
} else {
|
||||
const auto& def = this->item_defs.at(cell);
|
||||
phosg::fwrite_fmt(stream, " {:02X} (03{:02X}{:02X})", cell, def.first, def.second);
|
||||
}
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
|
||||
phosg::fwrite_fmt(stream, " Rare recovery table\n");
|
||||
for (size_t z = 0; z < this->rare_recovery_table.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", z);
|
||||
for (const auto& cell : this->rare_recovery_table[z]) {
|
||||
if (cell.value == 0x0F) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} (------) @ {:03}", cell.value, cell.weight);
|
||||
} else {
|
||||
const auto& def = this->item_defs.at(cell.value);
|
||||
phosg::fwrite_fmt(stream, " {:02X} (03{:02X}{:02X}) @ {:03}", cell.value, def.first, def.second, cell.weight);
|
||||
}
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
|
||||
phosg::fwrite_fmt(stream, " Tech disk table\n");
|
||||
for (size_t z = 0; z < this->tech_disk_table.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", z);
|
||||
for (const auto& cell : this->tech_disk_table[z]) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}({:>8}) @ {:03}",
|
||||
cell.first, name_for_technique(this->tech_num_map.at(cell.value)), cell.second);
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
|
||||
phosg::fwrite_fmt(stream, " Tech disk level table\n");
|
||||
phosg::fwrite_fmt(stream, " ");
|
||||
for (const auto& tech_num : this->tech_num_map) {
|
||||
phosg::fwrite_fmt(stream, " {:<9}", name_for_technique(tech_num));
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
for (size_t z = 0; z < this->tech_disk_level_table.size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", z);
|
||||
for (const auto& cell : this->tech_disk_level_table[z]) {
|
||||
switch (cell.mode) {
|
||||
case TechDiskLevelEntry::Mode::LEVEL_1:
|
||||
phosg::fwrite_fmt(stream, " LEVEL_1 ");
|
||||
break;
|
||||
case TechDiskLevelEntry::Mode::PLAYER_LEVEL_DIVISOR:
|
||||
phosg::fwrite_fmt(stream, " PLV / {:03}", cell.player_level_divisor_or_min_level);
|
||||
break;
|
||||
case TechDiskLevelEntry::Mode::RANDOM_IN_RANGE:
|
||||
phosg::fwrite_fmt(stream, " {:03} - {:03}", cell.player_level_divisor_or_min_level, cell.max_level);
|
||||
break;
|
||||
}
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
std::vector<std::vector<TechDiskLevelEntry>> tech_disk_level_table;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Weapon shop set
|
||||
|
||||
template <bool BE>
|
||||
struct RangeTableEntryT {
|
||||
U32T<BE> min;
|
||||
U32T<BE> max;
|
||||
} __packed_ws_be__(RangeTableEntryT, 8);
|
||||
|
||||
template <bool BE>
|
||||
struct WeaponRootT {
|
||||
U32T<BE> weapon_type_table; // {c, o -> (table)}[...(offsets)]
|
||||
U32T<BE> bonus_type_table1; // {u32 value, u32 weight}[9][6]
|
||||
U32T<BE> bonus_type_table2; // {u32 value, u32 weight}[9][6]
|
||||
U32T<BE> bonus_range_table1; // {u32 min_index, u32 max_index}[9]
|
||||
U32T<BE> bonus_range_table2; // {u32 min_index, u32 max_index}[9]
|
||||
U32T<BE> special_mode_table; // {u32 value, u32 weight}[8][3]
|
||||
U32T<BE> default_grind_range_table; // {u32 min, u32 max}[6]
|
||||
U32T<BE> favored_grind_range_table; // {u32 min, u32 max}[6]
|
||||
} __packed_ws_be__(WeaponRootT, 0x20);
|
||||
|
||||
const std::array<std::pair<uint8_t, uint8_t>, 0x48> WeaponShopRandomSet::type_defs({
|
||||
/* 00 */ {0x01, 0x00}, // Saber
|
||||
/* 01 */ {0x01, 0x01}, // Brand
|
||||
/* 02 */ {0x01, 0x02}, // Buster
|
||||
/* 03 */ {0x01, 0x03}, // Pallasch
|
||||
/* 04 */ {0x01, 0x04}, // Gladius
|
||||
/* 05 */ {0x03, 0x00}, // Dagger
|
||||
/* 06 */ {0x03, 0x01}, // Knife
|
||||
/* 07 */ {0x03, 0x02}, // Blade
|
||||
/* 08 */ {0x03, 0x03}, // Edge
|
||||
/* 09 */ {0x03, 0x04}, // Ripper
|
||||
/* 0A */ {0x02, 0x00}, // Sword
|
||||
/* 0B */ {0x02, 0x01}, // Gigush
|
||||
/* 0C */ {0x02, 0x02}, // Breaker
|
||||
/* 0D */ {0x02, 0x03}, // Claymore
|
||||
/* 0E */ {0x02, 0x04}, // Calibur
|
||||
/* 0F */ {0x05, 0x00}, // Slicer
|
||||
/* 10 */ {0x05, 0x01}, // Spinner
|
||||
/* 11 */ {0x05, 0x02}, // Cutter
|
||||
/* 12 */ {0x05, 0x03}, // Sawcer
|
||||
/* 13 */ {0x05, 0x04}, // Diska
|
||||
/* 14 */ {0x04, 0x00}, // Partisan
|
||||
/* 15 */ {0x04, 0x01}, // Halbert
|
||||
/* 16 */ {0x04, 0x02}, // Glaive
|
||||
/* 17 */ {0x04, 0x03}, // Berdys
|
||||
/* 18 */ {0x04, 0x04}, // Gungnir
|
||||
/* 19 */ {0x06, 0x00}, // Handgun
|
||||
/* 1A */ {0x06, 0x01}, // Autogun
|
||||
/* 1B */ {0x06, 0x02}, // Lockgun
|
||||
/* 1C */ {0x06, 0x03}, // Railgun
|
||||
/* 1D */ {0x06, 0x04}, // Raygun
|
||||
/* 1E */ {0x07, 0x00}, // Rifle
|
||||
/* 1F */ {0x07, 0x01}, // Sniper
|
||||
/* 20 */ {0x07, 0x02}, // Blaster
|
||||
/* 21 */ {0x07, 0x03}, // Beam
|
||||
/* 22 */ {0x07, 0x04}, // Laser
|
||||
/* 23 */ {0x08, 0x00}, // Mechgun
|
||||
/* 24 */ {0x08, 0x01}, // Assault
|
||||
/* 25 */ {0x08, 0x02}, // Repeater
|
||||
/* 26 */ {0x08, 0x03}, // Gatling
|
||||
/* 27 */ {0x08, 0x04}, // Vulcan
|
||||
/* 28 */ {0x09, 0x00}, // Shot
|
||||
/* 29 */ {0x09, 0x01}, // Spread
|
||||
/* 2A */ {0x09, 0x02}, // Cannon
|
||||
/* 2B */ {0x09, 0x03}, // Launcher
|
||||
/* 2C */ {0x09, 0x04}, // Arms
|
||||
/* 2D */ {0x0A, 0x00}, // Cane
|
||||
/* 2E */ {0x0A, 0x01}, // Stick
|
||||
/* 2F */ {0x0A, 0x02}, // Mace
|
||||
/* 30 */ {0x0A, 0x03}, // Club
|
||||
/* 31 */ {0x0B, 0x00}, // Rod
|
||||
/* 32 */ {0x0B, 0x01}, // Pole
|
||||
/* 33 */ {0x0B, 0x02}, // Pillar
|
||||
/* 34 */ {0x0B, 0x03}, // Striker
|
||||
/* 35 */ {0x0C, 0x00}, // Wand
|
||||
/* 36 */ {0x0C, 0x01}, // Staff
|
||||
/* 37 */ {0x0C, 0x02}, // Baton
|
||||
/* 38 */ {0x0C, 0x03}, // Scepter
|
||||
/* 39 */ {0xFF, 0xFF}, // Special-cased in type_defs_39 (depends on section ID)
|
||||
/* 3A */ {0xFF, 0xFF}, // Special-cased in type_defs_3A (depends on section ID)
|
||||
/* 3B */ {0x01, 0x05}, // DB'S SABER
|
||||
/* 3C */ {0x02, 0x05}, // FLOWEN'S SWORD
|
||||
/* 3D */ {0x06, 0x05}, // VARISTA
|
||||
/* 3E */ {0x08, 0x05}, // M&A60 VISE
|
||||
/* 3F */ {0x0A, 0x04}, // CLUB OF LACONIUM
|
||||
/* 40 */ {0x0C, 0x04}, // FIRE SCEPTER:AGNI
|
||||
/* 41 */ {0x0B, 0x04}, // BATTLE VERGE
|
||||
/* 42 */ {0x01, 0x06}, // KALADBOLG
|
||||
/* 43 */ {0x03, 0x05}, // BLADE DANCE
|
||||
/* 44 */ {0x07, 0x05}, // VISK-235W
|
||||
/* 45 */ {0x0A, 0x05}, // MACE OF ADAMAN
|
||||
/* 46 */ {0x0C, 0x05}, // ICE STAFF:DAGON
|
||||
/* 47 */ {0x0B, 0x05}, // BRAVE HAMMER
|
||||
});
|
||||
|
||||
const std::array<std::pair<uint8_t, uint8_t>, 10> WeaponShopRandomSet::type_defs_39({
|
||||
// Indexed by section_id
|
||||
{0x28, 0x00}, // HARISEN BATTLE FAN
|
||||
{0x2A, 0x00}, // AKIKO'S WOK
|
||||
{0x2B, 0x00}, // TOY HAMMER
|
||||
{0x35, 0x00}, // CRAZY TUNE
|
||||
{0x52, 0x00}, // FLOWER CANE
|
||||
{0x48, 0x00}, // SAMBA MARACAS
|
||||
{0x64, 0x00}, // CHAMELEON SCYTHE
|
||||
{0x59, 0x00}, // BROOM
|
||||
{0x8A, 0x00}, // SANGE
|
||||
{0x99, 0x00}, // ANGEL HARP
|
||||
});
|
||||
|
||||
const std::array<std::pair<uint8_t, uint8_t>, 10> WeaponShopRandomSet::type_defs_3A({
|
||||
// Indexed by section_id
|
||||
{0x99, 0x00}, // ANGEL HARP
|
||||
{0x64, 0x00}, // CHAMELEON SCYTHE
|
||||
{0x8A, 0x00}, // SANGE
|
||||
{0x28, 0x00}, // HARISEN BATTLE FAN
|
||||
{0x59, 0x00}, // BROOM
|
||||
{0x2B, 0x00}, // TOY HAMMER
|
||||
{0x52, 0x00}, // FLOWER CANE
|
||||
{0x2A, 0x00}, // AKIKO'S WOK
|
||||
{0x48, 0x00}, // SAMBA MARACAS
|
||||
{0x35, 0x00}, // CRAZY TUNE
|
||||
});
|
||||
|
||||
const std::array<int8_t, 20> WeaponShopRandomSet::bonus_values{
|
||||
-50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50};
|
||||
|
||||
WeaponShopRandomSet::WeaponShopRandomSet(const void* data, size_t size, bool big_endian) {
|
||||
if (big_endian) {
|
||||
this->parse_t<true>(data, size);
|
||||
} else {
|
||||
this->parse_t<false>(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
WeaponShopRandomSet::WeaponShopRandomSet(const std::string& data, bool big_endian)
|
||||
: WeaponShopRandomSet(data.data(), data.size(), big_endian) {}
|
||||
|
||||
WeaponShopRandomSet::WeaponShopRandomSet(const phosg::JSON& json) {
|
||||
for (const auto& it : json.get_list("WeaponTypeWeightTables")) {
|
||||
this->weapon_type_weight_tables.emplace_back(table_for_json_t<IntPairT<uint8_t>>(*it));
|
||||
}
|
||||
this->bonus_type_table1 = fixed_table_for_json_t<IntPairT<uint32_t>, 9, 6>(json.at("BonusTypeTable1"));
|
||||
this->bonus_type_table2 = fixed_table_for_json_t<IntPairT<uint32_t>, 9, 6>(json.at("BonusTypeTable2"));
|
||||
this->bonus_range_table1 = fixed_table_for_json_t<IntPairT<uint32_t>, 9>(json.at("BonusRangeTable1"));
|
||||
this->bonus_range_table2 = fixed_table_for_json_t<IntPairT<uint32_t>, 9>(json.at("BonusRangeTable2"));
|
||||
this->special_mode_table = fixed_table_for_json_t<IntPairT<uint32_t>, 8, 3>(json.at("SpecialModeTable"));
|
||||
this->default_grind_range_table = fixed_table_for_json_t<IntPairT<uint32_t>, 6>(json.at("DefaultDringRangeTable"));
|
||||
this->favored_grind_range_table = fixed_table_for_json_t<IntPairT<uint32_t>, 6>(json.at("FavoredDringRangeTable"));
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
void WeaponShopRandomSet::parse_t(const void* data, size_t size) {
|
||||
std::set<uint32_t> start_offsets;
|
||||
|
||||
phosg::StringReader r(data, size);
|
||||
uint32_t root_offset = r.pget<U32T<BE>>(size - 0x10);
|
||||
start_offsets.emplace(root_offset);
|
||||
|
||||
const auto& root = r.pget<WeaponRootT<BE>>(root_offset);
|
||||
start_offsets.emplace(root.weapon_type_table);
|
||||
start_offsets.emplace(root.bonus_type_table1);
|
||||
start_offsets.emplace(root.bonus_type_table2);
|
||||
start_offsets.emplace(root.bonus_range_table1);
|
||||
start_offsets.emplace(root.bonus_range_table2);
|
||||
start_offsets.emplace(root.special_mode_table);
|
||||
start_offsets.emplace(root.default_grind_range_table);
|
||||
start_offsets.emplace(root.favored_grind_range_table);
|
||||
|
||||
// Count the weapon types tables
|
||||
if (start_offsets.upper_bound(root.weapon_type_table) == start_offsets.end()) {
|
||||
throw std::runtime_error("Weapon type table is out of range");
|
||||
}
|
||||
for (uint32_t offset = root.weapon_type_table;
|
||||
offset < *start_offsets.upper_bound(root.weapon_type_table);
|
||||
offset += sizeof(TableSpecT<BE>)) {
|
||||
start_offsets.emplace(r.pget<TableSpecT<BE>>(offset).offset);
|
||||
}
|
||||
size_t num_weapon_types_tables =
|
||||
(*start_offsets.upper_bound(root.weapon_type_table) - root.weapon_type_table) / sizeof(TableSpecT<BE>);
|
||||
|
||||
while (this->weapon_type_weight_tables.size() < num_weapon_types_tables) {
|
||||
const auto& spec = r.pget<TableSpecT<BE>>(
|
||||
root.weapon_type_table + this->weapon_type_weight_tables.size() * sizeof(TableSpecT<BE>));
|
||||
this->weapon_type_weight_tables.emplace_back(parse_table_t<IntPairT<uint8_t>>(
|
||||
r, spec.offset, spec.row_size, start_offsets));
|
||||
}
|
||||
|
||||
auto parse_fixed_table_into_1d = [&]<size_t Count>(std::array<IntPairT<uint32_t>, Count>& ret, uint32_t offset) -> void {
|
||||
auto sub_r = r.sub(offset, sizeof(IntPairT<uint32_t>) * Count);
|
||||
for (size_t z = 0; z < Count; z++) {
|
||||
ret[z] = sub_r.get<IntPairT<U32T<BE>>>();
|
||||
}
|
||||
};
|
||||
auto parse_fixed_table_into_2d = [&]<size_t RowSize, size_t RowCount>(std::array<std::array<IntPairT<uint32_t>, RowSize>, RowCount>& ret, uint32_t offset) -> void {
|
||||
auto sub_r = r.sub(offset, sizeof(IntPairT<uint32_t>) * RowSize * RowCount);
|
||||
for (size_t y = 0; y < RowCount; y++) {
|
||||
for (size_t x = 0; x < RowSize; x++) {
|
||||
ret[y][x] = sub_r.get<IntPairT<U32T<BE>>>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parse_fixed_table_into_2d(this->bonus_type_table1, root.bonus_type_table1);
|
||||
parse_fixed_table_into_2d(this->bonus_type_table2, root.bonus_type_table2);
|
||||
parse_fixed_table_into_1d(this->bonus_range_table1, root.bonus_range_table1);
|
||||
parse_fixed_table_into_1d(this->bonus_range_table2, root.bonus_range_table2);
|
||||
parse_fixed_table_into_2d(this->special_mode_table, root.special_mode_table);
|
||||
parse_fixed_table_into_1d(this->default_grind_range_table, root.default_grind_range_table);
|
||||
parse_fixed_table_into_1d(this->favored_grind_range_table, root.favored_grind_range_table);
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
std::string WeaponShopRandomSet::serialize_binary_t() const {
|
||||
RELFileWriter<BE> rel;
|
||||
|
||||
WeaponRootT<BE> root;
|
||||
std::vector<TableSpecT<BE>> weapon_type_weight_table_specs;
|
||||
weapon_type_weight_table_specs.reserve(this->weapon_type_weight_tables.size());
|
||||
for (const auto& table : this->weapon_type_weight_tables) {
|
||||
weapon_type_weight_table_specs.emplace_back(serialize_table_t<IntPairT<uint8_t>>(rel, table));
|
||||
}
|
||||
|
||||
root.weapon_type_table = rel.w.size();
|
||||
for (const auto& spec : weapon_type_weight_table_specs) {
|
||||
rel.put(spec);
|
||||
rel.relocations.emplace(rel.w.size() - 8);
|
||||
}
|
||||
|
||||
auto serialize_fixed_table_1d = [&]<size_t Count>(const std::array<IntPairT<uint32_t>, Count>& table) -> uint32_t {
|
||||
uint32_t ret = rel.w.size();
|
||||
for (size_t z = 0; z < Count; z++) {
|
||||
rel.template put<IntPairT<U32T<BE>>>(table[z]);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
auto serialize_fixed_table_2d = [&]<size_t RowSize, size_t RowCount>(const std::array<std::array<IntPairT<uint32_t>, RowSize>, RowCount>& table) -> uint32_t {
|
||||
uint32_t ret = rel.w.size();
|
||||
for (size_t y = 0; y < RowCount; y++) {
|
||||
for (size_t x = 0; x < RowSize; x++) {
|
||||
rel.template put<IntPairT<U32T<BE>>>(table[y][x]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
rel.align(4);
|
||||
root.bonus_type_table1 = serialize_fixed_table_2d(this->bonus_type_table1);
|
||||
root.bonus_type_table2 = serialize_fixed_table_2d(this->bonus_type_table2);
|
||||
root.special_mode_table = serialize_fixed_table_2d(this->special_mode_table);
|
||||
root.bonus_range_table1 = serialize_fixed_table_1d(this->bonus_range_table1);
|
||||
root.bonus_range_table2 = serialize_fixed_table_1d(this->bonus_range_table2);
|
||||
root.default_grind_range_table = serialize_fixed_table_1d(this->default_grind_range_table);
|
||||
root.favored_grind_range_table = serialize_fixed_table_1d(this->favored_grind_range_table);
|
||||
|
||||
rel.align(4);
|
||||
uint32_t root_offset = rel.put(root);
|
||||
for (size_t z = 1; z <= 8; z++) {
|
||||
rel.relocations.emplace(rel.w.size() - (z * 4));
|
||||
}
|
||||
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
std::string WeaponShopRandomSet::serialize_binary(bool big_endian) const {
|
||||
return big_endian ? this->serialize_binary_t<true>() : this->serialize_binary_t<false>();
|
||||
}
|
||||
|
||||
phosg::JSON WeaponShopRandomSet::json() const {
|
||||
auto weapon_type_weight_tables_json = phosg::JSON::list();
|
||||
for (const auto& table : this->weapon_type_weight_tables) {
|
||||
weapon_type_weight_tables_json.emplace_back(json_for_table_t(table));
|
||||
}
|
||||
|
||||
return phosg::JSON::dict({
|
||||
{"WeaponTypeWeightTables", std::move(weapon_type_weight_tables_json)},
|
||||
{"BonusTypeTable1", json_for_fixed_table_t(this->bonus_type_table1)},
|
||||
{"BonusTypeTable2", json_for_fixed_table_t(this->bonus_type_table2)},
|
||||
{"BonusRangeTable1", json_for_fixed_table_t(this->bonus_range_table1)},
|
||||
{"BonusRangeTable2", json_for_fixed_table_t(this->bonus_range_table2)},
|
||||
{"SpecialModeTable", json_for_fixed_table_t(this->special_mode_table)},
|
||||
{"DefaultDringRangeTable", json_for_fixed_table_t(this->default_grind_range_table)},
|
||||
{"FavoredDringRangeTable", json_for_fixed_table_t(this->favored_grind_range_table)},
|
||||
});
|
||||
}
|
||||
|
||||
void WeaponShopRandomSet::print(FILE* stream) const {
|
||||
phosg::fwrite_fmt(stream, "WeaponShopRandomSet\n");
|
||||
for (size_t table_index = 0; table_index < this->weapon_type_weight_tables.size(); table_index++) {
|
||||
phosg::fwrite_fmt(stream, " Weapon type weight table {}\n", table_index);
|
||||
for (size_t z = 0; z < this->weapon_type_weight_tables[table_index].size(); z++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} ({:<10}):", z, name_for_section_id(z));
|
||||
for (const auto& cell : this->weapon_type_weight_tables[table_index][z]) {
|
||||
if (cell.value == 0x39) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} (SECID1) @ {:03}", cell.value, cell.weight);
|
||||
} else if (cell.value == 0x3A) {
|
||||
phosg::fwrite_fmt(stream, " {:02X} (SECID2) @ {:03}", cell.value, cell.weight);
|
||||
} else {
|
||||
const auto& def = this->type_defs.at(cell.value);
|
||||
phosg::fwrite_fmt(stream, " {:02X} (00{:02X}{:02X}) @ {:03}", cell.value, def.first, def.second, cell.weight);
|
||||
}
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
auto print_fixed_table_1d = [&]<size_t Count>(const std::array<IntPairT<uint32_t>, Count>& table) -> void {
|
||||
for (size_t z = 0; z < Count; z++) {
|
||||
const auto& cell = table[z];
|
||||
phosg::fwrite_fmt(stream, " {:02}: {:03}-{:03}\n", z, cell.first, cell.second);
|
||||
}
|
||||
};
|
||||
auto print_fixed_table_2d = [&]<size_t RowCount, size_t RowSize>(const std::array<std::array<IntPairT<uint32_t>, RowSize>, RowCount>& table) -> void {
|
||||
for (size_t y = 0; y < RowCount; y++) {
|
||||
phosg::fwrite_fmt(stream, " {:02X}:", y);
|
||||
for (size_t x = 0; x < RowSize; x++) {
|
||||
const auto& cell = table[y][x];
|
||||
phosg::fwrite_fmt(stream, " {:02} @ {:03}", cell.first, cell.second);
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
};
|
||||
|
||||
phosg::fwrite_fmt(stream, " Bonus type table 1\n");
|
||||
print_fixed_table_2d(this->bonus_type_table1);
|
||||
phosg::fwrite_fmt(stream, " Bonus type table 2\n");
|
||||
print_fixed_table_2d(this->bonus_type_table2);
|
||||
phosg::fwrite_fmt(stream, " Bonus range table 1\n");
|
||||
print_fixed_table_1d(this->bonus_range_table1);
|
||||
phosg::fwrite_fmt(stream, " Bonus range table 2\n");
|
||||
print_fixed_table_1d(this->bonus_range_table2);
|
||||
phosg::fwrite_fmt(stream, " Special mode table\n");
|
||||
print_fixed_table_2d(this->special_mode_table);
|
||||
phosg::fwrite_fmt(stream, " Default grind range table\n");
|
||||
print_fixed_table_1d(this->default_grind_range_table);
|
||||
phosg::fwrite_fmt(stream, " Favored grind range table\n");
|
||||
print_fixed_table_1d(this->favored_grind_range_table);
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <phosg/Encoding.hh>
|
||||
#include <phosg/JSON.hh>
|
||||
|
||||
#include "StaticGameData.hh"
|
||||
#include "Text.hh"
|
||||
#include "Types.hh"
|
||||
|
||||
struct ShopRandomSetBase {
|
||||
template <typename T>
|
||||
struct IntPairT {
|
||||
union {
|
||||
T first;
|
||||
T value;
|
||||
T min;
|
||||
} __attribute__((packed));
|
||||
union {
|
||||
T second;
|
||||
T weight;
|
||||
T max;
|
||||
} __attribute__((packed));
|
||||
|
||||
IntPairT() = default;
|
||||
|
||||
template <typename OtherT>
|
||||
IntPairT(const IntPairT<OtherT>& v) : first(v.first), second(v.second) {}
|
||||
|
||||
IntPairT(const phosg::JSON& v) : first(v.get_int(0)), second(v.get_int(1)) {}
|
||||
|
||||
phosg::JSON json() const {
|
||||
return phosg::JSON::list({this->first, this->second});
|
||||
}
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
struct ArmorShopRandomSet : ShopRandomSetBase {
|
||||
// This struct parses and accesses data from ArmorRandom.rel
|
||||
ArmorShopRandomSet(const void* data, size_t size, bool big_endian);
|
||||
ArmorShopRandomSet(const std::string& data, bool big_endian);
|
||||
explicit ArmorShopRandomSet(const phosg::JSON& json);
|
||||
|
||||
template <bool BE>
|
||||
void parse_t(const void* data, size_t size);
|
||||
template <bool BE>
|
||||
std::string serialize_binary_t() const;
|
||||
|
||||
std::string serialize_binary(bool big_endian) const;
|
||||
phosg::JSON json() const;
|
||||
|
||||
void print(FILE* stream) const;
|
||||
|
||||
std::vector<std::vector<IntPairT<uint8_t>>> armor_table;
|
||||
std::vector<std::vector<IntPairT<uint8_t>>> shield_table;
|
||||
std::vector<std::vector<IntPairT<uint8_t>>> unit_table;
|
||||
};
|
||||
|
||||
struct ToolShopRandomSet : ShopRandomSetBase {
|
||||
// This struct parses and accesses data from ToolRandom.rel
|
||||
struct TechDiskLevelEntry {
|
||||
enum class Mode : uint8_t {
|
||||
LEVEL_1 = 0,
|
||||
PLAYER_LEVEL_DIVISOR = 1,
|
||||
RANDOM_IN_RANGE = 2,
|
||||
};
|
||||
Mode mode;
|
||||
uint8_t player_level_divisor_or_min_level;
|
||||
uint8_t max_level;
|
||||
|
||||
TechDiskLevelEntry() = default;
|
||||
explicit TechDiskLevelEntry(const phosg::JSON& json);
|
||||
phosg::JSON json() const;
|
||||
} __packed_ws__(TechDiskLevelEntry, 3);
|
||||
|
||||
ToolShopRandomSet(const void* data, size_t size, bool big_endian);
|
||||
ToolShopRandomSet(const std::string& data, bool big_endian);
|
||||
explicit ToolShopRandomSet(const phosg::JSON& json);
|
||||
|
||||
template <bool BE>
|
||||
void parse_t(const void* data, size_t size);
|
||||
template <bool BE>
|
||||
std::string serialize_binary_t() const;
|
||||
|
||||
std::string serialize_binary(bool big_endian) const;
|
||||
phosg::JSON json() const;
|
||||
|
||||
void print(FILE* stream) const;
|
||||
|
||||
static const std::vector<std::pair<uint8_t, uint8_t>> item_defs;
|
||||
static const std::array<uint8_t, 0x13> tech_num_map;
|
||||
|
||||
std::vector<std::vector<uint8_t>> common_recovery_table;
|
||||
std::vector<std::vector<IntPairT<uint8_t>>> rare_recovery_table;
|
||||
std::vector<std::vector<IntPairT<uint8_t>>> tech_disk_table;
|
||||
std::vector<std::vector<TechDiskLevelEntry>> tech_disk_level_table;
|
||||
};
|
||||
|
||||
struct WeaponShopRandomSet : ShopRandomSetBase {
|
||||
// This struct parses and accesses data from WeaponRandom*.rel
|
||||
WeaponShopRandomSet(const void* data, size_t size, bool big_endian);
|
||||
WeaponShopRandomSet(const std::string& data, bool big_endian);
|
||||
explicit WeaponShopRandomSet(const phosg::JSON& json);
|
||||
|
||||
template <bool BE>
|
||||
void parse_t(const void* data, size_t size);
|
||||
template <bool BE>
|
||||
std::string serialize_binary_t() const;
|
||||
|
||||
std::string serialize_binary(bool big_endian) const;
|
||||
phosg::JSON json() const;
|
||||
|
||||
void print(FILE* stream) const;
|
||||
|
||||
static const std::array<std::pair<uint8_t, uint8_t>, 0x48> type_defs;
|
||||
static const std::array<std::pair<uint8_t, uint8_t>, 10> type_defs_39;
|
||||
static const std::array<std::pair<uint8_t, uint8_t>, 10> type_defs_3A;
|
||||
static const std::array<int8_t, 20> bonus_values;
|
||||
|
||||
std::vector<std::vector<std::vector<IntPairT<uint8_t>>>> weapon_type_weight_tables; // [table_index][section_id][entry_index]
|
||||
std::array<std::array<IntPairT<uint32_t>, 6>, 9> bonus_type_table1; // [table_index][entry_index]
|
||||
std::array<std::array<IntPairT<uint32_t>, 6>, 9> bonus_type_table2; // [table_index][entry_index]
|
||||
std::array<IntPairT<uint32_t>, 9> bonus_range_table1; // [table_index]
|
||||
std::array<IntPairT<uint32_t>, 9> bonus_range_table2; // [table_index]
|
||||
std::array<std::array<IntPairT<uint32_t>, 3>, 8> special_mode_table; // [table_index][entry_index]
|
||||
std::array<IntPairT<uint32_t>, 6> default_grind_range_table; // [table_index]
|
||||
std::array<IntPairT<uint32_t>, 6> favored_grind_range_table; // [table_index]
|
||||
};
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "TekkerAdjustmentSet.hh"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "CommonFileFormats.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "Types.hh"
|
||||
|
||||
static const std::array<int8_t, 11> delta_table = {-10, -5, -3, -2, -1, 0, 1, 2, 3, 5, 10};
|
||||
static const std::unordered_map<int8_t, size_t> reverse_delta_table = {
|
||||
{-10, 0}, {-5, 1}, {-3, 2}, {-2, 3}, {-1, 4}, {0, 5}, {1, 6}, {2, 7}, {3, 8}, {5, 9}, {10, 10}};
|
||||
|
||||
struct DeltaProbabilityEntry {
|
||||
uint8_t delta_index;
|
||||
uint8_t count_default;
|
||||
uint8_t count_favored;
|
||||
} __packed_ws__(DeltaProbabilityEntry, 3);
|
||||
|
||||
struct LuckTableEntry {
|
||||
uint8_t delta_index;
|
||||
int8_t luck;
|
||||
} __packed_ws__(LuckTableEntry, 2);
|
||||
|
||||
template <bool BE>
|
||||
struct ProbTableRefT {
|
||||
U32T<BE> offset;
|
||||
U32T<BE> count;
|
||||
} __packed_ws_be__(ProbTableRefT, 8);
|
||||
|
||||
template <bool BE>
|
||||
struct RootT {
|
||||
// Each section ID's favored weapon class has different probabilities than those used for all other weapons. The
|
||||
// tables are labeled with (D) for the default values and (F) for the favored-class values.
|
||||
|
||||
// Note that the favored bonuses for Redria are all zero; these values are unused because Redria does not have a
|
||||
// favored weapon type. Curiously, Yellowboze also does not have a favored weapon type, but the values for Yellowboze
|
||||
// are not all zero.
|
||||
|
||||
// This table specifies how likely a special is to be upgraded or downgraded by one level.
|
||||
// In PSO V3, the special upgrade table is:
|
||||
// Viridia => (D) +1=10%, 0=60%, -1=30%
|
||||
// Viridia => (F) +1=25%, 0=50%, -1=25%
|
||||
// Greennill => (D) +1=25%, 0=65%, -1=10%
|
||||
// Greennill => (F) +1=40%, 0=55%, -1=5%
|
||||
// Skyly => (D) +1=15%, 0=70%, -1=15%
|
||||
// Skyly => (F) +1=30%, 0=60%, -1=10%
|
||||
// Bluefull => (D) +1=10%, 0=60%, -1=30%
|
||||
// Bluefull => (F) +1=25%, 0=50%, -1=25%
|
||||
// Purplenum => (D) +1=25%, 0=65%, -1=10%
|
||||
// Purplenum => (F) +1=40%, 0=55%, -1=5%
|
||||
// Pinkal => (D) +1=15%, 0=70%, -1=15%
|
||||
// Pinkal => (F) +1=30%, 0=60%, -1=10%
|
||||
// Redria => (D) +1=20%, 0=60%, -1=20%
|
||||
// Redria => (F) +1=0%, 0=0%, -1=0%
|
||||
// Oran => (D) +1=15%, 0=70%, -1=15%
|
||||
// Oran => (F) +1=30%, 0=60%, -1=10%
|
||||
// Yellowboze => (D) +1=25%, 0=65%, -1=10%
|
||||
// Yellowboze => (F) +1=40%, 0=55%, -1=5%
|
||||
// Whitill => (D) +1=10%, 0=60%, -1=30%
|
||||
// Whitill => (F) +1=25%, 0=50%, -1=25%
|
||||
U32T<BE> special_delta_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// This table specifies how likely a weapon's grind is to be upgraded or downgraded, and by how much. The final grind
|
||||
// value is clamped to the range between 0 and the weapon's maximum grind from ItemPMT, inclusive.
|
||||
// In PSO V3, the grind delta table is:
|
||||
// Viridia => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Viridia => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
// Greennill => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Greennill => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Skyly => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Skyly => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Bluefull => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Bluefull => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
// Purplenum => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Purplenum => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Pinkal => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Pinkal => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Redria => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Redria => (F) +3=0%, +2=0%, +1=0%, 0=0%, -1=0%, -2=0%, -3=0%
|
||||
// Oran => (D) +3=0%, +2=7%, +1=10%, 0=60%, -1=13%, -2=7%, -3=3%
|
||||
// Oran => (F) +3=3%, +2=12%, +1=20%, 0=50%, -1=10%, -2=5%, -3=0%
|
||||
// Yellowboze => (D) +3=0%, +2=5%, +1=10%, 0=70%, -1=10%, -2=5%, -3=0%
|
||||
// Yellowboze => (F) +3=3%, +2=7%, +1=20%, 0=60%, -1=10%, -2=0%, -3=0%
|
||||
// Whitill => (D) +3=3%, +2=7%, +1=13%, 0=60%, -1=10%, -2=7%, -3=0%
|
||||
// Whitill => (F) +3=5%, +2=13%, +1=25%, 0=50%, -1=7%, -2=0%, -3=0%
|
||||
U32T<BE> grind_delta_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// This table specifies how likely a weapon's bonuses are to be upgraded or downgraded, and by how much. The final
|
||||
// bonuses are capped above at 100, but there is no lower limit (so negative results are possible).
|
||||
// In PSO V3, the bonus delta table is:
|
||||
// Viridia => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Viridia => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
// Greennill => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Greennill => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Skyly => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Skyly => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Bluefull => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Bluefull => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
// Purplenum => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Purplenum => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Pinkal => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Pinkal => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Redria => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Redria => (F) +10=0%, +5=0%, 0=0%, -5=0%, -10=0%
|
||||
// Oran => (D) +10=10%, +5=25%, 0=50%, -5=10%, -10=5%
|
||||
// Oran => (F) +10=13%, +5=30%, 0=50%, -5=5%, -10=2%
|
||||
// Yellowboze => (D) +10=5%, +5=10%, 0=50%, -5=25%, -10=10%
|
||||
// Yellowboze => (F) +10=8%, +5=15%, 0=50%, -5=20%, -10=7%
|
||||
// Whitill => (D) +10=5%, +5=15%, 0=60%, -5=15%, -10=5%
|
||||
// Whitill => (F) +10=8%, +5=20%, 0=60%, -5=10%, -10=2%
|
||||
U32T<BE> bonus_delta_table_offset; // [{c, o -> (DeltaProbabilityEntry)[10][c]})
|
||||
|
||||
// There is a secondary computation done during weapon adjustment that appears to determine how "good" the resulting
|
||||
// weapon is compared to its original state. If the result of this computation is positive, the game plays a jingle
|
||||
// when the tekker result is accepted. These tables describe how much each delta affects this value, which we call
|
||||
// luck.
|
||||
|
||||
// In PSO V3, the special upgrade luck table is:
|
||||
// +1 => +20, 0 => 0, -1 => -20
|
||||
U32T<BE> special_luck_table_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
|
||||
// In PSO V3, the grind delta luck table is:
|
||||
// +3 => +10, +2 => +5, +1 => +3, 0 => 0, -1 => -3, -2 => -5, -3 => -10
|
||||
U32T<BE> grind_luck_table_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
|
||||
// In PSO V3, the bonus delta luck table is:
|
||||
// +10 => +15, +5 => +8, 0 => 0, -5 => -8, -10 => -15
|
||||
U32T<BE> bonus_luck_table_offset; // LuckTableEntry[...]; ending with FF FF
|
||||
} __packed_ws_be__(RootT, 0x18);
|
||||
|
||||
uint8_t TekkerAdjustmentSet::favored_weapon_type_for_section_id(uint8_t section_id) {
|
||||
// The favored weapon type table is hardcoded in the game client. The table is:
|
||||
// Viridia shots
|
||||
// Greennill rifles
|
||||
// Skyly swords
|
||||
// Bluefull partisans
|
||||
// Purplenum mechguns
|
||||
// Pinkal canes
|
||||
// Redria (none)
|
||||
// Oran daggers
|
||||
// Yellowboze (none)
|
||||
// Whitill slicers
|
||||
static const std::array<uint8_t, 10> data{0x09, 0x07, 0x02, 0x04, 0x08, 0x0A, 0xFF, 0x03, 0xFF, 0x05};
|
||||
return data.at(section_id);
|
||||
}
|
||||
|
||||
TekkerAdjustmentSet::TekkerAdjustmentSet(const void* data, size_t size, bool big_endian) {
|
||||
if (big_endian) {
|
||||
this->parse_t<true>(data, size);
|
||||
} else {
|
||||
this->parse_t<false>(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
TekkerAdjustmentSet::TekkerAdjustmentSet(const std::string& data, bool big_endian)
|
||||
: TekkerAdjustmentSet(data.data(), data.size(), big_endian) {}
|
||||
|
||||
TekkerAdjustmentSet::TekkerAdjustmentSet(const phosg::JSON& json) {
|
||||
auto parse_delta_table = [](const phosg::JSON& json) -> std::array<Table, 10> {
|
||||
if (!json.is_dict() || json.size() != 10) {
|
||||
throw std::runtime_error("Invalid structure for TekkerAdjustmentSet JSON delta table");
|
||||
}
|
||||
std::array<Table, 10> ret;
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
auto& table = ret[section_id];
|
||||
for (const auto& [k, v] : json.at(name_for_section_id(section_id)).as_dict()) {
|
||||
auto prob = v->as_int();
|
||||
table.probs.emplace(stoll(k), prob);
|
||||
table.total += prob;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
this->favored_special_delta_table = parse_delta_table(json.at("FavoredSpecialDeltaTable"));
|
||||
this->default_special_delta_table = parse_delta_table(json.at("DefaultSpecialDeltaTable"));
|
||||
this->favored_grind_delta_table = parse_delta_table(json.at("FavoredGrindDeltaTable"));
|
||||
this->default_grind_delta_table = parse_delta_table(json.at("DefaultGrindDeltaTable"));
|
||||
this->favored_bonus_delta_table = parse_delta_table(json.at("FavoredBonusDeltaTable"));
|
||||
this->default_bonus_delta_table = parse_delta_table(json.at("DefaultBonusDeltaTable"));
|
||||
|
||||
auto parse_luck_table = [](const phosg::JSON& json) -> std::unordered_map<int8_t, int8_t> {
|
||||
std::unordered_map<int8_t, int8_t> ret;
|
||||
for (const auto& [k, v] : json.as_dict()) {
|
||||
ret.emplace(stoll(k), v->as_int());
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
this->special_luck_table = parse_luck_table(json.at("SpecialLuckTable"));
|
||||
this->grind_luck_table = parse_luck_table(json.at("GrindLuckTable"));
|
||||
this->bonus_luck_table = parse_luck_table(json.at("BonusLuckTable"));
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
void TekkerAdjustmentSet::parse_t(const void* data, size_t size) {
|
||||
phosg::StringReader r(data, size);
|
||||
const auto& root = r.pget<RootT<BE>>(r.pget<U32T<BE>>(size - 0x10));
|
||||
|
||||
auto parse_delta_table = [&r](std::array<Table, 10>& favored_tables, std::array<Table, 10>& default_tables, uint32_t ref_offset) -> void {
|
||||
const auto& ref = r.pget<ProbTableRefT<BE>>(ref_offset);
|
||||
auto* entries = &r.pget<DeltaProbabilityEntry>(ref.offset, sizeof(DeltaProbabilityEntry) * ref.count * 10);
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
auto& favored_table = favored_tables[section_id];
|
||||
auto& default_table = default_tables[section_id];
|
||||
for (size_t z = 0; z < ref.count; z++) {
|
||||
const auto& entry = entries[section_id * ref.count + z];
|
||||
int8_t delta = delta_table.at(entry.delta_index);
|
||||
favored_table.probs.emplace(delta, entry.count_favored);
|
||||
favored_table.total += entry.count_favored;
|
||||
default_table.probs.emplace(delta, entry.count_default);
|
||||
default_table.total += entry.count_default;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parse_delta_table(this->favored_special_delta_table, this->default_special_delta_table, root.special_delta_table_offset);
|
||||
parse_delta_table(this->favored_grind_delta_table, this->default_grind_delta_table, root.grind_delta_table_offset);
|
||||
parse_delta_table(this->favored_bonus_delta_table, this->default_bonus_delta_table, root.bonus_delta_table_offset);
|
||||
|
||||
auto parse_luck_table = [&r](uint32_t offset) -> std::unordered_map<int8_t, int8_t> {
|
||||
auto sub_r = r.sub(offset);
|
||||
std::unordered_map<int8_t, int8_t> ret;
|
||||
for (;;) {
|
||||
const auto& entry = sub_r.get<LuckTableEntry>();
|
||||
if (entry.delta_index == 0xFF) {
|
||||
break;
|
||||
}
|
||||
ret.emplace(delta_table.at(entry.delta_index), entry.luck);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
this->special_luck_table = parse_luck_table(root.special_luck_table_offset);
|
||||
this->grind_luck_table = parse_luck_table(root.grind_luck_table_offset);
|
||||
this->bonus_luck_table = parse_luck_table(root.bonus_luck_table_offset);
|
||||
}
|
||||
|
||||
template <bool BE>
|
||||
std::string TekkerAdjustmentSet::serialize_binary_t() const {
|
||||
RELFileWriter<BE> rel;
|
||||
|
||||
auto serialize_delta_tables = [&rel](const std::array<Table, 10>& favored_tables, const std::array<Table, 10>& default_tables) -> ProbTableRefT<BE> {
|
||||
std::set<int8_t> all_deltas;
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
for (const auto& [delta, _] : favored_tables[section_id].probs) {
|
||||
all_deltas.emplace(delta);
|
||||
}
|
||||
for (const auto& [delta, _] : default_tables[section_id].probs) {
|
||||
all_deltas.emplace(delta);
|
||||
}
|
||||
}
|
||||
|
||||
ProbTableRefT<BE> ret{rel.w.size(), all_deltas.size()};
|
||||
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
for (auto delta_it = all_deltas.rbegin(); delta_it != all_deltas.rend(); delta_it++) {
|
||||
DeltaProbabilityEntry entry;
|
||||
entry.delta_index = reverse_delta_table.at(*delta_it);
|
||||
try {
|
||||
entry.count_favored = favored_tables[section_id].probs.at(*delta_it);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
try {
|
||||
entry.count_default = default_tables[section_id].probs.at(*delta_it);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
rel.template put<DeltaProbabilityEntry>(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
auto special_delta_ref = serialize_delta_tables(this->favored_special_delta_table, this->default_special_delta_table);
|
||||
auto grind_delta_ref = serialize_delta_tables(this->favored_grind_delta_table, this->default_grind_delta_table);
|
||||
auto bonus_delta_ref = serialize_delta_tables(this->favored_bonus_delta_table, this->default_bonus_delta_table);
|
||||
|
||||
auto serialize_luck_table = [&rel](const std::unordered_map<int8_t, int8_t>& table) -> uint32_t {
|
||||
uint32_t ret = rel.w.size();
|
||||
|
||||
std::vector<std::pair<uint8_t, int8_t>> entries;
|
||||
for (const auto& [delta, luck] : table) {
|
||||
entries.emplace_back(std::make_pair(reverse_delta_table.at(delta), luck));
|
||||
}
|
||||
std::sort(entries.begin(), entries.end(), std::greater<std::pair<uint8_t, int8_t>>());
|
||||
|
||||
for (const auto& [delta_index, luck] : entries) {
|
||||
rel.w.put_u8(delta_index);
|
||||
rel.w.put_s8(luck);
|
||||
}
|
||||
rel.w.put_u16(0xFFFF);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
RootT<BE> root;
|
||||
root.special_luck_table_offset = serialize_luck_table(this->special_luck_table);
|
||||
root.grind_luck_table_offset = serialize_luck_table(this->grind_luck_table);
|
||||
root.bonus_luck_table_offset = serialize_luck_table(this->bonus_luck_table);
|
||||
|
||||
rel.align(4);
|
||||
rel.relocations.emplace(rel.w.size());
|
||||
root.special_delta_table_offset = rel.template put<ProbTableRefT<BE>>(special_delta_ref);
|
||||
rel.relocations.emplace(rel.w.size());
|
||||
root.grind_delta_table_offset = rel.template put<ProbTableRefT<BE>>(grind_delta_ref);
|
||||
rel.relocations.emplace(rel.w.size());
|
||||
root.bonus_delta_table_offset = rel.template put<ProbTableRefT<BE>>(bonus_delta_ref);
|
||||
|
||||
uint32_t root_offset = rel.template put<RootT<BE>>(root);
|
||||
for (size_t z = 1; z <= sizeof(RootT<BE>) / 4; z++) {
|
||||
rel.relocations.emplace(rel.w.size() - (z * 4));
|
||||
}
|
||||
|
||||
return rel.finalize(root_offset);
|
||||
}
|
||||
|
||||
std::string TekkerAdjustmentSet::serialize_binary(bool big_endian) const {
|
||||
return big_endian ? this->serialize_binary_t<true>() : this->serialize_binary_t<false>();
|
||||
}
|
||||
|
||||
phosg::JSON TekkerAdjustmentSet::json() const {
|
||||
auto ret = phosg::JSON::dict();
|
||||
|
||||
auto serialize_delta_table = [](const std::array<Table, 10>& table) -> phosg::JSON {
|
||||
auto ret = phosg::JSON::dict();
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
auto secid_ret = phosg::JSON::dict();
|
||||
for (const auto& [k, v] : table[section_id].probs) {
|
||||
secid_ret.emplace(std::format("{}", k), v);
|
||||
}
|
||||
ret.emplace(name_for_section_id(section_id), std::move(secid_ret));
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
ret.emplace("FavoredSpecialDeltaTable", serialize_delta_table(this->favored_special_delta_table));
|
||||
ret.emplace("DefaultSpecialDeltaTable", serialize_delta_table(this->default_special_delta_table));
|
||||
ret.emplace("FavoredGrindDeltaTable", serialize_delta_table(this->favored_grind_delta_table));
|
||||
ret.emplace("DefaultGrindDeltaTable", serialize_delta_table(this->default_grind_delta_table));
|
||||
ret.emplace("FavoredBonusDeltaTable", serialize_delta_table(this->favored_bonus_delta_table));
|
||||
ret.emplace("DefaultBonusDeltaTable", serialize_delta_table(this->default_bonus_delta_table));
|
||||
|
||||
auto serialize_luck_table = [](const std::unordered_map<int8_t, int8_t>& table) -> phosg::JSON {
|
||||
auto ret = phosg::JSON::dict();
|
||||
for (const auto& [k, v] : table) {
|
||||
ret.emplace(std::format("{}", k), v);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
ret.emplace("SpecialLuckTable", serialize_luck_table(this->special_luck_table));
|
||||
ret.emplace("GrindLuckTable", serialize_luck_table(this->grind_luck_table));
|
||||
ret.emplace("BonusLuckTable", serialize_luck_table(this->bonus_luck_table));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TekkerAdjustmentSet::print(FILE* stream) const {
|
||||
phosg::fwrite_fmt(stream, "TekkerAdjustmentSet\n");
|
||||
|
||||
auto print_table = [stream](const std::array<Table, 10>& table, const std::unordered_map<int8_t, int8_t>& luck_table) -> void {
|
||||
for (size_t section_id = 0; section_id < 10; section_id++) {
|
||||
phosg::fwrite_fmt(stream, " {:<10}:", name_for_section_id(section_id));
|
||||
std::vector<std::pair<int8_t, size_t>> sorted_probs;
|
||||
for (const auto& [delta, prob] : table[section_id].probs) {
|
||||
sorted_probs.emplace_back(delta, prob);
|
||||
}
|
||||
std::sort(sorted_probs.begin(), sorted_probs.end());
|
||||
for (const auto& [delta, prob] : sorted_probs) {
|
||||
int8_t luck = luck_table.at(delta);
|
||||
phosg::fwrite_fmt(stream, " {:>2} @ {:>2} ({:>2})", delta, prob, luck);
|
||||
}
|
||||
phosg::fwrite_fmt(stream, "\n");
|
||||
}
|
||||
};
|
||||
|
||||
phosg::fwrite_fmt(stream, " Favored special deltas:\n");
|
||||
print_table(this->favored_special_delta_table, this->special_luck_table);
|
||||
phosg::fwrite_fmt(stream, " Default special deltas:\n");
|
||||
print_table(this->default_special_delta_table, this->special_luck_table);
|
||||
phosg::fwrite_fmt(stream, " Favored grind deltas:\n");
|
||||
print_table(this->favored_grind_delta_table, this->grind_luck_table);
|
||||
phosg::fwrite_fmt(stream, " Default grind deltas:\n");
|
||||
print_table(this->default_grind_delta_table, this->grind_luck_table);
|
||||
phosg::fwrite_fmt(stream, " Favored bonus deltas:\n");
|
||||
print_table(this->favored_bonus_delta_table, this->bonus_luck_table);
|
||||
phosg::fwrite_fmt(stream, " Default bonus deltas:\n");
|
||||
print_table(this->default_bonus_delta_table, this->bonus_luck_table);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <phosg/Encoding.hh>
|
||||
#include <phosg/JSON.hh>
|
||||
|
||||
#include "EnemyType.hh"
|
||||
#include "GSLArchive.hh"
|
||||
#include "PSOEncryption.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "Text.hh"
|
||||
#include "Types.hh"
|
||||
|
||||
struct TekkerAdjustmentSet {
|
||||
// This struct parses and accesses data from JudgeItem.rel
|
||||
|
||||
TekkerAdjustmentSet(const void* data, size_t size, bool big_endian);
|
||||
TekkerAdjustmentSet(const std::string& data, bool big_endian);
|
||||
explicit TekkerAdjustmentSet(const phosg::JSON& json);
|
||||
|
||||
template <bool BE>
|
||||
void parse_t(const void* data, size_t size);
|
||||
template <bool BE>
|
||||
std::string serialize_binary_t() const;
|
||||
|
||||
std::string serialize_binary(bool big_endian) const;
|
||||
phosg::JSON json() const;
|
||||
|
||||
void print(FILE* stream) const;
|
||||
|
||||
static uint8_t favored_weapon_type_for_section_id(uint8_t section_id);
|
||||
|
||||
struct Table {
|
||||
std::unordered_map<int8_t, size_t> probs;
|
||||
size_t total = 0;
|
||||
};
|
||||
|
||||
std::array<Table, 10> favored_special_delta_table;
|
||||
std::array<Table, 10> default_special_delta_table;
|
||||
std::array<Table, 10> favored_grind_delta_table;
|
||||
std::array<Table, 10> default_grind_delta_table;
|
||||
std::array<Table, 10> favored_bonus_delta_table;
|
||||
std::array<Table, 10> default_bonus_delta_table;
|
||||
std::unordered_map<int8_t, int8_t> special_luck_table;
|
||||
std::unordered_map<int8_t, int8_t> grind_luck_table;
|
||||
std::unordered_map<int8_t, int8_t> bonus_luck_table;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
../tables/ItemMagEdit-bb-v4.prs
|
||||
@@ -15,7 +15,7 @@ reloc0:
|
||||
start:
|
||||
xor eax, eax
|
||||
mov edx, esp
|
||||
mov esp, <VERS 0x009EC359 0x009F61B0 0x009F81B0>
|
||||
mov esp, <VERS 0x009EC35B 0x009F61B0 0x009F81B0>
|
||||
mov ecx, 0x3C
|
||||
again:
|
||||
push 0
|
||||
|
||||
+280
-16
@@ -622,25 +622,289 @@
|
||||
// bytes); textual descriptions are not supported here.
|
||||
"QuestF95EResultItems": [
|
||||
[
|
||||
[0x00900000, 0x00900100, 0x00900200, 0x00900300, 0x00900400, 0x00900500, 0x00900600, 0x00900700, 0x00900800, 0x00B40000, 0x01014E00, 0x01030700, 0x01034100, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00B90000, 0x00340000, 0x00090100, 0x00900200, 0x00900700, 0x002C0000, 0x002D0000, 0x01023500, 0x00010600, 0x00010500, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00B60000, 0x008A0100, 0x00100100, 0x00100200, 0x00100300, 0x00100400, 0x00100500, 0x00100600, 0x00270000, 0x00010700, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00B70000, 0x00100100, 0x00100200, 0x00100300, 0x00100400, 0x00100500, 0x00100600, 0x00290000, 0x008A0000, 0x008A0200, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
// Black Paper's Deal Dorphon route
|
||||
[
|
||||
// Normal
|
||||
0x00900000, // DB'S SABER 3062
|
||||
0x00900200, // DB'S SABER 3069 Chris
|
||||
0x00900800, // DB'S SABER 3077
|
||||
0x01014E00, // OFFICER UNIFORM
|
||||
0x01030700, // God/Mind
|
||||
0x01034100, // God/Battle
|
||||
0x03030000, // Sol Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Hard
|
||||
0x00010500, // DB'S SABER (Ephinea)
|
||||
0x00010600, // KALADBOLG (Ephinea)
|
||||
0x002C0000, // ELYSION
|
||||
0x00340000, // RED SWORD
|
||||
0x00900000, // DB'S SABER 3062
|
||||
0x00900100, // DB'S SABER 3067
|
||||
0x00900200, // DB'S SABER 3069 Chris (Ephinea)
|
||||
0x00900300, // DB'S SABER 3064
|
||||
0x00900400, // DB'S SABER 3069 Torato
|
||||
0x00900500, // DB'S SABER 3073
|
||||
0x00900600, // DB'S SABER 3070
|
||||
0x00900700, // DB'S SABER 3075
|
||||
0x00900800, // DB'S SABER 3077 (Ephinea)
|
||||
0x00B90000, // FLAMBERGE
|
||||
0x01023500, // SECURE FEET
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x00010700, // DURANDAL
|
||||
0x00100100, // AGITO 1975 (real)
|
||||
0x00100200, // AGITO 1983
|
||||
0x00100300, // AGITO 2001
|
||||
0x00100400, // AGITO 1991
|
||||
0x00100500, // AGITO 1977
|
||||
0x00100600, // AGITO 1980
|
||||
0x00270000, // ANCIENT SABER
|
||||
0x008A0100, // YASHA
|
||||
0x00B60000, // GUREN
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x00100100, // AGITO 1975 (real)
|
||||
0x00100200, // AGITO 1983
|
||||
0x00100300, // AGITO 2001
|
||||
0x00100400, // AGITO 1991
|
||||
0x00100500, // AGITO 1977
|
||||
0x00100600, // AGITO 1980
|
||||
0x00290000, // YAMIGARASU
|
||||
0x008A0000, // SANGE
|
||||
0x008A0200, // KAMUI
|
||||
0x00B70000, // SHOUREN
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [
|
||||
[0x01028B00, 0x01022800, 0x01013400, 0x01030300, 0x01030B00, 0x03180700, 0x00550000, 0x01032900, 0x01032F00, 0x01032C00, 0x01032300, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x01028C00, 0x01021500, 0x01028A00, 0x01014000, 0x01034400, 0x01034600, 0x01034500, 0x01034700, 0x03180700, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00CB0000, 0x003A0000, 0x008C0200, 0x01022B00, 0x00500000, 0x000B0600, 0x000A0600, 0x000A0400, 0x00550000, 0x00230000, 0x003B0000, 0x03180700, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00510000, 0x01035200, 0x01032000, 0x01033E00, 0x01022900, 0x03180700, 0x000B0400, 0x000A0600, 0x00560000, 0x003B0000, 0x00230000, 0x000A0500, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
// Black Paper's Deal Rappy route
|
||||
[
|
||||
// Normal
|
||||
0x01013400, // SMOKING PLATE
|
||||
0x01022800, // TRIPOLIC SHIELD
|
||||
0x01028B00, // BUNNY EARS
|
||||
0x01030300, // God/Power
|
||||
0x01030B00, // God/Arm
|
||||
0x01032300, // Resist/Burning
|
||||
0x01032600, // Resist/Blizzard
|
||||
0x01032900, // Resist/Storm (Ephinea)
|
||||
0x01032C00, // Resist/Holy
|
||||
0x01032F00, // Resist/Devil (Ephinea)
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
|
||||
], [
|
||||
// Hard
|
||||
0x01014000, // RED COAT
|
||||
0x01021500, // INVISIBLE GUARD
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01028C00, // CAT EARS
|
||||
0x01034200, // Cure/Poison
|
||||
0x01034300, // Cure/Paralysis
|
||||
0x01034400, // Cure/Slow
|
||||
0x01034500, // Cure/Confuse
|
||||
0x01034600, // Cure/Freeze
|
||||
0x01034700, // Cure/Shock
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x000A0400, // CLUB OF LACONIUM (Ephinea)
|
||||
0x000A0600, // CLUB OF ZUMIURAN
|
||||
0x000B0600, // ALIVE AQHU
|
||||
0x00230000, // STING TIP
|
||||
0x003A0000, // MADAM'S PARASOL
|
||||
0x003B0000, // MADAM'S UMBRELLA
|
||||
0x00500000, // WINDMILL
|
||||
0x00550000, // RABBIT WAND
|
||||
0x00CB0000, // TYRELL'S PARASOL
|
||||
0x01022B00, // KASAMI BRACER
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030E0A00, // Book of HITOGATA (Ephinea)
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x000A0500, // MACE OF ADAMAN
|
||||
0x000A0600, // CLUB OF ZUMIURAN
|
||||
0x000B0400, // BATTLE VERGE
|
||||
0x00230000, // STING TIP (Ephinea)
|
||||
0x00250000, // TECHNICAL CROZIER
|
||||
0x003B0000, // MADAM'S UMBRELLA
|
||||
0x00500000, // WINDMILL
|
||||
0x00510000, // EVIL CURST
|
||||
0x00560000, // PLANTAIN LEAF
|
||||
0x01022900, // STANDSTILL SHIELD
|
||||
0x01032000, // God/Ability
|
||||
0x01033E00, // God/Technique
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [
|
||||
[0x01013200, 0x002F0100, 0x00B30000, 0x005E0000, 0x000E0200, 0x002E0000, 0x00950000, 0x009A0000, 0x002F0000, 0x01031B00, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00C00000, 0x00D20000, 0x008D0000, 0x01012E00, 0x008B0000, 0x00090700, 0x004E0000, 0x006D0000, 0x00150000, 0x008B0200, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00AA0000, 0x01014100, 0x01015100, 0x01022300, 0x003F0000, 0x00410000, 0x00050700, 0x00050600, 0x00050500, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00AF0000, 0x00430000, 0x01035100, 0x00CD0000, 0x00990000, 0x006C0000, 0x00450000, 0x006B0000, 0x00120000, 0x00650000, 0x01022900, 0x00130000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
// Black Paper's Deal Zu route
|
||||
[
|
||||
// Normal
|
||||
0x000E0100, // STAG CUTLERY
|
||||
0x000E0200, // TWIN BRAND
|
||||
0x002E0000, // METEOR CUDGEL
|
||||
0x002F0000, // MONKEY KING BAR
|
||||
0x005E0000, // TWIN BLAZE
|
||||
0x00950000, // PARTISAN of LIGHTNING
|
||||
0x009A0000, // DEMOLITION COMET
|
||||
0x00B30000, // VIVIENNE
|
||||
0x01013200, // ELECTRO FRAME
|
||||
0x01031B00, // God/Body
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot (Ephinea)
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Hard
|
||||
0x00090700, // FINAL IMPACT
|
||||
0x00150000, // FLAME VISIT
|
||||
0x004E0000, // PANZER FAUST
|
||||
0x006D0000, // MASER BEAM
|
||||
0x008B0000, // PHOTON LAUNCHER
|
||||
0x008B0200, // RED SCORPIR
|
||||
0x008D0000, // NUG2000-BAZOOKA
|
||||
0x00C00000, // CANNON ROUGE
|
||||
0x00D20000, // ANO BAZOOKA
|
||||
0x01012E00, // FLAME GARMENT
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x00050500, // SLICER OF ASSASSIN
|
||||
0x00050600, // DISKA OF LIBERATOR
|
||||
0x00050700, // DISKA OF BRAVEMAN
|
||||
0x003F0000, // FLIGHT CUTTER
|
||||
0x00400000, // FLIGHT FAN
|
||||
0x00410000, // RED SLICER
|
||||
0x00AA0000, // SLICER OF FANATIC
|
||||
0x01014100, // THIRTEEN
|
||||
0x01015100, // INFANTRY GEAR
|
||||
0x01022300, // REGENE GEAR ADV.
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot (Ephinea)
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x00120000, // SPREAD NEEDLE
|
||||
0x00130000, // HOLY RAY
|
||||
0x00430000, // HANDGUN:MILLA
|
||||
0x00450000, // FROZEN SHOOTER
|
||||
0x00650000, // YASMINKOV 3000R
|
||||
0x006B0000, // YASMINKOV 7000V
|
||||
0x006C0000, // YASMINKOV 9000M
|
||||
0x00990000, // ANGEL HARP
|
||||
0x00AF0000, // OPHELIE SEIZE
|
||||
0x00CD0000, // TANEGASHIMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [], [
|
||||
[0x00BA0000, 0x000D0300, 0x00430100, 0x00070800, 0x00420100, 0x00C90000, 0x03100000, 0x01029500, 0x01028F00, 0x01029100],
|
||||
[0x00BB0000, 0x000D0300, 0x00B70000, 0x00420100, 0x00070800, 0x00C90000, 0x01013600, 0x01028A00, 0x01029900, 0x01035100, 0x01035B00, 0x01035200, 0x03100000, 0x03180A00],
|
||||
[0x00BA0000, 0x00B40000, 0x000D0300, 0x00B60000, 0x00B30000, 0x00070800, 0x00430100, 0x00C90000, 0x01013600, 0x01028A00, 0x01029900, 0x01028500, 0x01034800, 0x01035100, 0x01035B00, 0x01035200, 0x03100000],
|
||||
[0x00BA0000, 0x00B40000, 0x000D0300, 0x00B60000, 0x00B30000, 0x00070800, 0x00430100, 0x00C90000, 0x01013600, 0x01028A00, 0x01029900, 0x01028500, 0x01034800, 0x01035100, 0x01035B00, 0x01035200],
|
||||
// Black Paper's Dangerous Deal 2
|
||||
[
|
||||
// Normal
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00420100, // MASTER RAVEN (Ephinea)
|
||||
0x00430100, // LAST SWAN
|
||||
0x00BA0000, // YUNCHANG
|
||||
0x00C90000, // DECALOG
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Hard
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00420100, // MASTER RAVEN
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B70000, // SHOUREN
|
||||
0x00BA0000, // YUNCHANG
|
||||
0x00BB0000, // SNAKE SPIRE
|
||||
0x00BC0000, // FLAPJACK FLAPPER
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Very Hard
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00430100, // LAST SWAN
|
||||
0x00B30000, // VIVIENNE
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B60000, // GUREN
|
||||
0x00BA0000, // YUNCHANG (Ephinea)
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028500, // GRATIA
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Ultimate
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00430100, // LAST SWAN
|
||||
0x00B30000, // VIVIENNE
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B60000, // GUREN
|
||||
0x00B70000, // SHOUREN
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028500, // GRATIA
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
],
|
||||
],
|
||||
],
|
||||
// Results for quest opcode F95F (used in Gallon's Plan). This list is indexed by type (which is the third argument
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
map_city00_00e.dat
|
||||
+1
@@ -0,0 +1 @@
|
||||
map_city00_00o.dat
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
ItemMagEdit-pc-v2.prs
|
||||
@@ -1 +0,0 @@
|
||||
ItemMagEdit-gc-v3.prs
|
||||
@@ -1 +0,0 @@
|
||||
ItemMagEdit-gc-v3.prs
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
ItemMagEdit-pc-v2.prs
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,363 @@
|
||||
{
|
||||
"ArmorTable": [
|
||||
[
|
||||
[0, 33],
|
||||
[1, 33],
|
||||
[2, 15],
|
||||
[3, 10],
|
||||
[4, 5],
|
||||
[5, 0],
|
||||
[6, 4],
|
||||
[7, 0],
|
||||
[8, 0],
|
||||
[9, 0],
|
||||
[10, 0],
|
||||
[11, 0],
|
||||
[12, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0],
|
||||
[17, 0],
|
||||
[18, 0],
|
||||
[19, 0],
|
||||
[20, 0]
|
||||
],
|
||||
[
|
||||
[0, 5],
|
||||
[1, 5],
|
||||
[2, 10],
|
||||
[3, 15],
|
||||
[4, 19],
|
||||
[5, 19],
|
||||
[6, 10],
|
||||
[7, 10],
|
||||
[8, 5],
|
||||
[9, 0],
|
||||
[10, 0],
|
||||
[11, 2],
|
||||
[12, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0],
|
||||
[17, 0],
|
||||
[18, 0],
|
||||
[19, 0],
|
||||
[20, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 5],
|
||||
[5, 5],
|
||||
[6, 10],
|
||||
[7, 15],
|
||||
[8, 19],
|
||||
[9, 19],
|
||||
[10, 10],
|
||||
[11, 10],
|
||||
[12, 5],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 2],
|
||||
[16, 0],
|
||||
[17, 0],
|
||||
[18, 0],
|
||||
[19, 0],
|
||||
[20, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0],
|
||||
[6, 2],
|
||||
[7, 4],
|
||||
[8, 5],
|
||||
[9, 5],
|
||||
[10, 10],
|
||||
[11, 12],
|
||||
[12, 14],
|
||||
[13, 14],
|
||||
[14, 10],
|
||||
[15, 9],
|
||||
[16, 5],
|
||||
[17, 5],
|
||||
[18, 3],
|
||||
[19, 2],
|
||||
[20, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0],
|
||||
[6, 0],
|
||||
[7, 2],
|
||||
[8, 5],
|
||||
[9, 5],
|
||||
[10, 5],
|
||||
[11, 6],
|
||||
[12, 10],
|
||||
[13, 13],
|
||||
[14, 14],
|
||||
[15, 14],
|
||||
[16, 14],
|
||||
[17, 7],
|
||||
[18, 3],
|
||||
[19, 1],
|
||||
[20, 1]
|
||||
]
|
||||
],
|
||||
"ShieldTable": [
|
||||
[
|
||||
[0, 34],
|
||||
[1, 34],
|
||||
[2, 15],
|
||||
[3, 15],
|
||||
[4, 0],
|
||||
[5, 0],
|
||||
[6, 2],
|
||||
[7, 0],
|
||||
[8, 0],
|
||||
[9, 0],
|
||||
[10, 0],
|
||||
[11, 0],
|
||||
[12, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0],
|
||||
[17, 0]
|
||||
],
|
||||
[
|
||||
[0, 5],
|
||||
[1, 10],
|
||||
[2, 14],
|
||||
[3, 18],
|
||||
[4, 18],
|
||||
[5, 14],
|
||||
[6, 10],
|
||||
[7, 5],
|
||||
[8, 2],
|
||||
[9, 2],
|
||||
[10, 2],
|
||||
[11, 0],
|
||||
[12, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0],
|
||||
[17, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 6],
|
||||
[4, 10],
|
||||
[5, 15],
|
||||
[6, 19],
|
||||
[7, 18],
|
||||
[8, 14],
|
||||
[9, 9],
|
||||
[10, 4],
|
||||
[11, 3],
|
||||
[12, 0],
|
||||
[13, 2],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0],
|
||||
[17, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 5],
|
||||
[5, 5],
|
||||
[6, 5],
|
||||
[7, 10],
|
||||
[8, 14],
|
||||
[9, 15],
|
||||
[10, 14],
|
||||
[11, 11],
|
||||
[12, 9],
|
||||
[13, 6],
|
||||
[14, 4],
|
||||
[15, 0],
|
||||
[16, 2],
|
||||
[17, 0]
|
||||
],
|
||||
[
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 4],
|
||||
[6, 5],
|
||||
[7, 5],
|
||||
[8, 8],
|
||||
[9, 11],
|
||||
[10, 13],
|
||||
[11, 13],
|
||||
[12, 14],
|
||||
[13, 14],
|
||||
[14, 9],
|
||||
[15, 2],
|
||||
[16, 1],
|
||||
[17, 1]
|
||||
]
|
||||
],
|
||||
"UnitTable": [
|
||||
[
|
||||
[0, 0],
|
||||
[4, 0],
|
||||
[8, 0],
|
||||
[12, 0],
|
||||
[16, 0],
|
||||
[24, 0],
|
||||
[33, 0],
|
||||
[36, 0],
|
||||
[39, 0],
|
||||
[42, 0],
|
||||
[45, 0],
|
||||
[1, 0],
|
||||
[5, 0],
|
||||
[9, 0],
|
||||
[13, 0],
|
||||
[17, 0],
|
||||
[25, 0],
|
||||
[34, 0],
|
||||
[37, 0],
|
||||
[40, 0],
|
||||
[43, 0],
|
||||
[46, 0],
|
||||
[51, 0],
|
||||
[54, 0],
|
||||
[57, 0],
|
||||
[67, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[4, 10],
|
||||
[8, 10],
|
||||
[12, 10],
|
||||
[16, 10],
|
||||
[24, 10],
|
||||
[33, 10],
|
||||
[36, 10],
|
||||
[39, 10],
|
||||
[42, 5],
|
||||
[45, 5],
|
||||
[1, 0],
|
||||
[5, 0],
|
||||
[9, 0],
|
||||
[13, 0],
|
||||
[17, 0],
|
||||
[25, 0],
|
||||
[34, 0],
|
||||
[37, 0],
|
||||
[40, 0],
|
||||
[43, 0],
|
||||
[46, 0],
|
||||
[51, 0],
|
||||
[54, 0],
|
||||
[57, 0],
|
||||
[67, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[4, 10],
|
||||
[8, 10],
|
||||
[12, 10],
|
||||
[16, 10],
|
||||
[24, 10],
|
||||
[33, 10],
|
||||
[36, 10],
|
||||
[39, 10],
|
||||
[42, 5],
|
||||
[45, 5],
|
||||
[1, 0],
|
||||
[5, 0],
|
||||
[9, 0],
|
||||
[13, 0],
|
||||
[17, 0],
|
||||
[25, 0],
|
||||
[34, 0],
|
||||
[37, 0],
|
||||
[40, 0],
|
||||
[43, 0],
|
||||
[46, 0],
|
||||
[51, 0],
|
||||
[54, 0],
|
||||
[57, 0],
|
||||
[67, 0]
|
||||
],
|
||||
[
|
||||
[0, 4],
|
||||
[4, 4],
|
||||
[8, 4],
|
||||
[12, 4],
|
||||
[16, 4],
|
||||
[24, 4],
|
||||
[33, 4],
|
||||
[36, 4],
|
||||
[39, 4],
|
||||
[42, 5],
|
||||
[45, 5],
|
||||
[1, 5],
|
||||
[5, 5],
|
||||
[9, 5],
|
||||
[13, 5],
|
||||
[17, 5],
|
||||
[25, 5],
|
||||
[34, 5],
|
||||
[37, 5],
|
||||
[40, 5],
|
||||
[43, 3],
|
||||
[46, 3],
|
||||
[51, 1],
|
||||
[54, 1],
|
||||
[57, 1],
|
||||
[67, 0]
|
||||
],
|
||||
[
|
||||
[0, 3],
|
||||
[4, 3],
|
||||
[8, 3],
|
||||
[12, 3],
|
||||
[16, 3],
|
||||
[24, 3],
|
||||
[33, 4],
|
||||
[36, 4],
|
||||
[39, 4],
|
||||
[42, 4],
|
||||
[45, 5],
|
||||
[1, 5],
|
||||
[5, 5],
|
||||
[9, 5],
|
||||
[13, 5],
|
||||
[17, 5],
|
||||
[25, 5],
|
||||
[34, 5],
|
||||
[37, 5],
|
||||
[40, 5],
|
||||
[43, 5],
|
||||
[46, 5],
|
||||
[51, 2],
|
||||
[54, 2],
|
||||
[57, 2],
|
||||
[67, 0]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,604 @@
|
||||
{
|
||||
"Colors": [
|
||||
[1.0, 0.19999998807907104, 0.099999994039535522, 1.0],
|
||||
[0.19999998807907104, 0.19999998807907104, 1.0, 1.0],
|
||||
[1.0, 0.89999997615814209, 0.099999994039535522, 1.0],
|
||||
[0.099999994039535522, 1.0, 0.099999994039535522, 1.0],
|
||||
[0.79999995231628418, 0.099999994039535522, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.099999994039535522, 0.19999998807907104, 1.0],
|
||||
[0.89999997615814209, 1.0, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.89999997615814209, 1.0, 1.0],
|
||||
[0.5, 0.29999998211860657, 0.19999998807907104, 1.0]
|
||||
],
|
||||
"Mags": [
|
||||
{
|
||||
"EvolutionNumber": 0,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 10, "Eff3": 10, "Eff48": 10, "Eff5": 10, "Eff67": 10}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 10, "Eff3": 10, "Eff48": 10, "Eff5": 10, "Eff67": 10}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 4, "Eff48": 4, "Eff5": 4, "Eff67": 4}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 4, "Eff48": 4, "Eff5": 4, "Eff67": 4}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 2, "Eff5": 2, "Eff67": 2}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 2, "Eff5": 2, "Eff67": 2}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 14, "Eff5": 14, "Eff67": 14}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 14, "Eff5": 14, "Eff67": 14}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 32, "Eff5": 32, "Eff67": 32},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 31, "Eff5": 31, "Eff67": 31}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 32, "Eff5": 32, "Eff67": 32},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 31, "Eff5": 31, "Eff67": 31}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 3, "Eff5": 3, "Eff67": 3}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 3, "Eff5": 3, "Eff67": 3}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 11, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 16, "Eff5": 16, "Eff67": 16},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 15, "Eff5": 15, "Eff67": 15}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 16, "Eff5": 16, "Eff67": 16},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 15, "Eff5": 15, "Eff67": 15}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 18, "Eff5": 18, "Eff67": 18},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 17, "Eff5": 17, "Eff67": 17}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 18, "Eff5": 18, "Eff67": 18},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 17, "Eff5": 17, "Eff67": 17}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 35, "Eff5": 35, "Eff67": 35},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 36, "Eff5": 36, "Eff67": 36}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 35, "Eff5": 35, "Eff67": 35},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 36, "Eff5": 36, "Eff67": 36}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 9, "Eff5": 9, "Eff67": 9},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 8, "Eff5": 8, "Eff67": 8}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 9, "Eff5": 9, "Eff67": 9},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 8, "Eff5": 8, "Eff67": 8}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 40, "Eff2": 40, "Eff3": 40, "Eff48": 46, "Eff5": 40, "Eff67": 46},
|
||||
"Right": {"Eff1": 39, "Eff2": 39, "Eff3": 39, "Eff48": 45, "Eff5": 39, "Eff67": 45}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 20, "Eff5": 20, "Eff67": 20},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 19, "Eff5": 19, "Eff67": 19}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 20, "Eff5": 20, "Eff67": 20},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 19, "Eff5": 19, "Eff67": 19}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [1, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [2, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 21, "Eff2": 21, "Eff3": 21, "Eff48": 54, "Eff5": 21, "Eff67": 54}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 21, "Eff2": 21, "Eff3": 21, "Eff48": 21, "Eff5": 21, "Eff67": 21}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 6,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [8, 9]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [10, 11]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 38, "Eff48": 38, "Eff5": 38, "Eff67": 38}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 38, "Eff48": 38, "Eff5": 38, "Eff67": 38}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 3,
|
||||
"UnknownA2": [3, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 13]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [14, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
}
|
||||
],
|
||||
"UnknownA3": [
|
||||
{"Flags": 33, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 129, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 24},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 67, "UnknownA2": 255, "UnknownA3": 0, "UnknownA4": -45, "UnknownA5": -15},
|
||||
{"Flags": 131, "UnknownA2": 255, "UnknownA3": 0, "UnknownA4": -45, "UnknownA5": -15},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 65, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -60, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 65, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -40, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 34, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 30},
|
||||
{"Flags": 33, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,606 @@
|
||||
{
|
||||
"Colors": [
|
||||
[1.0, 0.19999998807907104, 0.099999994039535522, 1.0],
|
||||
[0.19999998807907104, 0.19999998807907104, 1.0, 1.0],
|
||||
[1.0, 0.89999997615814209, 0.099999994039535522, 1.0],
|
||||
[0.099999994039535522, 1.0, 0.099999994039535522, 1.0],
|
||||
[0.79999995231628418, 0.099999994039535522, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.099999994039535522, 0.19999998807907104, 1.0],
|
||||
[0.89999997615814209, 1.0, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.89999997615814209, 1.0, 1.0],
|
||||
[0.5, 0.29999998211860657, 0.19999998807907104, 1.0]
|
||||
],
|
||||
"Mags": [
|
||||
{
|
||||
"EvolutionNumber": 0,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 10, "Eff3": 10, "Eff48": 10, "Eff5": 10, "Eff67": 10}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 4, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 4, "Eff48": 4, "Eff5": 4, "Eff67": 4}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 72, "Eff5": 2, "Eff67": 72}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 2, "Eff5": 2, "Eff67": 2}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 67, "Eff2": 67, "Eff3": 67, "Eff48": 71, "Eff5": 67, "Eff67": 71},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 70, "Eff5": 14, "Eff67": 70}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 14, "Eff5": 14, "Eff67": 14}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 11, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 74, "Eff5": 35, "Eff67": 74},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 73, "Eff5": 36, "Eff67": 73}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 35, "Eff5": 35, "Eff67": 35},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 36, "Eff5": 36, "Eff67": 36}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 76, "Eff5": 9, "Eff67": 76},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 75, "Eff5": 8, "Eff67": 75}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 9, "Eff5": 9, "Eff67": 9},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 8, "Eff5": 8, "Eff67": 8}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 40, "Eff2": 40, "Eff3": 40, "Eff48": 46, "Eff5": 40, "Eff67": 46},
|
||||
"Right": {"Eff1": 39, "Eff2": 39, "Eff3": 39, "Eff48": 45, "Eff5": 39, "Eff67": 45}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [1, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [2, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 78, "Eff2": 78, "Eff3": 78, "Eff48": 54, "Eff5": 78, "Eff67": 54}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 54, "Eff5": 3, "Eff67": 54}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 12, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 6,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [8, 9]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [10, 11]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 3,
|
||||
"UnknownA2": [3, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 13]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [14, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [15, 16]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [5, 8]
|
||||
}
|
||||
],
|
||||
"UnknownA3": [
|
||||
{"Flags": 33, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 129, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 24},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -24, "UnknownA5": 0},
|
||||
{"Flags": 66, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 65, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -60, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 65, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -40, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 34, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 30},
|
||||
{"Flags": 33, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 129, "UnknownA2": 246, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 66, "UnknownA2": 216, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,792 @@
|
||||
{
|
||||
"Colors": [
|
||||
[1.0, 0.19999998807907104, 0.099999994039535522, 1.0],
|
||||
[0.19999998807907104, 0.19999998807907104, 1.0, 1.0],
|
||||
[1.0, 0.89999997615814209, 0.099999994039535522, 1.0],
|
||||
[0.099999994039535522, 1.0, 0.099999994039535522, 1.0],
|
||||
[0.79999995231628418, 0.099999994039535522, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.099999994039535522, 0.19999998807907104, 1.0],
|
||||
[0.89999997615814209, 1.0, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.89999997615814209, 1.0, 1.0],
|
||||
[0.5, 0.29999998211860657, 0.19999998807907104, 1.0]
|
||||
],
|
||||
"Mags": [
|
||||
{
|
||||
"EvolutionNumber": 0,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 10, "Eff3": 10, "Eff48": 10, "Eff5": 10, "Eff67": 10}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 4, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 4, "Eff48": 4, "Eff5": 4, "Eff67": 4}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 72, "Eff5": 2, "Eff67": 72}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 2, "Eff5": 2, "Eff67": 2}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 67, "Eff2": 67, "Eff3": 67, "Eff48": 71, "Eff5": 67, "Eff67": 71},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 70, "Eff5": 14, "Eff67": 70}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 14, "Eff5": 14, "Eff67": 14}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 11, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 74, "Eff5": 35, "Eff67": 74},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 73, "Eff5": 36, "Eff67": 73}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 35, "Eff5": 35, "Eff67": 35},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 36, "Eff5": 36, "Eff67": 36}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 34, "Eff5": 34, "Eff67": 34},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 33, "Eff5": 33, "Eff67": 33}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 7, "Eff5": 7, "Eff67": 7},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 6, "Eff5": 6, "Eff67": 6}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 76, "Eff5": 9, "Eff67": 76},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 75, "Eff5": 8, "Eff67": 75}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 9, "Eff5": 9, "Eff67": 9},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 8, "Eff5": 8, "Eff67": 8}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 40, "Eff2": 40, "Eff3": 40, "Eff48": 46, "Eff5": 40, "Eff67": 46},
|
||||
"Right": {"Eff1": 39, "Eff2": 39, "Eff3": 39, "Eff48": 45, "Eff5": 39, "Eff67": 45}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 0, "Eff5": 0, "Eff67": 0},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 1, "Eff5": 1, "Eff67": 1}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [1, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [2, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 78, "Eff2": 78, "Eff3": 78, "Eff48": 54, "Eff5": 78, "Eff67": 54}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 54, "Eff5": 3, "Eff67": 54}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 12, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 6,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [8, 9]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [10, 11]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 3,
|
||||
"UnknownA2": [3, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 13]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [14, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [15, 16]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [5, 8]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [17, 18]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [19, 20]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
}
|
||||
],
|
||||
"UnknownA3": [
|
||||
{"Flags": 33, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 129, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 24},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -24, "UnknownA5": 0},
|
||||
{"Flags": 66, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 65, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -60, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 65, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -40, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 34, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 30},
|
||||
{"Flags": 33, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 129, "UnknownA2": 246, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 66, "UnknownA2": 216, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 64, "UnknownA2": 6, "UnknownA3": 0, "UnknownA4": 10, "UnknownA5": 50},
|
||||
{"Flags": 64, "UnknownA2": 6, "UnknownA3": 0, "UnknownA4": -50, "UnknownA5": -10},
|
||||
{"Flags": 64, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 80},
|
||||
{"Flags": 64, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -80, "UnknownA5": 0}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,918 @@
|
||||
{
|
||||
"Colors": [
|
||||
[1.0, 0.19999998807907104, 0.099999994039535522, 1.0],
|
||||
[0.19999998807907104, 0.19999998807907104, 1.0, 1.0],
|
||||
[1.0, 0.89999997615814209, 0.099999994039535522, 1.0],
|
||||
[0.099999994039535522, 1.0, 0.099999994039535522, 1.0],
|
||||
[0.79999995231628418, 0.099999994039535522, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.099999994039535522, 0.19999998807907104, 1.0],
|
||||
[0.89999997615814209, 1.0, 1.0, 1.0],
|
||||
[0.099999994039535522, 0.89999997615814209, 1.0, 1.0],
|
||||
[0.5, 0.29999998211860657, 0.19999998807907104, 1.0],
|
||||
[1.0, 0.39999997615814209, 0.0, 1.0],
|
||||
[0.50196075439453125, 0.54509800672531128, 0.97647053003311157, 1.0],
|
||||
[0.50196075439453125, 0.50196075439453125, 0.0, 1.0],
|
||||
[0.0, 0.94117641448974609, 0.71372544765472412, 1.0],
|
||||
[0.79999995231628418, 0.098039209842681885, 0.39215683937072754, 1.0],
|
||||
[0.49803918600082397, 0.49803918600082397, 0.49803918600082397, 1.0],
|
||||
[0.99607837200164795, 0.99607837200164795, 0.83529406785964966, 1.0],
|
||||
[0.99607837200164795, 0.49803918600082397, 0.78431367874145508, 1.0],
|
||||
[0.0, 0.49803918600082397, 0.32156860828399658, 1.0]
|
||||
],
|
||||
"Mags": [
|
||||
{
|
||||
"EvolutionNumber": 0,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 4, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 4, "Eff67": 13}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 72, "Eff5": 2, "Eff67": 72}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 2, "Eff2": 2, "Eff3": 2, "Eff48": 72, "Eff5": 2, "Eff67": 72}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 67, "Eff2": 67, "Eff3": 67, "Eff48": 71, "Eff5": 67, "Eff67": 71},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 70, "Eff5": 14, "Eff67": 70}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 67, "Eff2": 67, "Eff3": 67, "Eff48": 71, "Eff5": 67, "Eff67": 71},
|
||||
"Right": {"Eff1": 14, "Eff2": 14, "Eff3": 14, "Eff48": 70, "Eff5": 14, "Eff67": 70}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 30, "Eff2": 30, "Eff3": 30, "Eff48": 49, "Eff5": 30, "Eff67": 49},
|
||||
"Right": {"Eff1": 29, "Eff2": 29, "Eff3": 29, "Eff48": 48, "Eff5": 29, "Eff67": 48}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 32, "Eff2": 32, "Eff3": 32, "Eff48": 61, "Eff5": 32, "Eff67": 61},
|
||||
"Right": {"Eff1": 31, "Eff2": 31, "Eff3": 31, "Eff48": 60, "Eff5": 31, "Eff67": 60}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 28, "Eff2": 28, "Eff3": 28, "Eff48": 51, "Eff5": 28, "Eff67": 51},
|
||||
"Right": {"Eff1": 27, "Eff2": 27, "Eff3": 27, "Eff48": 50, "Eff5": 27, "Eff67": 50}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 18, "Eff2": 18, "Eff3": 18, "Eff48": 66, "Eff5": 18, "Eff67": 66},
|
||||
"Right": {"Eff1": 17, "Eff2": 17, "Eff3": 17, "Eff48": 65, "Eff5": 17, "Eff67": 65}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 74, "Eff5": 35, "Eff67": 74},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 73, "Eff5": 36, "Eff67": 73}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 35, "Eff2": 35, "Eff3": 35, "Eff48": 74, "Eff5": 35, "Eff67": 74},
|
||||
"Right": {"Eff1": 36, "Eff2": 36, "Eff3": 36, "Eff48": 73, "Eff5": 36, "Eff67": 73}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 34, "Eff2": 34, "Eff3": 34, "Eff48": 69, "Eff5": 34, "Eff67": 69},
|
||||
"Right": {"Eff1": 33, "Eff2": 33, "Eff3": 33, "Eff48": 68, "Eff5": 33, "Eff67": 68}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [0, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 7, "Eff2": 7, "Eff3": 7, "Eff48": 42, "Eff5": 7, "Eff67": 42},
|
||||
"Right": {"Eff1": 6, "Eff2": 6, "Eff3": 6, "Eff48": 41, "Eff5": 6, "Eff67": 41}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 76, "Eff5": 9, "Eff67": 76},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 75, "Eff5": 8, "Eff67": 75}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 9, "Eff2": 9, "Eff3": 9, "Eff48": 76, "Eff5": 9, "Eff67": 76},
|
||||
"Right": {"Eff1": 8, "Eff2": 8, "Eff3": 8, "Eff48": 75, "Eff5": 8, "Eff67": 75}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 40, "Eff2": 40, "Eff3": 40, "Eff48": 46, "Eff5": 40, "Eff67": 46},
|
||||
"Right": {"Eff1": 39, "Eff2": 39, "Eff3": 39, "Eff48": 45, "Eff5": 39, "Eff67": 45}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 40, "Eff2": 40, "Eff3": 40, "Eff48": 46, "Eff5": 40, "Eff67": 46},
|
||||
"Right": {"Eff1": 39, "Eff2": 39, "Eff3": 39, "Eff48": 45, "Eff5": 39, "Eff67": 45}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 53, "Eff5": 20, "Eff67": 53},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 52, "Eff5": 19, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [1, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 23, "Eff2": 23, "Eff3": 23, "Eff48": 53, "Eff5": 23, "Eff67": 53},
|
||||
"Right": {"Eff1": 22, "Eff2": 22, "Eff3": 22, "Eff48": 52, "Eff5": 22, "Eff67": 52}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [2, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 25, "Eff2": 25, "Eff3": 25, "Eff48": 56, "Eff5": 25, "Eff67": 56},
|
||||
"Right": {"Eff1": 24, "Eff2": 24, "Eff3": 24, "Eff48": 55, "Eff5": 24, "Eff67": 55}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 20, "Eff2": 20, "Eff3": 20, "Eff48": 58, "Eff5": 20, "Eff67": 58},
|
||||
"Right": {"Eff1": 19, "Eff2": 19, "Eff3": 19, "Eff48": 57, "Eff5": 19, "Eff67": 57}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 78, "Eff2": 78, "Eff3": 78, "Eff48": 54, "Eff5": 78, "Eff67": 54}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 78, "Eff2": 78, "Eff3": 78, "Eff48": 54, "Eff5": 78, "Eff67": 54}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 1,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 12, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 13, "Eff48": 13, "Eff5": 12, "Eff67": 13}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 2,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 6,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [8, 9]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [10, 11]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 38, "Eff2": 38, "Eff3": 59, "Eff48": 59, "Eff5": 38, "Eff67": 59}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 3,
|
||||
"UnknownA2": [3, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 13]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [14, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 3,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [15, 16]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [2, 4]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [5, 8]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [17, 18]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 81, "Eff2": 81, "Eff3": 81, "Eff48": 81, "Eff5": 81, "Eff67": 81},
|
||||
"Right": {"Eff1": 80, "Eff2": 80, "Eff3": 80, "Eff48": 80, "Eff5": 80, "Eff67": 80}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [19, 20]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 0, "Eff2": 0, "Eff3": 0, "Eff48": 43, "Eff5": 0, "Eff67": 43},
|
||||
"Right": {"Eff1": 1, "Eff2": 1, "Eff3": 1, "Eff48": 44, "Eff5": 1, "Eff67": 44}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 26, "Eff2": 26, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [6, 7]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 82, "Eff2": 82, "Eff3": 82, "Eff48": 82, "Eff5": 82, "Eff67": 82}
|
||||
},
|
||||
"RenderFlags": 255,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 16, "Eff2": 16, "Eff3": 16, "Eff48": 64, "Eff5": 16, "Eff67": 64},
|
||||
"Right": {"Eff1": 15, "Eff2": 15, "Eff3": 15, "Eff48": 63, "Eff5": 15, "Eff67": 63}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 4, "Eff3": 11, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [12, 13]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 3, "Eff2": 3, "Eff3": 3, "Eff48": 62, "Eff5": 3, "Eff67": 62}
|
||||
},
|
||||
"RenderFlags": 1,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 37, "Eff2": 37, "Eff3": 37, "Eff48": 47, "Eff5": 37, "Eff67": 47}
|
||||
},
|
||||
"RenderFlags": 10,
|
||||
"UnknownA2": [255, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 4, "Eff2": 77, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 3,
|
||||
"UnknownA2": [10, 11]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 5, "Eff2": 5, "Eff3": 77, "Eff48": 13, "Eff5": 12, "Eff67": 11}
|
||||
},
|
||||
"RenderFlags": 2,
|
||||
"UnknownA2": [14, 255]
|
||||
},
|
||||
{
|
||||
"EvolutionNumber": 4,
|
||||
"MotionRefs1": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"MotionRefs2": {
|
||||
"Left": {"Eff1": 255, "Eff2": 255, "Eff3": 255, "Eff48": 255, "Eff5": 255, "Eff67": 255},
|
||||
"Right": {"Eff1": 10, "Eff2": 13, "Eff3": 10, "Eff48": 13, "Eff5": 10, "Eff67": 13}
|
||||
},
|
||||
"RenderFlags": 0,
|
||||
"UnknownA2": [255, 255]
|
||||
}
|
||||
],
|
||||
"UnknownA3": [
|
||||
{"Flags": 33, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 129, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 24},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 20},
|
||||
{"Flags": 130, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -24, "UnknownA5": 0},
|
||||
{"Flags": 66, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 34, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": -20, "UnknownA5": 0},
|
||||
{"Flags": 65, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -60, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 60},
|
||||
{"Flags": 65, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": -40, "UnknownA5": 0},
|
||||
{"Flags": 68, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 34, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 35, "UnknownA2": 1, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 30},
|
||||
{"Flags": 33, "UnknownA2": 2, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 16},
|
||||
{"Flags": 129, "UnknownA2": 246, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 66, "UnknownA2": 216, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 40},
|
||||
{"Flags": 64, "UnknownA2": 6, "UnknownA3": 0, "UnknownA4": 10, "UnknownA5": 50},
|
||||
{"Flags": 64, "UnknownA2": 6, "UnknownA3": 0, "UnknownA4": -50, "UnknownA5": -10},
|
||||
{"Flags": 64, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": 0, "UnknownA5": 80},
|
||||
{"Flags": 64, "UnknownA2": 15, "UnknownA3": 0, "UnknownA4": -80, "UnknownA5": 0}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -122,12 +122,12 @@
|
||||
"000F03": "SONIC KNUCKLE",
|
||||
"000F04": "LOGiN",
|
||||
"001000": "OROTIAGITO",
|
||||
"001001": "AGITO",
|
||||
"001002": "AGITO",
|
||||
"001003": "AGITO",
|
||||
"001004": "AGITO",
|
||||
"001005": "AGITO",
|
||||
"001006": "AGITO",
|
||||
"001001": "AGITO", // 1975 (real)
|
||||
"001002": "AGITO", // 1983
|
||||
"001003": "AGITO", // 2001
|
||||
"001004": "AGITO", // 1991
|
||||
"001005": "AGITO", // 1977
|
||||
"001006": "AGITO", // 1980
|
||||
"001007": "RAIKIRI",
|
||||
"001100": "SOUL EATER",
|
||||
"001101": "SOUL BANISH",
|
||||
@@ -693,15 +693,15 @@
|
||||
"008F06": "FLOWEN'S SWORD",
|
||||
"008F07": "FLOWEN'S SWORD",
|
||||
"008F08": "FLOWEN'S SWORD",
|
||||
"009000": "DB'S SABER",
|
||||
"009001": "DB'S SABER",
|
||||
"009002": "DB'S SABER",
|
||||
"009003": "DB'S SABER",
|
||||
"009004": "DB'S SABER",
|
||||
"009005": "DB'S SABER",
|
||||
"009006": "DB'S SABER",
|
||||
"009007": "DB'S SABER",
|
||||
"009008": "DB'S SABER",
|
||||
"009000": "DB'S SABER", // 3062
|
||||
"009001": "DB'S SABER", // 3067
|
||||
"009002": "DB'S SABER", // 3069 Chris
|
||||
"009003": "DB'S SABER", // 3064
|
||||
"009004": "DB'S SABER", // 3069 Torato
|
||||
"009005": "DB'S SABER", // 3073
|
||||
"009006": "DB'S SABER", // 3070
|
||||
"009007": "DB'S SABER", // 3075
|
||||
"009008": "DB'S SABER", // 3077
|
||||
"009100": "GI GUE BAZOOKA",
|
||||
"009200": "GUARDIANNA",
|
||||
"009300": "VIRIDIA CARD",
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"BonusLuckTable": {"-10": -15, "-5": -8, "0": 0, "10": 15, "5": 8},
|
||||
"DefaultBonusDeltaTable": {
|
||||
"Bluefull": {"-10": 5, "-5": 15, "0": 60, "10": 5, "5": 15},
|
||||
"Greennill": {"-10": 10, "-5": 25, "0": 50, "10": 5, "5": 10},
|
||||
"Oran": {"-10": 5, "-5": 10, "0": 50, "10": 10, "5": 25},
|
||||
"Pinkal": {"-10": 5, "-5": 10, "0": 50, "10": 10, "5": 25},
|
||||
"Purplenum": {"-10": 10, "-5": 25, "0": 50, "10": 5, "5": 10},
|
||||
"Redria": {"-10": 5, "-5": 10, "0": 50, "10": 10, "5": 25},
|
||||
"Skyly": {"-10": 5, "-5": 10, "0": 50, "10": 10, "5": 25},
|
||||
"Viridia": {"-10": 5, "-5": 15, "0": 60, "10": 5, "5": 15},
|
||||
"Whitill": {"-10": 5, "-5": 15, "0": 60, "10": 5, "5": 15},
|
||||
"Yellowboze": {"-10": 10, "-5": 25, "0": 50, "10": 5, "5": 10}
|
||||
},
|
||||
"DefaultGrindDeltaTable": {
|
||||
"Bluefull": {"-1": 10, "-2": 7, "-3": 0, "0": 60, "1": 13, "2": 7, "3": 3},
|
||||
"Greennill": {"-1": 10, "-2": 5, "-3": 0, "0": 70, "1": 10, "2": 5, "3": 0},
|
||||
"Oran": {"-1": 13, "-2": 7, "-3": 3, "0": 60, "1": 10, "2": 7, "3": 0},
|
||||
"Pinkal": {"-1": 13, "-2": 7, "-3": 3, "0": 60, "1": 10, "2": 7, "3": 0},
|
||||
"Purplenum": {"-1": 10, "-2": 5, "-3": 0, "0": 70, "1": 10, "2": 5, "3": 0},
|
||||
"Redria": {"-1": 13, "-2": 7, "-3": 3, "0": 60, "1": 10, "2": 7, "3": 0},
|
||||
"Skyly": {"-1": 13, "-2": 7, "-3": 3, "0": 60, "1": 10, "2": 7, "3": 0},
|
||||
"Viridia": {"-1": 10, "-2": 7, "-3": 0, "0": 60, "1": 13, "2": 7, "3": 3},
|
||||
"Whitill": {"-1": 10, "-2": 7, "-3": 0, "0": 60, "1": 13, "2": 7, "3": 3},
|
||||
"Yellowboze": {"-1": 10, "-2": 5, "-3": 0, "0": 70, "1": 10, "2": 5, "3": 0}
|
||||
},
|
||||
"DefaultSpecialDeltaTable": {
|
||||
"Bluefull": {"-1": 30, "0": 60, "1": 10},
|
||||
"Greennill": {"-1": 10, "0": 65, "1": 25},
|
||||
"Oran": {"-1": 15, "0": 70, "1": 15},
|
||||
"Pinkal": {"-1": 15, "0": 70, "1": 15},
|
||||
"Purplenum": {"-1": 10, "0": 65, "1": 25},
|
||||
"Redria": {"-1": 20, "0": 60, "1": 20},
|
||||
"Skyly": {"-1": 15, "0": 70, "1": 15},
|
||||
"Viridia": {"-1": 30, "0": 60, "1": 10},
|
||||
"Whitill": {"-1": 30, "0": 60, "1": 10},
|
||||
"Yellowboze": {"-1": 10, "0": 65, "1": 25}
|
||||
},
|
||||
"FavoredBonusDeltaTable": {
|
||||
"Bluefull": {"-10": 2, "-5": 10, "0": 60, "10": 8, "5": 20},
|
||||
"Greennill": {"-10": 7, "-5": 20, "0": 50, "10": 8, "5": 15},
|
||||
"Oran": {"-10": 2, "-5": 5, "0": 50, "10": 13, "5": 30},
|
||||
"Pinkal": {"-10": 2, "-5": 5, "0": 50, "10": 13, "5": 30},
|
||||
"Purplenum": {"-10": 7, "-5": 20, "0": 50, "10": 8, "5": 15},
|
||||
"Redria": {"-10": 0, "-5": 0, "0": 0, "10": 0, "5": 0},
|
||||
"Skyly": {"-10": 2, "-5": 5, "0": 50, "10": 13, "5": 30},
|
||||
"Viridia": {"-10": 2, "-5": 10, "0": 60, "10": 8, "5": 20},
|
||||
"Whitill": {"-10": 2, "-5": 10, "0": 60, "10": 8, "5": 20},
|
||||
"Yellowboze": {"-10": 7, "-5": 20, "0": 50, "10": 8, "5": 15}
|
||||
},
|
||||
"FavoredGrindDeltaTable": {
|
||||
"Bluefull": {"-1": 7, "-2": 0, "-3": 0, "0": 50, "1": 25, "2": 13, "3": 5},
|
||||
"Greennill": {"-1": 10, "-2": 0, "-3": 0, "0": 60, "1": 20, "2": 7, "3": 3},
|
||||
"Oran": {"-1": 10, "-2": 5, "-3": 0, "0": 50, "1": 20, "2": 12, "3": 3},
|
||||
"Pinkal": {"-1": 10, "-2": 5, "-3": 0, "0": 50, "1": 20, "2": 12, "3": 3},
|
||||
"Purplenum": {"-1": 10, "-2": 0, "-3": 0, "0": 60, "1": 20, "2": 7, "3": 3},
|
||||
"Redria": {"-1": 0, "-2": 0, "-3": 0, "0": 0, "1": 0, "2": 0, "3": 0},
|
||||
"Skyly": {"-1": 10, "-2": 5, "-3": 0, "0": 50, "1": 20, "2": 12, "3": 3},
|
||||
"Viridia": {"-1": 7, "-2": 0, "-3": 0, "0": 50, "1": 25, "2": 13, "3": 5},
|
||||
"Whitill": {"-1": 7, "-2": 0, "-3": 0, "0": 50, "1": 25, "2": 13, "3": 5},
|
||||
"Yellowboze": {"-1": 10, "-2": 0, "-3": 0, "0": 60, "1": 20, "2": 7, "3": 3}
|
||||
},
|
||||
"FavoredSpecialDeltaTable": {
|
||||
"Bluefull": {"-1": 25, "0": 50, "1": 25},
|
||||
"Greennill": {"-1": 5, "0": 55, "1": 40},
|
||||
"Oran": {"-1": 10, "0": 60, "1": 30},
|
||||
"Pinkal": {"-1": 10, "0": 60, "1": 30},
|
||||
"Purplenum": {"-1": 5, "0": 55, "1": 40},
|
||||
"Redria": {"-1": 0, "0": 0, "1": 0},
|
||||
"Skyly": {"-1": 10, "0": 60, "1": 30},
|
||||
"Viridia": {"-1": 25, "0": 50, "1": 25},
|
||||
"Whitill": {"-1": 25, "0": 50, "1": 25},
|
||||
"Yellowboze": {"-1": 5, "0": 55, "1": 40}
|
||||
},
|
||||
"GrindLuckTable": {"-1": -3, "-2": -5, "-3": -10, "0": 0, "1": 3, "2": 5, "3": 10},
|
||||
"SpecialLuckTable": {"-1": -20, "0": 0, "1": 20}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
{
|
||||
"CommonRecoveryTable": [
|
||||
[0, 15, 3, 15, 6, 7, 9, 11, 12, 15, 15],
|
||||
[0, 1, 3, 4, 6, 7, 9, 11, 12, 15, 15],
|
||||
[0, 1, 3, 4, 6, 7, 9, 11, 12, 15, 15],
|
||||
[15, 1, 15, 4, 6, 7, 9, 11, 12, 15, 15],
|
||||
[15, 1, 15, 4, 6, 7, 9, 11, 12, 15, 15],
|
||||
[15, 1, 15, 4, 6, 7, 9, 11, 12, 15, 15]
|
||||
],
|
||||
"RareRecoveryTable": [
|
||||
[
|
||||
[2, 0],
|
||||
[5, 0],
|
||||
[8, 0],
|
||||
[10, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 100]
|
||||
],
|
||||
[
|
||||
[2, 25],
|
||||
[5, 25],
|
||||
[8, 24],
|
||||
[10, 0],
|
||||
[13, 0],
|
||||
[14, 1],
|
||||
[15, 25]
|
||||
],
|
||||
[
|
||||
[2, 37],
|
||||
[5, 37],
|
||||
[8, 10],
|
||||
[10, 4],
|
||||
[13, 0],
|
||||
[14, 2],
|
||||
[15, 10]
|
||||
],
|
||||
[
|
||||
[2, 42],
|
||||
[5, 42],
|
||||
[8, 9],
|
||||
[10, 4],
|
||||
[13, 0],
|
||||
[14, 3],
|
||||
[15, 0]
|
||||
],
|
||||
[
|
||||
[2, 41],
|
||||
[5, 41],
|
||||
[8, 9],
|
||||
[10, 5],
|
||||
[13, 0],
|
||||
[14, 4],
|
||||
[15, 0]
|
||||
]
|
||||
],
|
||||
"TechDiskLevelTable": [
|
||||
[
|
||||
{"PlayerLevelDivisor": 3},
|
||||
{"PlayerLevelDivisor": 4},
|
||||
{"PlayerLevelDivisor": 6},
|
||||
{"PlayerLevelDivisor": 3},
|
||||
{"PlayerLevelDivisor": 35},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
[
|
||||
{"PlayerLevelDivisor": 6},
|
||||
{"PlayerLevelDivisor": 7},
|
||||
{"PlayerLevelDivisor": 8},
|
||||
{"PlayerLevelDivisor": 6},
|
||||
{"PlayerLevelDivisor": 35},
|
||||
{"PlayerLevelDivisor": 9},
|
||||
{"PlayerLevelDivisor": 7},
|
||||
{"PlayerLevelDivisor": 6},
|
||||
{"PlayerLevelDivisor": 8},
|
||||
{"PlayerLevelDivisor": 9},
|
||||
{"PlayerLevelDivisor": 12},
|
||||
{"PlayerLevelDivisor": 8},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
[
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"PlayerLevelDivisor": 35},
|
||||
{"PlayerLevelDivisor": 8},
|
||||
{"PlayerLevelDivisor": 7},
|
||||
{"PlayerLevelDivisor": 5},
|
||||
{"PlayerLevelDivisor": 6},
|
||||
{"PlayerLevelDivisor": 8},
|
||||
{"PlayerLevelDivisor": 9},
|
||||
{"PlayerLevelDivisor": 10},
|
||||
{},
|
||||
{},
|
||||
{"PlayerLevelDivisor": 10},
|
||||
{"PlayerLevelDivisor": 11},
|
||||
{"PlayerLevelDivisor": 12}
|
||||
],
|
||||
[
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"PlayerLevelDivisor": 35},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 12, "MinLevel": 4},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{"MaxLevel": 10, "MinLevel": 3},
|
||||
{},
|
||||
{},
|
||||
{"PlayerLevelDivisor": 12},
|
||||
{"PlayerLevelDivisor": 13},
|
||||
{"PlayerLevelDivisor": 11}
|
||||
],
|
||||
[
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"PlayerLevelDivisor": 35},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 14, "MinLevel": 5},
|
||||
{"MaxLevel": 13, "MinLevel": 4},
|
||||
{"MaxLevel": 13, "MinLevel": 4},
|
||||
{"MaxLevel": 13, "MinLevel": 4},
|
||||
{},
|
||||
{},
|
||||
{"MaxLevel": 13, "MinLevel": 3},
|
||||
{"MaxLevel": 13, "MinLevel": 3},
|
||||
{"MaxLevel": 13, "MinLevel": 3}
|
||||
]
|
||||
],
|
||||
"TechDiskTable": [
|
||||
[
|
||||
[0, 18],
|
||||
[1, 18],
|
||||
[2, 18],
|
||||
[3, 18],
|
||||
[4, 18],
|
||||
[5, 2],
|
||||
[6, 3],
|
||||
[7, 3],
|
||||
[8, 2],
|
||||
[9, 0],
|
||||
[10, 0],
|
||||
[11, 0],
|
||||
[12, 0],
|
||||
[13, 0],
|
||||
[14, 0],
|
||||
[15, 0],
|
||||
[16, 0]
|
||||
],
|
||||
[
|
||||
[0, 7],
|
||||
[1, 7],
|
||||
[2, 7],
|
||||
[3, 7],
|
||||
[4, 7],
|
||||
[5, 6],
|
||||
[6, 6],
|
||||
[7, 6],
|
||||
[8, 7],
|
||||
[9, 8],
|
||||
[10, 8],
|
||||
[11, 8],
|
||||
[12, 5],
|
||||
[13, 5],
|
||||
[14, 2],
|
||||
[15, 2],
|
||||
[16, 2]
|
||||
],
|
||||
[
|
||||
[0, 5],
|
||||
[1, 5],
|
||||
[2, 5],
|
||||
[3, 6],
|
||||
[4, 5],
|
||||
[5, 5],
|
||||
[6, 5],
|
||||
[7, 5],
|
||||
[8, 5],
|
||||
[9, 5],
|
||||
[10, 5],
|
||||
[11, 5],
|
||||
[12, 6],
|
||||
[13, 6],
|
||||
[14, 9],
|
||||
[15, 9],
|
||||
[16, 9]
|
||||
],
|
||||
[
|
||||
[0, 6],
|
||||
[1, 6],
|
||||
[2, 6],
|
||||
[3, 5],
|
||||
[4, 5],
|
||||
[5, 6],
|
||||
[6, 6],
|
||||
[7, 6],
|
||||
[8, 6],
|
||||
[9, 6],
|
||||
[10, 6],
|
||||
[11, 6],
|
||||
[12, 6],
|
||||
[13, 6],
|
||||
[14, 6],
|
||||
[15, 6],
|
||||
[16, 6]
|
||||
],
|
||||
[
|
||||
[0, 6],
|
||||
[1, 6],
|
||||
[2, 6],
|
||||
[3, 5],
|
||||
[4, 5],
|
||||
[5, 6],
|
||||
[6, 6],
|
||||
[7, 6],
|
||||
[8, 6],
|
||||
[9, 6],
|
||||
[10, 6],
|
||||
[11, 6],
|
||||
[12, 6],
|
||||
[13, 6],
|
||||
[14, 6],
|
||||
[15, 6],
|
||||
[16, 6]
|
||||
]
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,862 @@
|
||||
{
|
||||
"BonusRangeTable1": [
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 15],
|
||||
[10, 15],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 17],
|
||||
[10, 19]
|
||||
],
|
||||
"BonusRangeTable2": [
|
||||
[10, 13],
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 15],
|
||||
[10, 15],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 19]
|
||||
],
|
||||
"BonusTypeTable1": [
|
||||
[
|
||||
[0, 60],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 50],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 15],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 30],
|
||||
[1, 10],
|
||||
[2, 15],
|
||||
[3, 25],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 15],
|
||||
[3, 20],
|
||||
[4, 30],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 25],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 30],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 25],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 25],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 10]
|
||||
]
|
||||
],
|
||||
"BonusTypeTable2": [
|
||||
[
|
||||
[0, 100],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 100],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 65],
|
||||
[1, 5],
|
||||
[2, 10],
|
||||
[3, 10],
|
||||
[4, 10],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 45],
|
||||
[1, 10],
|
||||
[2, 10],
|
||||
[3, 15],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 30],
|
||||
[1, 25],
|
||||
[2, 20],
|
||||
[3, 10],
|
||||
[4, 10],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 15],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 25],
|
||||
[4, 20],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 15],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 25],
|
||||
[4, 15],
|
||||
[5, 10]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 15]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 15],
|
||||
[3, 15],
|
||||
[4, 20],
|
||||
[5, 20]
|
||||
]
|
||||
],
|
||||
"DefaultDringRangeTable": [
|
||||
[0, 2],
|
||||
[0, 3],
|
||||
[0, 4],
|
||||
[0, 6],
|
||||
[0, 8],
|
||||
[0, 10]
|
||||
],
|
||||
"FavoredDringRangeTable": [
|
||||
[0, 1],
|
||||
[0, 3],
|
||||
[1, 5],
|
||||
[2, 8],
|
||||
[3, 11],
|
||||
[3, 16]
|
||||
],
|
||||
"SpecialModeTable": [
|
||||
[
|
||||
[0, 85],
|
||||
[1, 15],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 70],
|
||||
[1, 30],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 50],
|
||||
[1, 50],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 80],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 60],
|
||||
[2, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 40],
|
||||
[2, 40]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 30],
|
||||
[2, 60]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 10],
|
||||
[2, 80]
|
||||
]
|
||||
],
|
||||
"WeaponTypeWeightTables": [
|
||||
[
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 15],
|
||||
[30, 25],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 20],
|
||||
[30, 20],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 25],
|
||||
[30, 10],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 5],
|
||||
[45, 30]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 5],
|
||||
[25, 25],
|
||||
[30, 20],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 25],
|
||||
[25, 20],
|
||||
[30, 10],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 20],
|
||||
[30, 20],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[5, 8],
|
||||
[30, 8],
|
||||
[1, 12],
|
||||
[10, 8],
|
||||
[15, 0],
|
||||
[20, 16],
|
||||
[26, 12],
|
||||
[35, 8],
|
||||
[46, 12],
|
||||
[49, 8],
|
||||
[53, 8]
|
||||
],
|
||||
[
|
||||
[5, 12],
|
||||
[30, 18],
|
||||
[1, 10],
|
||||
[10, 0],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 10],
|
||||
[35, 8],
|
||||
[46, 10],
|
||||
[49, 8],
|
||||
[53, 8]
|
||||
],
|
||||
[
|
||||
[5, 8],
|
||||
[30, 12],
|
||||
[1, 10],
|
||||
[10, 18],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 10],
|
||||
[35, 0],
|
||||
[46, 10],
|
||||
[49, 8],
|
||||
[53, 8]
|
||||
],
|
||||
[
|
||||
[5, 8],
|
||||
[30, 8],
|
||||
[1, 10],
|
||||
[10, 8],
|
||||
[15, 8],
|
||||
[20, 18],
|
||||
[26, 10],
|
||||
[35, 8],
|
||||
[46, 10],
|
||||
[49, 12],
|
||||
[53, 0]
|
||||
],
|
||||
[
|
||||
[5, 13],
|
||||
[30, 8],
|
||||
[1, 10],
|
||||
[10, 3],
|
||||
[15, 8],
|
||||
[20, 3],
|
||||
[26, 10],
|
||||
[35, 19],
|
||||
[46, 10],
|
||||
[49, 8],
|
||||
[53, 8]
|
||||
],
|
||||
[
|
||||
[5, 8],
|
||||
[30, 0],
|
||||
[1, 10],
|
||||
[10, 8],
|
||||
[15, 8],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[35, 8],
|
||||
[46, 10],
|
||||
[49, 8],
|
||||
[53, 18]
|
||||
],
|
||||
[
|
||||
[5, 0],
|
||||
[30, 9],
|
||||
[1, 10],
|
||||
[10, 9],
|
||||
[15, 16],
|
||||
[20, 9],
|
||||
[26, 10],
|
||||
[35, 9],
|
||||
[46, 10],
|
||||
[49, 9],
|
||||
[53, 9]
|
||||
],
|
||||
[
|
||||
[5, 16],
|
||||
[30, 8],
|
||||
[1, 10],
|
||||
[10, 11],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 10],
|
||||
[35, 8],
|
||||
[46, 10],
|
||||
[49, 0],
|
||||
[53, 11]
|
||||
],
|
||||
[
|
||||
[5, 9],
|
||||
[30, 9],
|
||||
[1, 10],
|
||||
[10, 9],
|
||||
[15, 9],
|
||||
[20, 9],
|
||||
[26, 9],
|
||||
[35, 9],
|
||||
[46, 9],
|
||||
[49, 9],
|
||||
[53, 9]
|
||||
],
|
||||
[
|
||||
[5, 7],
|
||||
[30, 7],
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 12],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[6, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 7],
|
||||
[40, 16],
|
||||
[15, 0],
|
||||
[20, 10],
|
||||
[31, 7],
|
||||
[46, 12],
|
||||
[53, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 0],
|
||||
[6, 12],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 7],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[31, 16],
|
||||
[46, 10],
|
||||
[53, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 16],
|
||||
[6, 7],
|
||||
[26, 10],
|
||||
[35, 0],
|
||||
[49, 7],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[31, 12],
|
||||
[46, 10],
|
||||
[53, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[6, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 12],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 16],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 0]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 3],
|
||||
[6, 12],
|
||||
[26, 10],
|
||||
[35, 17],
|
||||
[49, 7],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 3],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[6, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 7],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 12],
|
||||
[31, 0],
|
||||
[46, 10],
|
||||
[53, 16]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[6, 0],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 7],
|
||||
[40, 14],
|
||||
[15, 14],
|
||||
[20, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 10],
|
||||
[6, 15],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[49, 0],
|
||||
[40, 7],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 10]
|
||||
],
|
||||
[
|
||||
[1, 9],
|
||||
[10, 8],
|
||||
[6, 8],
|
||||
[26, 9],
|
||||
[35, 8],
|
||||
[49, 8],
|
||||
[40, 9],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[31, 8],
|
||||
[46, 9],
|
||||
[53, 8]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[6, 7],
|
||||
[26, 10],
|
||||
[35, 12],
|
||||
[49, 7],
|
||||
[40, 0],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 0],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[40, 16],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 0],
|
||||
[6, 12],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 16],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 16],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 0],
|
||||
[31, 12],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 16],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 0],
|
||||
[49, 12]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 3],
|
||||
[6, 12],
|
||||
[15, 7],
|
||||
[20, 3],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 17],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 0],
|
||||
[46, 10],
|
||||
[53, 16],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 0],
|
||||
[15, 14],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 14],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 10],
|
||||
[6, 15],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 10],
|
||||
[49, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[11, 8],
|
||||
[6, 8],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 9],
|
||||
[40, 9],
|
||||
[36, 8],
|
||||
[31, 8],
|
||||
[46, 9],
|
||||
[53, 8],
|
||||
[49, 8]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 0],
|
||||
[36, 12],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 0],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[40, 16],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 0],
|
||||
[6, 12],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 16],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 16],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 0],
|
||||
[31, 12],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 16],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 0],
|
||||
[49, 12]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 3],
|
||||
[6, 12],
|
||||
[15, 7],
|
||||
[20, 3],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 17],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 7],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 0],
|
||||
[46, 10],
|
||||
[53, 16],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 0],
|
||||
[15, 14],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 14],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 10],
|
||||
[6, 15],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 7],
|
||||
[36, 7],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 10],
|
||||
[49, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[11, 8],
|
||||
[6, 8],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 9],
|
||||
[40, 9],
|
||||
[36, 8],
|
||||
[31, 8],
|
||||
[46, 9],
|
||||
[53, 8],
|
||||
[49, 8]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[11, 7],
|
||||
[6, 7],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[40, 0],
|
||||
[36, 12],
|
||||
[31, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[49, 7]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,972 @@
|
||||
{
|
||||
"BonusRangeTable1": [
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 15],
|
||||
[10, 15],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 17],
|
||||
[10, 19]
|
||||
],
|
||||
"BonusRangeTable2": [
|
||||
[10, 13],
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 14],
|
||||
[10, 15],
|
||||
[10, 15],
|
||||
[10, 16],
|
||||
[10, 16],
|
||||
[10, 19]
|
||||
],
|
||||
"BonusTypeTable1": [
|
||||
[
|
||||
[0, 60],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 50],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 15],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 30],
|
||||
[1, 10],
|
||||
[2, 15],
|
||||
[3, 25],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 15],
|
||||
[3, 20],
|
||||
[4, 30],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 25],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 30],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 25],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 25],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 25],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 10]
|
||||
]
|
||||
],
|
||||
"BonusTypeTable2": [
|
||||
[
|
||||
[0, 100],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 100],
|
||||
[1, 0],
|
||||
[2, 0],
|
||||
[3, 0],
|
||||
[4, 0],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 65],
|
||||
[1, 5],
|
||||
[2, 10],
|
||||
[3, 10],
|
||||
[4, 10],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 45],
|
||||
[1, 10],
|
||||
[2, 10],
|
||||
[3, 15],
|
||||
[4, 20],
|
||||
[5, 0]
|
||||
],
|
||||
[
|
||||
[0, 30],
|
||||
[1, 25],
|
||||
[2, 20],
|
||||
[3, 10],
|
||||
[4, 10],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 15],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 25],
|
||||
[4, 20],
|
||||
[5, 5]
|
||||
],
|
||||
[
|
||||
[0, 15],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 25],
|
||||
[4, 15],
|
||||
[5, 10]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 15],
|
||||
[2, 20],
|
||||
[3, 20],
|
||||
[4, 20],
|
||||
[5, 15]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 20],
|
||||
[2, 15],
|
||||
[3, 15],
|
||||
[4, 20],
|
||||
[5, 20]
|
||||
]
|
||||
],
|
||||
"DefaultDringRangeTable": [
|
||||
[0, 2],
|
||||
[0, 3],
|
||||
[0, 4],
|
||||
[0, 6],
|
||||
[0, 8],
|
||||
[0, 10]
|
||||
],
|
||||
"FavoredDringRangeTable": [
|
||||
[0, 1],
|
||||
[0, 3],
|
||||
[1, 5],
|
||||
[2, 8],
|
||||
[3, 11],
|
||||
[3, 16]
|
||||
],
|
||||
"SpecialModeTable": [
|
||||
[
|
||||
[0, 85],
|
||||
[1, 15],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 70],
|
||||
[1, 30],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 50],
|
||||
[1, 50],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 80],
|
||||
[2, 0]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 60],
|
||||
[2, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[1, 40],
|
||||
[2, 40]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 30],
|
||||
[2, 60]
|
||||
],
|
||||
[
|
||||
[0, 10],
|
||||
[1, 10],
|
||||
[2, 80]
|
||||
]
|
||||
],
|
||||
"WeaponTypeWeightTables": [
|
||||
[
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 15],
|
||||
[30, 25],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 20],
|
||||
[30, 20],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 25],
|
||||
[30, 10],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 5],
|
||||
[45, 30]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 5],
|
||||
[25, 25],
|
||||
[30, 20],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 25],
|
||||
[25, 20],
|
||||
[30, 10],
|
||||
[45, 25]
|
||||
],
|
||||
[
|
||||
[0, 20],
|
||||
[5, 20],
|
||||
[25, 20],
|
||||
[30, 20],
|
||||
[45, 20]
|
||||
],
|
||||
[
|
||||
[0, 25],
|
||||
[5, 15],
|
||||
[25, 25],
|
||||
[30, 15],
|
||||
[45, 20]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 0],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 7],
|
||||
[40, 16],
|
||||
[31, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 0],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 12],
|
||||
[40, 7],
|
||||
[31, 16]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 16],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 0],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 7],
|
||||
[40, 7],
|
||||
[31, 12]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 7],
|
||||
[20, 16],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 12],
|
||||
[53, 0],
|
||||
[6, 7],
|
||||
[40, 7],
|
||||
[31, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 3],
|
||||
[15, 7],
|
||||
[20, 3],
|
||||
[26, 10],
|
||||
[35, 17],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 12],
|
||||
[40, 7],
|
||||
[31, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 7],
|
||||
[20, 12],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 16],
|
||||
[6, 7],
|
||||
[40, 7],
|
||||
[31, 0]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 14],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 0],
|
||||
[40, 14],
|
||||
[31, 7]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 10],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 7],
|
||||
[46, 10],
|
||||
[49, 0],
|
||||
[53, 10],
|
||||
[6, 15],
|
||||
[40, 7],
|
||||
[31, 7]
|
||||
],
|
||||
[
|
||||
[1, 9],
|
||||
[10, 8],
|
||||
[15, 8],
|
||||
[20, 8],
|
||||
[26, 9],
|
||||
[35, 8],
|
||||
[46, 9],
|
||||
[49, 8],
|
||||
[53, 8],
|
||||
[6, 8],
|
||||
[40, 9],
|
||||
[31, 8]
|
||||
],
|
||||
[
|
||||
[1, 10],
|
||||
[10, 7],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[26, 10],
|
||||
[35, 12],
|
||||
[46, 10],
|
||||
[49, 7],
|
||||
[53, 7],
|
||||
[6, 7],
|
||||
[40, 0],
|
||||
[31, 7]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 4],
|
||||
[40, 8],
|
||||
[15, 0],
|
||||
[20, 12],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 3],
|
||||
[7, 3],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 3],
|
||||
[41, 8]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 0],
|
||||
[6, 6],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 4],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[32, 16],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 0],
|
||||
[7, 6],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 3],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 8],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 0],
|
||||
[49, 4],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[32, 12],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 8],
|
||||
[7, 3],
|
||||
[27, 5],
|
||||
[36, 0],
|
||||
[50, 3],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 6],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 16],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 0],
|
||||
[2, 5],
|
||||
[11, 3],
|
||||
[7, 3],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 6],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 2],
|
||||
[6, 6],
|
||||
[26, 5],
|
||||
[35, 9],
|
||||
[49, 4],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 3],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 1],
|
||||
[7, 6],
|
||||
[27, 5],
|
||||
[36, 8],
|
||||
[50, 3],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 4],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 12],
|
||||
[32, 0],
|
||||
[46, 10],
|
||||
[53, 16],
|
||||
[2, 5],
|
||||
[11, 3],
|
||||
[7, 3],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 3],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 0],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 4],
|
||||
[40, 7],
|
||||
[15, 14],
|
||||
[20, 7],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 3],
|
||||
[7, 0],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 3],
|
||||
[41, 7]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 5],
|
||||
[6, 8],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 0],
|
||||
[40, 4],
|
||||
[15, 7],
|
||||
[20, 7],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 10],
|
||||
[2, 5],
|
||||
[11, 5],
|
||||
[7, 7],
|
||||
[27, 5],
|
||||
[36, 3],
|
||||
[50, 0],
|
||||
[41, 3]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 4],
|
||||
[49, 4],
|
||||
[40, 4],
|
||||
[15, 9],
|
||||
[20, 8],
|
||||
[32, 8],
|
||||
[46, 9],
|
||||
[53, 8],
|
||||
[2, 4],
|
||||
[11, 4],
|
||||
[7, 4],
|
||||
[27, 4],
|
||||
[36, 4],
|
||||
[50, 4],
|
||||
[41, 4]
|
||||
],
|
||||
[
|
||||
[1, 5],
|
||||
[10, 4],
|
||||
[6, 4],
|
||||
[26, 5],
|
||||
[35, 6],
|
||||
[49, 4],
|
||||
[40, 0],
|
||||
[15, 16],
|
||||
[20, 7],
|
||||
[32, 7],
|
||||
[46, 10],
|
||||
[53, 7],
|
||||
[2, 5],
|
||||
[11, 3],
|
||||
[7, 3],
|
||||
[27, 5],
|
||||
[36, 6],
|
||||
[50, 3],
|
||||
[41, 0]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[2, 9],
|
||||
[12, 8],
|
||||
[7, 7],
|
||||
[16, 0],
|
||||
[21, 9],
|
||||
[27, 10],
|
||||
[41, 18],
|
||||
[37, 8],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 0],
|
||||
[7, 9],
|
||||
[16, 7],
|
||||
[21, 8],
|
||||
[27, 10],
|
||||
[41, 7],
|
||||
[37, 7],
|
||||
[32, 18],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 8],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 18],
|
||||
[7, 7],
|
||||
[16, 7],
|
||||
[21, 7],
|
||||
[27, 10],
|
||||
[41, 8],
|
||||
[37, 0],
|
||||
[32, 9],
|
||||
[47, 10],
|
||||
[54, 8],
|
||||
[50, 7],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 7],
|
||||
[7, 7],
|
||||
[16, 8],
|
||||
[21, 18],
|
||||
[27, 10],
|
||||
[41, 8],
|
||||
[37, 7],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 0],
|
||||
[50, 9],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 10],
|
||||
[12, 2],
|
||||
[7, 9],
|
||||
[16, 7],
|
||||
[21, 2],
|
||||
[27, 11],
|
||||
[41, 8],
|
||||
[37, 18],
|
||||
[32, 7],
|
||||
[47, 11],
|
||||
[54, 7],
|
||||
[50, 8],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 7],
|
||||
[7, 8],
|
||||
[16, 7],
|
||||
[21, 9],
|
||||
[27, 10],
|
||||
[41, 7],
|
||||
[37, 7],
|
||||
[32, 0],
|
||||
[47, 10],
|
||||
[54, 18],
|
||||
[50, 8],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 8],
|
||||
[12, 8],
|
||||
[7, 0],
|
||||
[16, 12],
|
||||
[21, 8],
|
||||
[27, 8],
|
||||
[41, 12],
|
||||
[37, 8],
|
||||
[32, 8],
|
||||
[47, 8],
|
||||
[54, 8],
|
||||
[50, 12],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 8],
|
||||
[7, 18],
|
||||
[16, 7],
|
||||
[21, 8],
|
||||
[27, 10],
|
||||
[41, 8],
|
||||
[37, 7],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 8],
|
||||
[50, 0],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 8],
|
||||
[12, 8],
|
||||
[7, 8],
|
||||
[16, 8],
|
||||
[21, 8],
|
||||
[27, 8],
|
||||
[41, 8],
|
||||
[37, 8],
|
||||
[32, 8],
|
||||
[47, 8],
|
||||
[54, 5],
|
||||
[50, 15],
|
||||
[57, 0]
|
||||
],
|
||||
[
|
||||
[2, 9],
|
||||
[12, 8],
|
||||
[7, 7],
|
||||
[16, 18],
|
||||
[21, 8],
|
||||
[27, 10],
|
||||
[41, 0],
|
||||
[37, 9],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0]
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
[3, 10],
|
||||
[12, 7],
|
||||
[8, 7],
|
||||
[17, 0],
|
||||
[22, 11],
|
||||
[28, 10],
|
||||
[42, 17],
|
||||
[37, 7],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 0],
|
||||
[8, 11],
|
||||
[17, 7],
|
||||
[22, 7],
|
||||
[28, 10],
|
||||
[42, 7],
|
||||
[37, 7],
|
||||
[32, 17],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 17],
|
||||
[8, 7],
|
||||
[17, 7],
|
||||
[22, 7],
|
||||
[28, 10],
|
||||
[42, 7],
|
||||
[37, 0],
|
||||
[32, 11],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 7],
|
||||
[8, 7],
|
||||
[17, 7],
|
||||
[22, 17],
|
||||
[28, 11],
|
||||
[42, 7],
|
||||
[37, 7],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 0],
|
||||
[50, 10],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 3],
|
||||
[8, 11],
|
||||
[17, 7],
|
||||
[22, 3],
|
||||
[28, 11],
|
||||
[42, 7],
|
||||
[37, 17],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 7],
|
||||
[50, 7],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 7],
|
||||
[8, 7],
|
||||
[17, 7],
|
||||
[22, 11],
|
||||
[28, 11],
|
||||
[42, 7],
|
||||
[37, 7],
|
||||
[32, 0],
|
||||
[47, 10],
|
||||
[54, 17],
|
||||
[50, 6],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 7],
|
||||
[12, 6],
|
||||
[8, 0],
|
||||
[17, 12],
|
||||
[22, 7],
|
||||
[28, 7],
|
||||
[42, 12],
|
||||
[37, 6],
|
||||
[32, 7],
|
||||
[47, 10],
|
||||
[54, 13],
|
||||
[50, 13],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 8],
|
||||
[8, 15],
|
||||
[17, 6],
|
||||
[22, 6],
|
||||
[28, 10],
|
||||
[42, 6],
|
||||
[37, 6],
|
||||
[32, 6],
|
||||
[47, 10],
|
||||
[54, 17],
|
||||
[50, 0],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 6],
|
||||
[12, 6],
|
||||
[8, 6],
|
||||
[17, 6],
|
||||
[22, 6],
|
||||
[28, 6],
|
||||
[42, 6],
|
||||
[37, 6],
|
||||
[32, 13],
|
||||
[47, 13],
|
||||
[54, 13],
|
||||
[50, 13],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
],
|
||||
[
|
||||
[3, 10],
|
||||
[12, 6],
|
||||
[8, 6],
|
||||
[17, 13],
|
||||
[22, 6],
|
||||
[28, 9],
|
||||
[42, 0],
|
||||
[37, 9],
|
||||
[32, 14],
|
||||
[47, 17],
|
||||
[54, 4],
|
||||
[50, 6],
|
||||
[57, 0],
|
||||
[58, 0]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
+280
-57
@@ -283,66 +283,289 @@
|
||||
],
|
||||
"QuestF95EResultItems": [
|
||||
[
|
||||
[0x00900000, 0x00900100, 0x00900200, 0x00900300, 0x00900400, 0x00900500,
|
||||
0x00900600, 0x00900700, 0x00900800, 0x00B40000, 0x01014E00, 0x01030700,
|
||||
0x01034100, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00B90000, 0x00340000, 0x00090100, 0x00900200, 0x00900700, 0x002C0000,
|
||||
0x002D0000, 0x01023500, 0x00010600, 0x00010500, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000],
|
||||
[0x00B60000, 0x008A0100, 0x00100100, 0x00100200, 0x00100300, 0x00100400,
|
||||
0x00100500, 0x00100600, 0x00270000, 0x00010700, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000],
|
||||
[0x00B70000, 0x00100100, 0x00100200, 0x00100300, 0x00100400, 0x00100500,
|
||||
0x00100600, 0x00290000, 0x008A0000, 0x008A0200, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000],
|
||||
// Black Paper's Deal Dorphon route
|
||||
[
|
||||
// Normal
|
||||
0x00900000, // DB'S SABER 3062
|
||||
0x00900200, // DB'S SABER 3069 Chris
|
||||
0x00900800, // DB'S SABER 3077
|
||||
0x01014E00, // OFFICER UNIFORM
|
||||
0x01030700, // God/Mind
|
||||
0x01034100, // God/Battle
|
||||
0x03030000, // Sol Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Hard
|
||||
0x00010500, // DB'S SABER (Ephinea)
|
||||
0x00010600, // KALADBOLG (Ephinea)
|
||||
0x002C0000, // ELYSION
|
||||
0x00340000, // RED SWORD
|
||||
0x00900000, // DB'S SABER 3062
|
||||
0x00900100, // DB'S SABER 3067
|
||||
0x00900200, // DB'S SABER 3069 Chris (Ephinea)
|
||||
0x00900300, // DB'S SABER 3064
|
||||
0x00900400, // DB'S SABER 3069 Torato
|
||||
0x00900500, // DB'S SABER 3073
|
||||
0x00900600, // DB'S SABER 3070
|
||||
0x00900700, // DB'S SABER 3075
|
||||
0x00900800, // DB'S SABER 3077 (Ephinea)
|
||||
0x00B90000, // FLAMBERGE
|
||||
0x01023500, // SECURE FEET
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x00010700, // DURANDAL
|
||||
0x00100100, // AGITO 1975 (real)
|
||||
0x00100200, // AGITO 1983
|
||||
0x00100300, // AGITO 2001
|
||||
0x00100400, // AGITO 1991
|
||||
0x00100500, // AGITO 1977
|
||||
0x00100600, // AGITO 1980
|
||||
0x00270000, // ANCIENT SABER
|
||||
0x008A0100, // YASHA
|
||||
0x00B60000, // GUREN
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x00100100, // AGITO 1975 (real)
|
||||
0x00100200, // AGITO 1983
|
||||
0x00100300, // AGITO 2001
|
||||
0x00100400, // AGITO 1991
|
||||
0x00100500, // AGITO 1977
|
||||
0x00100600, // AGITO 1980
|
||||
0x00290000, // YAMIGARASU
|
||||
0x008A0000, // SANGE
|
||||
0x008A0200, // KAMUI
|
||||
0x00B70000, // SHOUREN
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [
|
||||
[0x01028B00, 0x01022800, 0x01013400, 0x01030300, 0x01030B00, 0x03180700,
|
||||
0x00550000, 0x01032900, 0x01032F00, 0x01032C00, 0x01032300, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000],
|
||||
[0x01028C00, 0x01021500, 0x01028A00, 0x01014000, 0x01034400, 0x01034600,
|
||||
0x01034500, 0x01034700, 0x03180700, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00CB0000, 0x003A0000, 0x008C0200, 0x01022B00, 0x00500000, 0x000B0600,
|
||||
0x000A0600, 0x000A0400, 0x00550000, 0x00230000, 0x003B0000, 0x03180700,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00510000, 0x01035200, 0x01032000, 0x01033E00, 0x01022900, 0x03180700,
|
||||
0x000B0400, 0x000A0600, 0x00560000, 0x003B0000, 0x00230000, 0x000A0500,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000],
|
||||
// Black Paper's Deal Rappy route
|
||||
[
|
||||
// Normal
|
||||
0x01013400, // SMOKING PLATE
|
||||
0x01022800, // TRIPOLIC SHIELD
|
||||
0x01028B00, // BUNNY EARS
|
||||
0x01030300, // God/Power
|
||||
0x01030B00, // God/Arm
|
||||
0x01032300, // Resist/Burning
|
||||
0x01032600, // Resist/Blizzard
|
||||
0x01032900, // Resist/Storm (Ephinea)
|
||||
0x01032C00, // Resist/Holy
|
||||
0x01032F00, // Resist/Devil (Ephinea)
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
|
||||
], [
|
||||
// Hard
|
||||
0x01014000, // RED COAT
|
||||
0x01021500, // INVISIBLE GUARD
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01028C00, // CAT EARS
|
||||
0x01034200, // Cure/Poison
|
||||
0x01034300, // Cure/Paralysis
|
||||
0x01034400, // Cure/Slow
|
||||
0x01034500, // Cure/Confuse
|
||||
0x01034600, // Cure/Freeze
|
||||
0x01034700, // Cure/Shock
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x000A0400, // CLUB OF LACONIUM (Ephinea)
|
||||
0x000A0600, // CLUB OF ZUMIURAN
|
||||
0x000B0600, // ALIVE AQHU
|
||||
0x00230000, // STING TIP
|
||||
0x003A0000, // MADAM'S PARASOL
|
||||
0x003B0000, // MADAM'S UMBRELLA
|
||||
0x00500000, // WINDMILL
|
||||
0x00550000, // RABBIT WAND
|
||||
0x00CB0000, // TYRELL'S PARASOL
|
||||
0x01022B00, // KASAMI BRACER
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030E0A00, // Book of HITOGATA (Ephinea)
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x000A0500, // MACE OF ADAMAN
|
||||
0x000A0600, // CLUB OF ZUMIURAN
|
||||
0x000B0400, // BATTLE VERGE
|
||||
0x00230000, // STING TIP (Ephinea)
|
||||
0x00250000, // TECHNICAL CROZIER
|
||||
0x003B0000, // MADAM'S UMBRELLA
|
||||
0x00500000, // WINDMILL
|
||||
0x00510000, // EVIL CURST
|
||||
0x00560000, // PLANTAIN LEAF
|
||||
0x01022900, // STANDSTILL SHIELD
|
||||
0x01032000, // God/Ability
|
||||
0x01033E00, // God/Technique
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x03180700, // Rappy's Beak
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [
|
||||
[0x01013200, 0x002F0100, 0x00B30000, 0x005E0000, 0x000E0200, 0x002E0000,
|
||||
0x00950000, 0x009A0000, 0x002F0000, 0x01031B00, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000],
|
||||
[0x00C00000, 0x00D20000, 0x008D0000, 0x01012E00, 0x008B0000, 0x00090700,
|
||||
0x004E0000, 0x006D0000, 0x00150000, 0x008B0200, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000],
|
||||
[0x00AA0000, 0x01014100, 0x01015100, 0x01022300, 0x003F0000, 0x00410000,
|
||||
0x00050700, 0x00050600, 0x00050500, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000],
|
||||
[0x00AF0000, 0x00430000, 0x01035100, 0x00CD0000, 0x00990000, 0x006C0000,
|
||||
0x00450000, 0x006B0000, 0x00120000, 0x00650000, 0x01022900, 0x00130000,
|
||||
0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000,
|
||||
0x04000000, 0x04000000, 0x04000000],
|
||||
// Black Paper's Deal Zu route
|
||||
[
|
||||
// Normal
|
||||
0x000E0100, // STAG CUTLERY
|
||||
0x000E0200, // TWIN BRAND
|
||||
0x002E0000, // METEOR CUDGEL
|
||||
0x002F0000, // MONKEY KING BAR
|
||||
0x005E0000, // TWIN BLAZE
|
||||
0x00950000, // PARTISAN of LIGHTNING
|
||||
0x009A0000, // DEMOLITION COMET
|
||||
0x00B30000, // VIVIENNE
|
||||
0x01013200, // ELECTRO FRAME
|
||||
0x01031B00, // God/Body
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot (Ephinea)
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Hard
|
||||
0x00090700, // FINAL IMPACT
|
||||
0x00150000, // FLAME VISIT
|
||||
0x004E0000, // PANZER FAUST
|
||||
0x006D0000, // MASER BEAM
|
||||
0x008B0000, // PHOTON LAUNCHER
|
||||
0x008B0200, // RED SCORPIR
|
||||
0x008D0000, // NUG2000-BAZOOKA
|
||||
0x00C00000, // CANNON ROUGE
|
||||
0x00D20000, // ANO BAZOOKA
|
||||
0x01012E00, // FLAME GARMENT
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Very Hard
|
||||
0x00050500, // SLICER OF ASSASSIN
|
||||
0x00050600, // DISKA OF LIBERATOR
|
||||
0x00050700, // DISKA OF BRAVEMAN
|
||||
0x003F0000, // FLIGHT CUTTER
|
||||
0x00400000, // FLIGHT FAN
|
||||
0x00410000, // RED SLICER
|
||||
0x00AA0000, // SLICER OF FANATIC
|
||||
0x01014100, // THIRTEEN
|
||||
0x01015100, // INFANTRY GEAR
|
||||
0x01022300, // REGENE GEAR ADV.
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot (Ephinea)
|
||||
0x04000000, // Meseta
|
||||
], [
|
||||
// Ultimate
|
||||
0x00120000, // SPREAD NEEDLE
|
||||
0x00130000, // HOLY RAY
|
||||
0x00430000, // HANDGUN:MILLA
|
||||
0x00450000, // FROZEN SHOOTER
|
||||
0x00650000, // YASMINKOV 3000R
|
||||
0x006B0000, // YASMINKOV 7000V
|
||||
0x006C0000, // YASMINKOV 9000M
|
||||
0x00990000, // ANGEL HARP
|
||||
0x00AF0000, // OPHELIE SEIZE
|
||||
0x00CD0000, // TANEGASHIMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x03030000, // Sol Atomizer
|
||||
0x03040000, // Moon Atomizer
|
||||
0x03050000, // Star Atomizer
|
||||
0x030F0000, // AddSlot
|
||||
0x04000000, // Meseta
|
||||
],
|
||||
], [], [
|
||||
[0x00BA0000, 0x000D0300, 0x00430100, 0x00070800, 0x00420100, 0x00C90000,
|
||||
0x03100000, 0x01029500, 0x01028F00, 0x01029100],
|
||||
[0x00BB0000, 0x000D0300, 0x00B70000, 0x00420100, 0x00070800, 0x00C90000,
|
||||
0x01013600, 0x01028A00, 0x01029900, 0x01035100, 0x01035B00, 0x01035200,
|
||||
0x03100000, 0x03180A00],
|
||||
[0x00BA0000, 0x00B40000, 0x000D0300, 0x00B60000, 0x00B30000, 0x00070800,
|
||||
0x00430100, 0x00C90000, 0x01013600, 0x01028A00, 0x01029900, 0x01028500,
|
||||
0x01034800, 0x01035100, 0x01035B00, 0x01035200, 0x03100000],
|
||||
[0x00BA0000, 0x00B40000, 0x000D0300, 0x00B60000, 0x00B30000, 0x00070800,
|
||||
0x00430100, 0x00C90000, 0x01013600, 0x01028A00, 0x01029900, 0x01028500,
|
||||
0x01034800, 0x01035100, 0x01035B00, 0x01035200],
|
||||
// Black Paper's Dangerous Deal 2
|
||||
[
|
||||
// Normal
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00420100, // MASTER RAVEN (Ephinea)
|
||||
0x00430100, // LAST SWAN
|
||||
0x00BA0000, // YUNCHANG
|
||||
0x00C90000, // DECALOG
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Hard
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00420100, // MASTER RAVEN
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B70000, // SHOUREN
|
||||
0x00BA0000, // YUNCHANG
|
||||
0x00BB0000, // SNAKE SPIRE
|
||||
0x00BC0000, // FLAPJACK FLAPPER
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Very Hard
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00430100, // LAST SWAN
|
||||
0x00B30000, // VIVIENNE
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B60000, // GUREN
|
||||
0x00BA0000, // YUNCHANG (Ephinea)
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028500, // GRATIA
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
], [
|
||||
// Ultimate
|
||||
0x00070800, // RIANOV 303SNR
|
||||
0x000D0300, // PHOENIX CLAW
|
||||
0x00430100, // LAST SWAN
|
||||
0x00B30000, // VIVIENNE
|
||||
0x00B40000, // KUSANAGI
|
||||
0x00B60000, // GUREN
|
||||
0x00B70000, // SHOUREN
|
||||
0x00C90000, // DECALOG
|
||||
0x01013600, // BLACK HOUND CUIRASS
|
||||
0x01028500, // GRATIA
|
||||
0x01028A00, // YATA MIRROR
|
||||
0x01029900, // STINK SHIELD
|
||||
0x01034800, // YASAKANI MAGATAMA
|
||||
0x01035100, // SMARTLINK
|
||||
0x01035200, // DIVINE PROTECTION
|
||||
0x01035B00, // Centurion/Ability
|
||||
0x03100000, // Photon Drop
|
||||
],
|
||||
],
|
||||
],
|
||||
"QuestF95FResultItems": [
|
||||
|
||||
@@ -9,6 +9,42 @@ fi
|
||||
|
||||
DIR=tests/game-tables
|
||||
PMT_PREFIX=$DIR/item-parameter-table
|
||||
MMT_PREFIX=$DIR/mag-metadata-table
|
||||
|
||||
echo "... (armor-random-shop-set)"
|
||||
$EXECUTABLE decode-armor-shop-random-set --big-endian $DIR/armor-shop-random-set.expected.bin $DIR/armor-shop-random-set.json
|
||||
$EXECUTABLE encode-armor-shop-random-set --big-endian $DIR/armor-shop-random-set.json $DIR/armor-shop-random-set.encoded.bin
|
||||
bindiff $DIR/armor-shop-random-set.expected.bin $DIR/armor-shop-random-set.encoded.bin
|
||||
|
||||
echo "... (tool-random-shop-set)"
|
||||
$EXECUTABLE decode-tool-shop-random-set --big-endian $DIR/tool-shop-random-set.expected.bin $DIR/tool-shop-random-set.json
|
||||
$EXECUTABLE encode-tool-shop-random-set --big-endian $DIR/tool-shop-random-set.json $DIR/tool-shop-random-set.encoded.bin
|
||||
bindiff $DIR/tool-shop-random-set.expected.bin $DIR/tool-shop-random-set.encoded.bin
|
||||
|
||||
echo "... (weapon-random-shop-set-normal)"
|
||||
$EXECUTABLE decode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-normal.expected.bin $DIR/weapon-shop-random-set-normal.json
|
||||
$EXECUTABLE encode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-normal.json $DIR/weapon-shop-random-set-normal.encoded.bin
|
||||
bindiff $DIR/weapon-shop-random-set-normal.expected.bin $DIR/weapon-shop-random-set-normal.encoded.bin
|
||||
|
||||
echo "... (weapon-random-shop-set-hard)"
|
||||
$EXECUTABLE decode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-hard.expected.bin $DIR/weapon-shop-random-set-hard.json
|
||||
$EXECUTABLE encode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-hard.json $DIR/weapon-shop-random-set-hard.encoded.bin
|
||||
bindiff $DIR/weapon-shop-random-set-hard.expected.bin $DIR/weapon-shop-random-set-hard.encoded.bin
|
||||
|
||||
echo "... (weapon-random-shop-set-very-hard)"
|
||||
$EXECUTABLE decode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-very-hard.expected.bin $DIR/weapon-shop-random-set-very-hard.json
|
||||
$EXECUTABLE encode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-very-hard.json $DIR/weapon-shop-random-set-very-hard.encoded.bin
|
||||
bindiff $DIR/weapon-shop-random-set-very-hard.expected.bin $DIR/weapon-shop-random-set-very-hard.encoded.bin
|
||||
|
||||
echo "... (weapon-random-shop-set-ultimate)"
|
||||
$EXECUTABLE decode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-ultimate.expected.bin $DIR/weapon-shop-random-set-ultimate.json
|
||||
$EXECUTABLE encode-weapon-shop-random-set --big-endian $DIR/weapon-shop-random-set-ultimate.json $DIR/weapon-shop-random-set-ultimate.encoded.bin
|
||||
bindiff $DIR/weapon-shop-random-set-ultimate.expected.bin $DIR/weapon-shop-random-set-ultimate.encoded.bin
|
||||
|
||||
echo "... (tekker-adjustment-set)"
|
||||
$EXECUTABLE decode-tekker-adjustment-set --big-endian $DIR/tekker-adjustment-set.expected.bin $DIR/tekker-adjustment-set.json
|
||||
$EXECUTABLE encode-tekker-adjustment-set --big-endian $DIR/tekker-adjustment-set.json $DIR/tekker-adjustment-set.encoded.bin
|
||||
bindiff $DIR/tekker-adjustment-set.expected.bin $DIR/tekker-adjustment-set.encoded.bin
|
||||
|
||||
echo "... (battle-params)"
|
||||
$EXECUTABLE decode-battle-params tests/game-tables/battle-params-ep1-on.dat tests/game-tables/battle-params-ep2-on.dat tests/game-tables/battle-params-ep4-on.dat tests/game-tables/battle-params-ep1-off.dat tests/game-tables/battle-params-ep2-off.dat tests/game-tables/battle-params-ep4-off.dat tests/game-tables/battle-params.json
|
||||
@@ -85,5 +121,60 @@ $EXECUTABLE decode-item-parameter-table --bb-v4 $PMT_PREFIX-bb-v4.expected.bin -
|
||||
$EXECUTABLE encode-item-parameter-table --bb-v4 $PMT_PREFIX-bb-v4.json $PMT_PREFIX-bb-v4.encoded.bin --decompressed
|
||||
bindiff $PMT_PREFIX-bb-v4.expected.bin $PMT_PREFIX-bb-v4.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) DC 11/2000"
|
||||
$EXECUTABLE decode-mag-metadata-table --dc-11-2000 $MMT_PREFIX-dc-11-2000.expected.bin --decompressed $MMT_PREFIX-dc-11-2000.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --dc-11-2000 $MMT_PREFIX-dc-11-2000.json $MMT_PREFIX-dc-11-2000.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-dc-11-2000.expected.bin $MMT_PREFIX-dc-11-2000.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) DC V1"
|
||||
$EXECUTABLE decode-mag-metadata-table --dc-v1 $MMT_PREFIX-dc-v1.expected.bin --decompressed $MMT_PREFIX-dc-v1.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --dc-v1 $MMT_PREFIX-dc-v1.json $MMT_PREFIX-dc-v1.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-dc-v1.expected.bin $MMT_PREFIX-dc-v1.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) DC V2"
|
||||
$EXECUTABLE decode-mag-metadata-table --dc-v2 $MMT_PREFIX-dc-v2.expected.bin --decompressed $MMT_PREFIX-dc-v2.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --dc-v2 $MMT_PREFIX-dc-v2.json $MMT_PREFIX-dc-v2.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-dc-v2.expected.bin $MMT_PREFIX-dc-v2.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) PC NTE"
|
||||
$EXECUTABLE decode-mag-metadata-table --pc-nte $MMT_PREFIX-pc-nte.expected.bin --decompressed $MMT_PREFIX-pc-nte.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --pc-nte $MMT_PREFIX-pc-nte.json $MMT_PREFIX-pc-nte.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-pc-nte.expected.bin $MMT_PREFIX-pc-nte.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) PC V2"
|
||||
$EXECUTABLE decode-mag-metadata-table --pc-v2 $MMT_PREFIX-pc-v2.expected.bin --decompressed $MMT_PREFIX-pc-v2.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --pc-v2 $MMT_PREFIX-pc-v2.json $MMT_PREFIX-pc-v2.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-pc-v2.expected.bin $MMT_PREFIX-pc-v2.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) GC NTE"
|
||||
$EXECUTABLE decode-mag-metadata-table --gc-nte $MMT_PREFIX-gc-nte.expected.bin --decompressed $MMT_PREFIX-gc-nte.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --gc-nte $MMT_PREFIX-gc-nte.json $MMT_PREFIX-gc-nte.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-gc-nte.expected.bin $MMT_PREFIX-gc-nte.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) GC V3"
|
||||
$EXECUTABLE decode-mag-metadata-table --gc-v3 $MMT_PREFIX-gc-v3.expected.bin --decompressed $MMT_PREFIX-gc-v3.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --gc-v3 $MMT_PREFIX-gc-v3.json $MMT_PREFIX-gc-v3.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-gc-v3.expected.bin $MMT_PREFIX-gc-v3.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) GC Ep3 NTE"
|
||||
$EXECUTABLE decode-mag-metadata-table --gc-ep3-nte $MMT_PREFIX-gc-ep3-nte.expected.bin --decompressed $MMT_PREFIX-gc-ep3-nte.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --gc-ep3-nte $MMT_PREFIX-gc-ep3-nte.json $MMT_PREFIX-gc-ep3-nte.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-gc-ep3-nte.expected.bin $MMT_PREFIX-gc-ep3-nte.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) GC Ep3"
|
||||
$EXECUTABLE decode-mag-metadata-table --gc-ep3 $MMT_PREFIX-gc-ep3.expected.bin --decompressed $MMT_PREFIX-gc-ep3.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --gc-ep3 $MMT_PREFIX-gc-ep3.json $MMT_PREFIX-gc-ep3.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-gc-ep3.expected.bin $MMT_PREFIX-gc-ep3.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) XB"
|
||||
$EXECUTABLE decode-mag-metadata-table --xb-v3 $MMT_PREFIX-xb-v3.expected.bin --decompressed $MMT_PREFIX-xb-v3.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --xb-v3 $MMT_PREFIX-xb-v3.json $MMT_PREFIX-xb-v3.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-xb-v3.expected.bin $MMT_PREFIX-xb-v3.encoded.bin
|
||||
|
||||
echo "... (mag-metadata-table) BB"
|
||||
$EXECUTABLE decode-mag-metadata-table --bb-v4 $MMT_PREFIX-bb-v4.expected.bin --decompressed $MMT_PREFIX-bb-v4.json --hex
|
||||
$EXECUTABLE encode-mag-metadata-table --bb-v4 $MMT_PREFIX-bb-v4.json $MMT_PREFIX-bb-v4.encoded.bin --decompressed
|
||||
bindiff $MMT_PREFIX-bb-v4.expected.bin $MMT_PREFIX-bb-v4.encoded.bin
|
||||
|
||||
echo "... clean up"
|
||||
rm -f $DIR/*.encoded.bin $DIR/*.json $DIR/battle-params.json.enc* $DIR/battle-params-encoded*
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user