implement character overlays for challenge mode
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
- Implement server-side drops on non-BB game versions
|
- Implement server-side drops on non-BB game versions
|
||||||
- Find a way to silence audio in RunDOL.s
|
- Find a way to silence audio in RunDOL.s
|
||||||
- Encapsulate BB server-side random state and make replays deterministic
|
- Encapsulate BB server-side random state and make replays deterministic
|
||||||
- Implement character and inventory replacement for battle and challenge modes
|
|
||||||
- Implement choice search
|
- Implement choice search
|
||||||
- Write a simple status API
|
- Write a simple status API
|
||||||
- Implement per-game logging
|
- Implement per-game logging
|
||||||
@@ -15,6 +14,8 @@
|
|||||||
- Implement decrypt/encrypt actions for VMS files
|
- Implement decrypt/encrypt actions for VMS files
|
||||||
- Fix Word Select mapping across versions
|
- Fix Word Select mapping across versions
|
||||||
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
|
- Make UI strings localizable (e.g. entries in menus, welcome message, etc.)
|
||||||
|
- Figure out what causes the corruption message on PC proxy sessions and fix it
|
||||||
|
- Enable item tracking in battle/challenge games (everything should already be set up for it to work)
|
||||||
|
|
||||||
## Episode 3
|
## Episode 3
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,63 @@ void ClientGameData::create_battle_overlay(shared_ptr<const BattleRules> rules,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientGameData::create_challenge_overlay(size_t template_index, shared_ptr<const LevelTable> level_table) {
|
||||||
|
const auto& tpl = get_challenge_template_definition(this->player(true, false)->disp.visual.class_flags, template_index);
|
||||||
|
|
||||||
|
this->overlay_player_data.reset(new SavedPlayerDataBB(*this->player(true, false)));
|
||||||
|
auto overlay = this->overlay_player_data;
|
||||||
|
|
||||||
|
for (size_t z = 0; z < overlay->inventory.items.size(); z++) {
|
||||||
|
auto& i = overlay->inventory.items[z];
|
||||||
|
i.present = 0;
|
||||||
|
i.extension_data1 = 0;
|
||||||
|
i.extension_data2 = 0;
|
||||||
|
i.flags = 0;
|
||||||
|
i.data = ItemData();
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay->inventory.items[13].extension_data2 = 1;
|
||||||
|
|
||||||
|
overlay->disp.stats.char_stats = level_table->base_stats_for_class(overlay->disp.visual.char_class);
|
||||||
|
for (overlay->disp.stats.level = 0;
|
||||||
|
overlay->disp.stats.level < tpl.level;
|
||||||
|
overlay->disp.stats.level++) {
|
||||||
|
const auto& level_stats = level_table->stats_delta_for_level(
|
||||||
|
overlay->disp.visual.char_class, overlay->disp.stats.level + 1);
|
||||||
|
// The original code clamps the resulting stat values to [0, max_stat]; we
|
||||||
|
// don't have max_stat handy so we just allow them to be unbounded
|
||||||
|
overlay->disp.stats.char_stats.atp += level_stats.atp;
|
||||||
|
overlay->disp.stats.char_stats.mst += level_stats.mst;
|
||||||
|
overlay->disp.stats.char_stats.evp += level_stats.evp;
|
||||||
|
overlay->disp.stats.char_stats.hp += level_stats.hp;
|
||||||
|
overlay->disp.stats.char_stats.dfp += level_stats.dfp;
|
||||||
|
overlay->disp.stats.char_stats.ata += level_stats.ata;
|
||||||
|
// Note: It is not a bug that lck is ignored here; the original code
|
||||||
|
// ignores it too.
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay->disp.stats.unknown_a1 = 40;
|
||||||
|
overlay->disp.stats.unknown_a3 = 10.0;
|
||||||
|
overlay->disp.stats.experience = level_table->stats_delta_for_level(overlay->disp.visual.char_class, overlay->disp.stats.level).experience;
|
||||||
|
overlay->disp.stats.meseta = 0;
|
||||||
|
overlay->clear_all_material_usage();
|
||||||
|
for (size_t z = 0; z < 0x13; z++) {
|
||||||
|
overlay->set_technique_level(z, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t z = 0; z < tpl.items.size(); z++) {
|
||||||
|
auto& inv_item = overlay->inventory.items[z];
|
||||||
|
inv_item.present = tpl.items[z].present;
|
||||||
|
inv_item.flags = tpl.items[z].flags;
|
||||||
|
inv_item.data = tpl.items[z].data;
|
||||||
|
}
|
||||||
|
overlay->inventory.num_items = tpl.items.size();
|
||||||
|
|
||||||
|
for (const auto& tech_level : tpl.tech_levels) {
|
||||||
|
overlay->set_technique_level(tech_level.tech_num, tech_level.level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<SavedAccountDataBB> ClientGameData::account(bool allow_load) {
|
shared_ptr<SavedAccountDataBB> ClientGameData::account(bool allow_load) {
|
||||||
if (!this->account_data.get() && allow_load) {
|
if (!this->account_data.get() && allow_load) {
|
||||||
if (this->bb_username.empty()) {
|
if (this->bb_username.empty()) {
|
||||||
@@ -446,6 +503,14 @@ void SavedPlayerDataBB::set_material_usage(MaterialType which, uint8_t usage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SavedPlayerDataBB::clear_all_material_usage() {
|
||||||
|
this->inventory.hp_materials_used = 0;
|
||||||
|
this->inventory.tp_materials_used = 0;
|
||||||
|
for (size_t z = 0; z < 5; z++) {
|
||||||
|
this->inventory.items[z + 8].extension_data2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SavedPlayerDataBB::print_inventory(FILE* stream) const {
|
void SavedPlayerDataBB::print_inventory(FILE* stream) const {
|
||||||
fprintf(stream, "[PlayerInventory] Meseta: %" PRIu32 "\n", this->disp.stats.meseta.load());
|
fprintf(stream, "[PlayerInventory] Meseta: %" PRIu32 "\n", this->disp.stats.meseta.load());
|
||||||
fprintf(stream, "[PlayerInventory] %hhu items\n", this->inventory.num_items);
|
fprintf(stream, "[PlayerInventory] %hhu items\n", this->inventory.num_items);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ struct SavedPlayerDataBB { // .nsc file format
|
|||||||
|
|
||||||
uint8_t get_material_usage(MaterialType which) const;
|
uint8_t get_material_usage(MaterialType which) const;
|
||||||
void set_material_usage(MaterialType which, uint8_t usage);
|
void set_material_usage(MaterialType which, uint8_t usage);
|
||||||
|
void clear_all_material_usage();
|
||||||
|
|
||||||
void print_inventory(FILE* stream) const;
|
void print_inventory(FILE* stream) const;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
@@ -124,9 +125,13 @@ public:
|
|||||||
~ClientGameData();
|
~ClientGameData();
|
||||||
|
|
||||||
void create_battle_overlay(std::shared_ptr<const BattleRules> rules, std::shared_ptr<const LevelTable> level_table);
|
void create_battle_overlay(std::shared_ptr<const BattleRules> rules, std::shared_ptr<const LevelTable> level_table);
|
||||||
|
void create_challenge_overlay(size_t template_index, std::shared_ptr<const LevelTable> level_table);
|
||||||
inline void delete_overlay() {
|
inline void delete_overlay() {
|
||||||
this->overlay_player_data.reset();
|
this->overlay_player_data.reset();
|
||||||
}
|
}
|
||||||
|
inline bool has_overlay() const {
|
||||||
|
return this->overlay_player_data.get() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<SavedAccountDataBB> account(bool allow_load = true);
|
std::shared_ptr<SavedAccountDataBB> account(bool allow_load = true);
|
||||||
std::shared_ptr<SavedPlayerDataBB> player(bool allow_load = true, bool allow_overlay = true);
|
std::shared_ptr<SavedPlayerDataBB> player(bool allow_load = true, bool allow_overlay = true);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void PlayerDispDataBB::apply_dressing_room(const PlayerDispDataBBPreview& pre) {
|
|||||||
this->visual.char_class = pre.visual.char_class;
|
this->visual.char_class = pre.visual.char_class;
|
||||||
this->visual.v2_flags = pre.visual.v2_flags;
|
this->visual.v2_flags = pre.visual.v2_flags;
|
||||||
this->visual.version = pre.visual.version;
|
this->visual.version = pre.visual.version;
|
||||||
this->visual.v1_flags = pre.visual.v1_flags;
|
this->visual.class_flags = pre.visual.class_flags;
|
||||||
this->visual.costume = pre.visual.costume;
|
this->visual.costume = pre.visual.costume;
|
||||||
this->visual.skin = pre.visual.skin;
|
this->visual.skin = pre.visual.skin;
|
||||||
this->visual.face = pre.visual.face;
|
this->visual.face = pre.visual.face;
|
||||||
@@ -606,3 +606,98 @@ BattleRules::MesetaDropMode enum_for_name<BattleRules::MesetaDropMode>(const cha
|
|||||||
throw invalid_argument("invalid BattleRules::MesetaDropMode name");
|
throw invalid_argument("invalid BattleRules::MesetaDropMode name");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ChallengeTemplateDefinition& get_challenge_template_definition(uint32_t class_flags, size_t index) {
|
||||||
|
static auto make_template_item = +[](bool equipped, uint64_t first_data, uint64_t second_data = 0) -> PlayerInventoryItem {
|
||||||
|
PlayerInventoryItem ret = {
|
||||||
|
.present = 1,
|
||||||
|
.extension_data1 = 0,
|
||||||
|
.extension_data2 = 0,
|
||||||
|
.flags = (equipped ? 8 : 0),
|
||||||
|
.data = ItemData()};
|
||||||
|
ret.data.data1[0] = first_data >> 56;
|
||||||
|
ret.data.data1[1] = first_data >> 48;
|
||||||
|
ret.data.data1[2] = first_data >> 40;
|
||||||
|
ret.data.data1[3] = first_data >> 32;
|
||||||
|
ret.data.data1[4] = first_data >> 24;
|
||||||
|
ret.data.data1[5] = first_data >> 16;
|
||||||
|
ret.data.data1[6] = first_data >> 8;
|
||||||
|
ret.data.data1[7] = first_data >> 0;
|
||||||
|
ret.data.data1[8] = second_data >> 56;
|
||||||
|
ret.data.data1[9] = second_data >> 48;
|
||||||
|
ret.data.data1[10] = second_data >> 40;
|
||||||
|
ret.data.data1[11] = second_data >> 32;
|
||||||
|
ret.data.data2[0] = second_data >> 24;
|
||||||
|
ret.data.data2[1] = second_data >> 16;
|
||||||
|
ret.data.data2[2] = second_data >> 8;
|
||||||
|
ret.data.data2[3] = second_data >> 0;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static const vector<ChallengeTemplateDefinition> hunter_templates({
|
||||||
|
{0, {make_template_item(true, 0x0001000000000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0300000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{4, {make_template_item(true, 0x0001000500000000, 0x0000000000000000), make_template_item(true, 0x0101010000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x02010D002003F401, 0x0000000028000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{6, {make_template_item(true, 0x0002000000000000, 0x0000000000000000), make_template_item(true, 0x0101020000000000, 0x0000000000000000), make_template_item(true, 0x0102010000000000, 0x0000000000000000), make_template_item(true, 0x0201100020032003, 0x0000000028000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{9, {make_template_item(true, 0x0002000500000000, 0x0000000000000000), make_template_item(true, 0x0101030000000000, 0x0000000000000000), make_template_item(true, 0x0102020000000000, 0x0000000000000000), make_template_item(true, 0x02011300E8032003, 0x0000640028000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0301000000020000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{12, {make_template_item(true, 0x0001010000000000, 0x0000000000000000), make_template_item(true, 0x0101030000000000, 0x0000000000000000), make_template_item(true, 0x0102030000000000, 0x0000000000000000), make_template_item(true, 0x020116004C04E803, 0x0000640028000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x0301000000020000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{14, {make_template_item(true, 0x0001010500000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102030000000000, 0x0000000000000000), make_template_item(true, 0x020118004C04E803, 0x6400C80028000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x0301000000020000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{17, {make_template_item(true, 0x0002010000000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x02012700DC056C07, 0xC8002C0128000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301000000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{19, {make_template_item(true, 0x0002010500000000, 0x0000000000000000), make_template_item(true, 0x0101050000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x02012200DC057805, 0xC8002C0128000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301000000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{22, {make_template_item(true, 0x0001020000000000, 0x0000000000000000), make_template_item(true, 0x0101050000000000, 0x0000000000000000), make_template_item(true, 0x0102050000000000, 0x0000000000000000), make_template_item(true, 0x020E260008071405, 0x2C01900128000012), make_template_item(false, 0x03000000000A0000, 0x0000000000000000), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301000000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{24, {make_template_item(true, 0x0001030000000000, 0x0000000000000000), make_template_item(true, 0x0101070000000000, 0x0000000000000000), make_template_item(true, 0x0102070000000000, 0x0000000000000000), make_template_item(true, 0x02054600D007B80B, 0xE803E80328000012), make_template_item(false, 0x03000100000A0000, 0x0000000000000000), make_template_item(false, 0x0301010000050000, 0x0000000000000000), make_template_item(false, 0x0306010000050000, 0x0000000000000000), make_template_item(false, 0x0306000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{50, {make_template_item(true, 0x0001040000000000, 0x0000000000000000), make_template_item(true, 0x01010E0000000000, 0x0000000000000000), make_template_item(true, 0x01020E0000000000, 0x0000000000000000), make_template_item(true, 0x02058C00A00F7017, 0xD007D00728000012), make_template_item(false, 0x03000200000A0000, 0x0000000000000000), make_template_item(false, 0x0301020000050000, 0x0000000000000000), make_template_item(false, 0x0306010000050000, 0x0000000000000000), make_template_item(false, 0x0306000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{99, {make_template_item(true, 0x0001050000000000, 0x0000000000000000), make_template_item(true, 0x0101160000000000, 0x0000000000000000), make_template_item(true, 0x0102120000000000, 0x0000000000000000), make_template_item(true, 0x0205B40070177017, 0xB80BB80B28000012), make_template_item(false, 0x03000200000A0000, 0x0000000000000000), make_template_item(false, 0x0301020000050000, 0x0000000000000000), make_template_item(false, 0x0306010000050000, 0x0000000000000000), make_template_item(false, 0x0306000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{0, {make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{24, {make_template_item(true, 0x02054600D007B80B, 0xE803E80328000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{50, {make_template_item(true, 0x02058200A00F8813, 0xD007D00728000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{99, {make_template_item(true, 0x0205BE007017581B, 0xB80BB80B28000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
});
|
||||||
|
static const vector<ChallengeTemplateDefinition> ranger_templates({
|
||||||
|
{0, {make_template_item(true, 0x0006000000000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0300000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{4, {make_template_item(true, 0x0006000500000000, 0x0000000000000000), make_template_item(true, 0x0101010000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x020D0C00F401C800, 0xF401000028000012), make_template_item(false, 0x0300000000050000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{5, {make_template_item(true, 0x0006000500000000, 0x0000000000000000), make_template_item(true, 0x0101010000000000, 0x0000000000000000), make_template_item(true, 0x0102010000000000, 0x0000000000000000), make_template_item(true, 0x020D0E00F401C800, 0xBC02000028000012), make_template_item(false, 0x0300000000050000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{8, {make_template_item(true, 0x0006000500000000, 0x0000000000000000), make_template_item(true, 0x0101020000000000, 0x0000000000000000), make_template_item(true, 0x0102020000000000, 0x0000000000000000), make_template_item(true, 0x020D1000F4012C01, 0x2003000028000012), make_template_item(false, 0x0300000000050000, 0x0000000000000000), make_template_item(false, 0x0301000000010000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{10, {make_template_item(true, 0x0006000500000000, 0x0000000000000000), make_template_item(true, 0x0101020000000000, 0x0000000000000000), make_template_item(true, 0x0102030000000000, 0x0000000000000000), make_template_item(true, 0x020D120058029001, 0x2003000028000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0300010000020000, 0x0000000000000000), make_template_item(false, 0x0301000000010000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{12, {make_template_item(true, 0x0006010000000000, 0x0000000000000000), make_template_item(true, 0x0101030000000000, 0x0000000000000000), make_template_item(true, 0x0102030000000000, 0x0000000000000000), make_template_item(true, 0x020D140058029001, 0x2003C80028000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0300010000020000, 0x0000000000000000), make_template_item(false, 0x0301000000010000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{14, {make_template_item(true, 0x0006010500000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x020D1700BC02F401, 0x8403C80028000012), make_template_item(false, 0x0300000000070000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x0301000000020000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{15, {make_template_item(true, 0x0006010500000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x020D190020035802, 0x8403C80028000012), make_template_item(false, 0x0300000000070000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x0301000000020000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{18, {make_template_item(true, 0x0006020000000000, 0x0000000000000000), make_template_item(true, 0x0101050000000000, 0x0000000000000000), make_template_item(true, 0x0102050000000000, 0x0000000000000000), make_template_item(true, 0x020D1E002003BC02, 0xB0042C0128000012), make_template_item(false, 0x0300000000070000, 0x0000000000000000), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301000000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{24, {make_template_item(true, 0x0006030000000000, 0x0000000000000000), make_template_item(true, 0x0101070000000000, 0x0000000000000000), make_template_item(true, 0x0102070000000000, 0x0000000000000000), make_template_item(true, 0x020C4600D007E803, 0xB80BE80328000012), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301010000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{50, {make_template_item(true, 0x0006040000000000, 0x0000000000000000), make_template_item(true, 0x01010E0000000000, 0x0000000000000000), make_template_item(true, 0x01020E0000000000, 0x0000000000000000), make_template_item(true, 0x020C8C00B80BC409, 0x7017C40928000012), make_template_item(false, 0x0300020000050000, 0x0000000000000000), make_template_item(false, 0x0301020000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{99, {make_template_item(true, 0x0006050000000000, 0x0000000000000000), make_template_item(true, 0x0101160000000000, 0x0000000000000000), make_template_item(true, 0x0102120000000000, 0x0000000000000000), make_template_item(true, 0x0206B400B80BB80B, 0x2823B80B28000012), make_template_item(false, 0x0300020000080000, 0x0000000000000000), make_template_item(false, 0x0301020000050000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0308000000050000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{0, {make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{24, {make_template_item(true, 0x020C4600D007E803, 0xB80BE80328000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{50, {make_template_item(true, 0x020C8C00B80BC409, 0x7017C40928000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{99, {make_template_item(true, 0x0206B400B80BB80B, 0x2823B80B28000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
});
|
||||||
|
static const vector<ChallengeTemplateDefinition> force_templates({
|
||||||
|
{0, {make_template_item(true, 0x000A000000000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0300000000040000, 0x0000000000000000), make_template_item(false, 0x0301000000040000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{4, {make_template_item(true, 0x000A000500000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x02190D0020036400, 0x0000900128000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0301000000060000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 2}, {0x03, 2}, {0x0D, 2}, {0x0A, 2}}},
|
||||||
|
{6, {make_template_item(true, 0x000B000000000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x02190F002003C800, 0x0000F40128000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0301000000060000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 2}, {0x03, 2}, {0x0D, 2}, {0x0A, 2}}},
|
||||||
|
{9, {make_template_item(true, 0x000B000500000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x0219120084032C01, 0x0000580228000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0301000000060000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 2}, {0x03, 2}, {0x0D, 2}, {0x0A, 2}}},
|
||||||
|
{11, {make_template_item(true, 0x000B000500000000, 0x0000000000000000), make_template_item(true, 0x0101000000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x02191400E8032C01, 0x0000BC0228000012), make_template_item(false, 0x0300000000060000, 0x0000000000000000), make_template_item(false, 0x0300010000020000, 0x0000000000000000), make_template_item(false, 0x0301000000080000, 0x0000000000000000), make_template_item(false, 0x0301010000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 4}, {0x06, 4}, {0x03, 4}, {0x0D, 2}, {0x0A, 2}, {0x0B, 2}, {0x0C, 2}}},
|
||||||
|
{12, {make_template_item(true, 0x000B000500000000, 0x0000000000000000), make_template_item(true, 0x0101030000000000, 0x0000000000000000), make_template_item(true, 0x0102000000000000, 0x0000000000000000), make_template_item(true, 0x02191600E8039001, 0x6400BC0228000012), make_template_item(false, 0x0300000000070000, 0x0000000000000000), make_template_item(false, 0x0300010000020000, 0x0000000000000000), make_template_item(false, 0x0301000000070000, 0x0000000000000000), make_template_item(false, 0x0301010000030000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 4}, {0x06, 4}, {0x03, 4}, {0x0D, 2}, {0x0A, 2}, {0x0B, 2}, {0x0C, 2}}},
|
||||||
|
{15, {make_template_item(true, 0x000B000A00000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x02191B00B004F401, 0xC800200328000012), make_template_item(false, 0x0300000000070000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x0301000000080000, 0x0000000000000000), make_template_item(false, 0x0301010000040000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 6}, {0x06, 6}, {0x03, 6}, {0x01, 0}, {0x04, 0}, {0x0D, 3}, {0x0A, 3}, {0x0B, 3}, {0x0C, 3}, {0x0F, 2}}},
|
||||||
|
{16, {make_template_item(true, 0x000B000A00000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x02191D00B0045802, 0xC800840328000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000030000, 0x0000000000000000), make_template_item(false, 0x03010000000A0000, 0x0000000000000000), make_template_item(false, 0x0301010000040000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 6}, {0x06, 6}, {0x03, 6}, {0x01, 0}, {0x04, 0}, {0x0D, 3}, {0x0A, 3}, {0x0B, 3}, {0x0C, 3}, {0x0F, 2}}},
|
||||||
|
{19, {make_template_item(true, 0x000A010000000000, 0x0000000000000000), make_template_item(true, 0x0101040000000000, 0x0000000000000000), make_template_item(true, 0x0102040000000000, 0x0000000000000000), make_template_item(true, 0x02192200DC05BC02, 0xC800E80328000012), make_template_item(false, 0x0300000000080000, 0x0000000000000000), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301010000050000, 0x0000000000000000), make_template_item(false, 0x03010000000A0000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 6}, {0x06, 6}, {0x03, 6}, {0x01, 0}, {0x04, 0}, {0x0D, 3}, {0x0A, 3}, {0x0B, 3}, {0x0C, 3}, {0x0F, 2}}},
|
||||||
|
{24, {make_template_item(true, 0x000A010A00000000, 0x0000000000000000), make_template_item(true, 0x0101060000000000, 0x0000000000000000), make_template_item(true, 0x0102060000000000, 0x0000000000000000), make_template_item(true, 0x021C4600D007E803, 0xE803B80B28000012), make_template_item(false, 0x0300010000050000, 0x0000000000000000), make_template_item(false, 0x0301010000080000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 7}, {0x06, 7}, {0x03, 7}, {0x01, 4}, {0x04, 4}, {0x0D, 7}, {0x0A, 7}, {0x0B, 7}, {0x0C, 7}, {0x0F, 6}}},
|
||||||
|
{50, {make_template_item(true, 0x000A020000000000, 0x0000000000000000), make_template_item(true, 0x01010E0000000000, 0x0000000000000000), make_template_item(true, 0x01020D0000000000, 0x0000000000000000), make_template_item(true, 0x021C8C00B80BD007, 0xD007581B28000012), make_template_item(false, 0x0300020000050000, 0x0000000000000000), make_template_item(false, 0x0301020000080000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 9}, {0x06, 9}, {0x03, 9}, {0x01, 9}, {0x04, 9}, {0x0D, 9}, {0x0A, 9}, {0x0B, 9}, {0x0C, 9}, {0x0F, 9}}},
|
||||||
|
{99, {make_template_item(true, 0x000A040000000000, 0x0000000000000000), make_template_item(true, 0x0101160000000000, 0x0000000000000000), make_template_item(true, 0x0102110000000000, 0x0000000000000000), make_template_item(true, 0x021CB400AC0DD007, 0xC409102728000012), make_template_item(false, 0x0300020000050000, 0x0000000000000000), make_template_item(false, 0x03010200000A0000, 0x0000000000000000), make_template_item(false, 0x0306010000030000, 0x0000000000000000), make_template_item(false, 0x0306000000030000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {{0x00, 14}, {0x06, 14}, {0x03, 14}, {0x01, 14}, {0x04, 14}, {0x0D, 14}, {0x0A, 14}, {0x0B, 14}, {0x0C, 14}, {0x0F, 14}}},
|
||||||
|
{0, {make_template_item(true, 0x02000500F4010000, 0x0000000028000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{24, {make_template_item(true, 0x021C4600D007E803, 0xE803B80B28000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{50, {make_template_item(true, 0x021C8C00B80BD007, 0xD007581B28000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
{99, {make_template_item(true, 0x021CB400AC0DD007, 0xC409102728000012), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000), make_template_item(false, 0x0309000000000000, 0x0000000000000000)}, {}},
|
||||||
|
});
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
if ((class_flags & 0xE0) == 0x20) {
|
||||||
|
return hunter_templates.at(index);
|
||||||
|
} else if ((class_flags & 0xE0) == 0x40) {
|
||||||
|
return ranger_templates.at(index);
|
||||||
|
} else if ((class_flags & 0xE0) == 0x80) {
|
||||||
|
return force_templates.at(index);
|
||||||
|
} else {
|
||||||
|
throw runtime_error("invalid class flags on original player");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,7 +108,12 @@ struct PlayerVisualConfig {
|
|||||||
/* 31 */ uint8_t char_class = 0;
|
/* 31 */ uint8_t char_class = 0;
|
||||||
/* 32 */ uint8_t v2_flags = 0;
|
/* 32 */ uint8_t v2_flags = 0;
|
||||||
/* 33 */ uint8_t version = 0;
|
/* 33 */ uint8_t version = 0;
|
||||||
/* 34 */ le_uint32_t v1_flags = 0;
|
// class_flags specifies features of the character's class. The bits are:
|
||||||
|
// -------- -------- -------- FRHANMfm
|
||||||
|
// F = force, R = ranger, H = hunter
|
||||||
|
// A = android, N = newman, M = human
|
||||||
|
// f = female, m = male
|
||||||
|
/* 34 */ le_uint32_t class_flags = 0;
|
||||||
/* 38 */ le_uint16_t costume = 0;
|
/* 38 */ le_uint16_t costume = 0;
|
||||||
/* 3A */ le_uint16_t skin = 0;
|
/* 3A */ le_uint16_t skin = 0;
|
||||||
/* 3C */ le_uint16_t face = 0;
|
/* 3C */ le_uint16_t face = 0;
|
||||||
@@ -483,3 +488,15 @@ struct BattleRules {
|
|||||||
bool operator==(const BattleRules& other) const = default;
|
bool operator==(const BattleRules& other) const = default;
|
||||||
bool operator!=(const BattleRules& other) const = default;
|
bool operator!=(const BattleRules& other) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ChallengeTemplateDefinition {
|
||||||
|
uint32_t level;
|
||||||
|
std::vector<PlayerInventoryItem> items;
|
||||||
|
struct TechLevel {
|
||||||
|
uint8_t tech_num;
|
||||||
|
uint8_t level;
|
||||||
|
};
|
||||||
|
std::vector<TechLevel> tech_levels;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ChallengeTemplateDefinition& get_challenge_template_definition(uint32_t class_flags, size_t index);
|
||||||
|
|||||||
+23
-9
@@ -223,7 +223,8 @@ VersionedQuest::VersionedQuest(
|
|||||||
uint8_t language,
|
uint8_t language,
|
||||||
std::shared_ptr<const std::string> bin_contents,
|
std::shared_ptr<const std::string> bin_contents,
|
||||||
std::shared_ptr<const std::string> dat_contents,
|
std::shared_ptr<const std::string> dat_contents,
|
||||||
std::shared_ptr<const BattleRules> battle_rules)
|
std::shared_ptr<const BattleRules> battle_rules,
|
||||||
|
ssize_t challenge_template_index)
|
||||||
: quest_number(quest_number),
|
: quest_number(quest_number),
|
||||||
category_id(category_id),
|
category_id(category_id),
|
||||||
episode(Episode::NONE),
|
episode(Episode::NONE),
|
||||||
@@ -233,7 +234,8 @@ VersionedQuest::VersionedQuest(
|
|||||||
is_dlq_encoded(false),
|
is_dlq_encoded(false),
|
||||||
bin_contents(bin_contents),
|
bin_contents(bin_contents),
|
||||||
dat_contents(dat_contents),
|
dat_contents(dat_contents),
|
||||||
battle_rules(battle_rules) {
|
battle_rules(battle_rules),
|
||||||
|
challenge_template_index(challenge_template_index) {
|
||||||
|
|
||||||
auto bin_decompressed = prs_decompress(*this->bin_contents);
|
auto bin_decompressed = prs_decompress(*this->bin_contents);
|
||||||
|
|
||||||
@@ -378,7 +380,8 @@ Quest::Quest(shared_ptr<const VersionedQuest> initial_version)
|
|||||||
episode(initial_version->episode),
|
episode(initial_version->episode),
|
||||||
joinable(initial_version->joinable),
|
joinable(initial_version->joinable),
|
||||||
name(initial_version->name),
|
name(initial_version->name),
|
||||||
battle_rules(initial_version->battle_rules) {
|
battle_rules(initial_version->battle_rules),
|
||||||
|
challenge_template_index(initial_version->challenge_template_index) {
|
||||||
this->versions.emplace(this->versions_key(initial_version->version, initial_version->language), initial_version);
|
this->versions.emplace(this->versions_key(initial_version->version, initial_version->language), initial_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,6 +408,9 @@ void Quest::add_version(shared_ptr<const VersionedQuest> vq) {
|
|||||||
if (this->battle_rules && (*this->battle_rules != *vq->battle_rules)) {
|
if (this->battle_rules && (*this->battle_rules != *vq->battle_rules)) {
|
||||||
throw runtime_error("quest version has different battle rules");
|
throw runtime_error("quest version has different battle rules");
|
||||||
}
|
}
|
||||||
|
if (this->challenge_template_index != vq->challenge_template_index) {
|
||||||
|
throw runtime_error("quest version has different challenge template index");
|
||||||
|
}
|
||||||
|
|
||||||
this->versions.emplace(this->versions_key(vq->version, vq->language), vq);
|
this->versions.emplace(this->versions_key(vq->version, vq->language), vq);
|
||||||
}
|
}
|
||||||
@@ -654,35 +660,42 @@ QuestIndex::QuestIndex(
|
|||||||
metadata_json_cache.emplace(json_filename, metadata_json);
|
metadata_json_cache.emplace(json_filename, metadata_json);
|
||||||
|
|
||||||
shared_ptr<BattleRules> battle_rules;
|
shared_ptr<BattleRules> battle_rules;
|
||||||
|
ssize_t challenge_template_index = -1;
|
||||||
if (metadata_json) {
|
if (metadata_json) {
|
||||||
try {
|
try {
|
||||||
battle_rules.reset(new BattleRules(metadata_json->at("battle_rules")));
|
battle_rules.reset(new BattleRules(metadata_json->at("battle_rules")));
|
||||||
} catch (const out_of_range&) {
|
} catch (const out_of_range&) {
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
challenge_template_index = metadata_json->at("challenge_template_index").as_int();
|
||||||
|
} catch (const out_of_range&) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<VersionedQuest> vq(new VersionedQuest(
|
shared_ptr<VersionedQuest> vq(new VersionedQuest(
|
||||||
quest_number, category_id, version, language, bin_contents, dat_contents, battle_rules));
|
quest_number, category_id, version, language, bin_contents, dat_contents, battle_rules, challenge_template_index));
|
||||||
|
|
||||||
string ascii_name = format_data_string(encode_sjis(vq->name));
|
string ascii_name = format_data_string(encode_sjis(vq->name));
|
||||||
auto category_name = encode_sjis(this->category_index->at(vq->category_id).name);
|
auto category_name = encode_sjis(this->category_index->at(vq->category_id).name);
|
||||||
|
|
||||||
string dat_str = dat_filename.empty() ? "" : (" with layout " + dat_filename);
|
string dat_str = dat_filename.empty() ? "" : (" with layout " + dat_filename);
|
||||||
string metadata_json_str = battle_rules ? (" with battle rules from " + json_filename) : "";
|
string battle_rules_str = battle_rules ? (" with battle rules from " + json_filename) : "";
|
||||||
|
string challenge_template_str = (challenge_template_index >= 0) ? string_printf(" with challenge template index %zd", vq->challenge_template_index) : "";
|
||||||
auto q_it = this->quests_by_number.find(vq->quest_number);
|
auto q_it = this->quests_by_number.find(vq->quest_number);
|
||||||
if (q_it != this->quests_by_number.end()) {
|
if (q_it != this->quests_by_number.end()) {
|
||||||
q_it->second->add_version(vq);
|
q_it->second->add_version(vq);
|
||||||
static_game_data_log.info("(%s) Added %s %c version of quest %" PRIu32 " %s%s%s",
|
static_game_data_log.info("(%s) Added %s %c version of quest %" PRIu32 " %s%s%s%s",
|
||||||
bin_filename.c_str(),
|
bin_filename.c_str(),
|
||||||
name_for_enum(vq->version),
|
name_for_enum(vq->version),
|
||||||
char_for_language_code(vq->language),
|
char_for_language_code(vq->language),
|
||||||
vq->quest_number,
|
vq->quest_number,
|
||||||
ascii_name.c_str(),
|
ascii_name.c_str(),
|
||||||
dat_str.c_str(),
|
dat_str.c_str(),
|
||||||
metadata_json_str.c_str());
|
battle_rules_str.c_str(),
|
||||||
|
challenge_template_str.c_str());
|
||||||
} else {
|
} else {
|
||||||
this->quests_by_number.emplace(vq->quest_number, new Quest(vq));
|
this->quests_by_number.emplace(vq->quest_number, new Quest(vq));
|
||||||
static_game_data_log.info("(%s) Created %s %c quest %" PRIu32 " %s (%s, %s (%" PRIu32 "), %s)%s%s",
|
static_game_data_log.info("(%s) Created %s %c quest %" PRIu32 " %s (%s, %s (%" PRIu32 "), %s)%s%s%s",
|
||||||
bin_filename.c_str(),
|
bin_filename.c_str(),
|
||||||
name_for_enum(vq->version),
|
name_for_enum(vq->version),
|
||||||
char_for_language_code(vq->language),
|
char_for_language_code(vq->language),
|
||||||
@@ -693,7 +706,8 @@ QuestIndex::QuestIndex(
|
|||||||
vq->category_id,
|
vq->category_id,
|
||||||
vq->joinable ? "joinable" : "not joinable",
|
vq->joinable ? "joinable" : "not joinable",
|
||||||
dat_str.c_str(),
|
dat_str.c_str(),
|
||||||
metadata_json_str.c_str());
|
battle_rules_str.c_str(),
|
||||||
|
challenge_template_str.c_str());
|
||||||
}
|
}
|
||||||
} catch (const exception& e) {
|
} catch (const exception& e) {
|
||||||
static_game_data_log.warning("(%s) Failed to index quest file: (%s)", bin_filename.c_str(), e.what());
|
static_game_data_log.warning("(%s) Failed to index quest file: (%s)", bin_filename.c_str(), e.what());
|
||||||
|
|||||||
+4
-1
@@ -67,6 +67,7 @@ struct VersionedQuest {
|
|||||||
std::shared_ptr<const std::string> bin_contents;
|
std::shared_ptr<const std::string> bin_contents;
|
||||||
std::shared_ptr<const std::string> dat_contents;
|
std::shared_ptr<const std::string> dat_contents;
|
||||||
std::shared_ptr<const BattleRules> battle_rules;
|
std::shared_ptr<const BattleRules> battle_rules;
|
||||||
|
ssize_t challenge_template_index;
|
||||||
|
|
||||||
VersionedQuest(
|
VersionedQuest(
|
||||||
uint32_t quest_number,
|
uint32_t quest_number,
|
||||||
@@ -75,7 +76,8 @@ struct VersionedQuest {
|
|||||||
uint8_t language,
|
uint8_t language,
|
||||||
std::shared_ptr<const std::string> bin_contents,
|
std::shared_ptr<const std::string> bin_contents,
|
||||||
std::shared_ptr<const std::string> dat_contents,
|
std::shared_ptr<const std::string> dat_contents,
|
||||||
std::shared_ptr<const BattleRules> battle_rules = nullptr);
|
std::shared_ptr<const BattleRules> battle_rules = nullptr,
|
||||||
|
ssize_t challenge_template_index = -1);
|
||||||
|
|
||||||
std::string bin_filename() const;
|
std::string bin_filename() const;
|
||||||
std::string dat_filename() const;
|
std::string dat_filename() const;
|
||||||
@@ -105,6 +107,7 @@ public:
|
|||||||
bool joinable;
|
bool joinable;
|
||||||
std::u16string name;
|
std::u16string name;
|
||||||
std::shared_ptr<const BattleRules> battle_rules;
|
std::shared_ptr<const BattleRules> battle_rules;
|
||||||
|
ssize_t challenge_template_index;
|
||||||
std::map<uint16_t, std::shared_ptr<const VersionedQuest>> versions;
|
std::map<uint16_t, std::shared_ptr<const VersionedQuest>> versions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1411,7 +1411,7 @@ std::string disassemble_quest_script(const void* data, size_t size, QuestScriptV
|
|||||||
lines.emplace_back(string_printf(" %04zX char_class %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, char_class), visual.char_class, name_for_char_class(visual.char_class)));
|
lines.emplace_back(string_printf(" %04zX char_class %02hhX (%s)", l->offset + offsetof(PlayerVisualConfig, char_class), visual.char_class, name_for_char_class(visual.char_class)));
|
||||||
lines.emplace_back(string_printf(" %04zX v2_flags %02hhX", l->offset + offsetof(PlayerVisualConfig, v2_flags), visual.v2_flags));
|
lines.emplace_back(string_printf(" %04zX v2_flags %02hhX", l->offset + offsetof(PlayerVisualConfig, v2_flags), visual.v2_flags));
|
||||||
lines.emplace_back(string_printf(" %04zX version %02hhX", l->offset + offsetof(PlayerVisualConfig, version), visual.version));
|
lines.emplace_back(string_printf(" %04zX version %02hhX", l->offset + offsetof(PlayerVisualConfig, version), visual.version));
|
||||||
lines.emplace_back(string_printf(" %04zX v1_flags %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, v1_flags), visual.v1_flags.load()));
|
lines.emplace_back(string_printf(" %04zX class_flags %08" PRIX32, l->offset + offsetof(PlayerVisualConfig, class_flags), visual.class_flags.load()));
|
||||||
lines.emplace_back(string_printf(" %04zX costume %04hX", l->offset + offsetof(PlayerVisualConfig, costume), visual.costume.load()));
|
lines.emplace_back(string_printf(" %04zX costume %04hX", l->offset + offsetof(PlayerVisualConfig, costume), visual.costume.load()));
|
||||||
lines.emplace_back(string_printf(" %04zX skin %04hX", l->offset + offsetof(PlayerVisualConfig, skin), visual.skin.load()));
|
lines.emplace_back(string_printf(" %04zX skin %04hX", l->offset + offsetof(PlayerVisualConfig, skin), visual.skin.load()));
|
||||||
lines.emplace_back(string_printf(" %04zX face %04hX", l->offset + offsetof(PlayerVisualConfig, face), visual.face.load()));
|
lines.emplace_back(string_printf(" %04zX face %04hX", l->offset + offsetof(PlayerVisualConfig, face), visual.face.load()));
|
||||||
|
|||||||
+14
-2
@@ -2026,8 +2026,8 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
|
|||||||
l->item_creator->set_restrictions(q->battle_rules);
|
l->item_creator->set_restrictions(q->battle_rules);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t x = 0; x < l->max_clients; x++) {
|
for (size_t client_id = 0; client_id < l->max_clients; client_id++) {
|
||||||
auto lc = l->clients[x];
|
auto lc = l->clients[client_id];
|
||||||
if (!lc) {
|
if (!lc) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2043,6 +2043,18 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, const string& data)
|
|||||||
lc->game_data.create_battle_overlay(vq->battle_rules, s->level_table);
|
lc->game_data.create_battle_overlay(vq->battle_rules, s->level_table);
|
||||||
lc->log.info("Created battle overlay");
|
lc->log.info("Created battle overlay");
|
||||||
lc->game_data.player()->print_inventory(stderr);
|
lc->game_data.player()->print_inventory(stderr);
|
||||||
|
} else if (vq->challenge_template_index >= 0) {
|
||||||
|
lc->game_data.create_challenge_overlay(vq->challenge_template_index, s->level_table);
|
||||||
|
lc->log.info("Created challenge overlay");
|
||||||
|
lc->game_data.player()->print_inventory(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an overlay was created, item IDs need to be assigned
|
||||||
|
if (lc->game_data.has_overlay()) {
|
||||||
|
auto overlay = lc->game_data.player();
|
||||||
|
for (size_t z = 0; z < overlay->inventory.num_items; z++) {
|
||||||
|
overlay->inventory.items[z].data.id = l->generate_item_id(client_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string bin_filename = vq->bin_filename();
|
string bin_filename = vq->bin_filename();
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "FORBID_ALL",
|
||||||
|
"weapon_and_armor_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"meseta_drop_mode": "ALLOW",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"replace_char": false,
|
||||||
|
"box_drop_area": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"max_tech_disk_level": 0,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 0,
|
||||||
|
"box_drop_area": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "FORBID_ALL",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"max_tech_disk_level": 0,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 4,
|
||||||
|
"box_drop_area": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"max_tech_disk_level": 1,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 1,
|
||||||
|
"box_drop_area": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "FORBID_ALL",
|
||||||
|
"weapon_and_armor_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"meseta_drop_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"replace_char": false,
|
||||||
|
"box_drop_area": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"max_tech_disk_level": 4,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 19,
|
||||||
|
"box_drop_area": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "CLEAR_AND_ALLOW",
|
||||||
|
"forbid_scape_dolls": false,
|
||||||
|
"max_tech_disk_level": 0,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 0,
|
||||||
|
"box_drop_area": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"battle_rules": {
|
||||||
|
"tech_disk_mode": "LIMIT_LEVEL",
|
||||||
|
"weapon_and_armor_mode": "FORBID_ALL",
|
||||||
|
"forbid_mags": false,
|
||||||
|
"tool_mode": "FORBID_ALL",
|
||||||
|
"meseta_drop_mode": "FORBID_ALL",
|
||||||
|
"forbid_scape_dolls": true,
|
||||||
|
"max_tech_disk_level": 0,
|
||||||
|
"replace_char": true,
|
||||||
|
"char_level": 19,
|
||||||
|
"box_drop_area": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 3
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 6
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 8
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 5
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 8
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"challenge_template_index": 8
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user