convert shop random sets to JSON
This commit is contained in:
@@ -125,6 +125,7 @@ set(SOURCES
|
||||
src/ServerShell.cc
|
||||
src/ServerState.cc
|
||||
src/ShellCommands.cc
|
||||
src/ShopRandomSets.cc
|
||||
src/SignalWatcher.cc
|
||||
src/StaticGameData.cc
|
||||
src/TeamIndex.cc
|
||||
|
||||
@@ -950,94 +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);
|
||||
}
|
||||
|
||||
@@ -284,114 +284,3 @@ class JSONCommonItemSet : public CommonItemSet {
|
||||
public:
|
||||
explicit JSONCommonItemSet(const phosg::JSON& json);
|
||||
};
|
||||
|
||||
class RELFileSet {
|
||||
public:
|
||||
template <typename ValueT, typename WeightT = ValueT>
|
||||
struct WeightTableEntry {
|
||||
ValueT value;
|
||||
WeightT weight;
|
||||
phosg::JSON json() const {
|
||||
return phosg::JSON::dict({{"Weight", this->weight}, {"Value", this->value}});
|
||||
}
|
||||
static WeightTableEntry<ValueT, WeightT> from_json(const phosg::JSON& json) {
|
||||
return WeightTableEntry<ValueT, WeightT>{json.get_int("Weight"), json.get_int("Value")};
|
||||
}
|
||||
} __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;
|
||||
};
|
||||
|
||||
+60
-202
@@ -15,6 +15,23 @@ struct ProbabilityTable {
|
||||
|
||||
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");
|
||||
@@ -52,9 +69,9 @@ struct ProbabilityTable {
|
||||
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,
|
||||
@@ -1080,13 +1097,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;) {
|
||||
@@ -1124,13 +1135,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;) {
|
||||
@@ -1167,13 +1172,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;) {
|
||||
@@ -1211,10 +1210,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) {
|
||||
@@ -1231,17 +1226,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1251,15 +1244,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;
|
||||
@@ -1273,8 +1259,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++;
|
||||
@@ -1294,28 +1280,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));
|
||||
@@ -1326,22 +1300,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);
|
||||
@@ -1394,119 +1368,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);
|
||||
@@ -1542,16 +1422,15 @@ void ItemCreator::generate_weapon_shop_item_grind(ItemData& item, size_t player_
|
||||
|
||||
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) {
|
||||
@@ -1572,13 +1451,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.
|
||||
@@ -1597,9 +1471,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) {
|
||||
@@ -1622,14 +1493,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.
|
||||
@@ -1637,8 +1502,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1664,14 +1529,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 {
|
||||
@@ -1681,8 +1539,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -7,6 +7,7 @@
|
||||
#include "PSOEncryption.hh"
|
||||
#include "PlayerSubordinates.hh"
|
||||
#include "RareItemSet.hh"
|
||||
#include "ShopRandomSets.hh"
|
||||
#include "StaticGameData.hh"
|
||||
#include "TekkerAdjustmentSet.hh"
|
||||
|
||||
@@ -20,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,
|
||||
@@ -81,9 +82,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;
|
||||
|
||||
+97
-4
@@ -2433,7 +2433,7 @@ Action a_encode_mag_metadata_table(
|
||||
|
||||
Action a_decode_tekker_adjustment_set(
|
||||
"decode-tekker-adjustment-set", "\
|
||||
decode-tekker-adjustment-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
|
||||
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) {
|
||||
@@ -2446,7 +2446,7 @@ Action a_decode_tekker_adjustment_set(
|
||||
|
||||
Action a_encode_tekker_adjustment_set(
|
||||
"encode-tekker-adjustment-set", "\
|
||||
encode-tekker-adjustment-set [INPUT-FILENAME [OUTPUT-FILENAME]] [OPTIONS...]\n\
|
||||
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) {
|
||||
@@ -2454,6 +2454,78 @@ Action a_encode_tekker_adjustment_set(
|
||||
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) {
|
||||
@@ -2704,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();
|
||||
@@ -2790,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));
|
||||
@@ -2804,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\
|
||||
|
||||
+11
-11
@@ -2108,24 +2108,24 @@ 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 set");
|
||||
|
||||
+5
-4
@@ -27,6 +27,7 @@
|
||||
#include "MagMetadataTable.hh"
|
||||
#include "Menu.hh"
|
||||
#include "Quest.hh"
|
||||
#include "ShopRandomSets.hh"
|
||||
#include "TeamIndex.hh"
|
||||
#include "TekkerAdjustmentSet.hh"
|
||||
#include "WordSelectTable.hh"
|
||||
@@ -213,9 +214,9 @@ 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;
|
||||
@@ -364,7 +365,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 {
|
||||
|
||||
@@ -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]
|
||||
};
|
||||
@@ -355,3 +355,36 @@ phosg::JSON TekkerAdjustmentSet::json() const {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@ struct TekkerAdjustmentSet {
|
||||
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;
|
||||
size_t total = 0;
|
||||
};
|
||||
|
||||
std::array<Table, 10> favored_special_delta_table;
|
||||
|
||||
@@ -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,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]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -11,6 +11,41 @@ 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
|
||||
$EXECUTABLE encode-battle-params tests/game-tables/battle-params.json tests/game-tables/battle-params-encoded
|
||||
@@ -21,11 +56,6 @@ bindiff tests/game-tables/battle-params-ep1-off.dat tests/game-tables/battle-par
|
||||
bindiff tests/game-tables/battle-params-ep2-off.dat tests/game-tables/battle-params-encoded_lab.dat
|
||||
bindiff tests/game-tables/battle-params-ep4-off.dat tests/game-tables/battle-params-encoded_ep4.dat
|
||||
|
||||
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 "... (level-table) BB"
|
||||
$EXECUTABLE decode-level-table --bb-v4 $DIR/level-table-bb-v4.expected.bin --decompressed $DIR/level-table-bb-v4.json --hex
|
||||
$EXECUTABLE encode-level-table-v4 $DIR/level-table-bb-v4.json $DIR/level-table-bb-v4.encoded.bin --decompressed
|
||||
|
||||
Reference in New Issue
Block a user