From 9097abf307ac8c3839bcac7cc3ac7829113c867a Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 22 Nov 2023 12:28:11 -0800 Subject: [PATCH] fix starting inventory on new BB chars --- src/PlayerSubordinates.cc | 16 +++-- src/PlayerSubordinates.hh | 3 + src/SaveFileFormats.cc | 145 ++++++++++++++++++++++++++++++++++++-- src/SaveFileFormats.hh | 2 +- 4 files changed, 154 insertions(+), 12 deletions(-) diff --git a/src/PlayerSubordinates.cc b/src/PlayerSubordinates.cc index 20d39d1d..3748906a 100644 --- a/src/PlayerSubordinates.cc +++ b/src/PlayerSubordinates.cc @@ -22,6 +22,14 @@ using namespace std; +PlayerInventoryItem::PlayerInventoryItem(const ItemData& item, bool equipped) + : present(1), + unknown_a1(0), + extension_data1(0), + extension_data2(0), + flags(equipped ? 8 : 0), + data(item) {} + uint32_t PlayerVisualConfig::compute_name_color_checksum(uint32_t name_color) { uint8_t x = (random_object() % 0xFF) + 1; uint8_t y = (random_object() % 0xFF) + 1; @@ -889,13 +897,7 @@ BattleRules::MesetaMode enum_for_name(const char* name) } static PlayerInventoryItem make_template_item(bool equipped, uint64_t first_data, uint64_t second_data) { - PlayerInventoryItem ret = { - .present = 1, - .unknown_a1 = 0, - .extension_data1 = 0, - .extension_data2 = 0, - .flags = (equipped ? 8 : 0), - .data = ItemData()}; + PlayerInventoryItem ret(ItemData(), equipped); ret.data.data1[0] = first_data >> 56; ret.data.data1[1] = first_data >> 48; ret.data.data1[2] = first_data >> 40; diff --git a/src/PlayerSubordinates.hh b/src/PlayerSubordinates.hh index da59e2fe..23af8ec2 100644 --- a/src/PlayerSubordinates.hh +++ b/src/PlayerSubordinates.hh @@ -52,6 +52,9 @@ struct PlayerInventoryItem { /* 04 */ le_uint32_t flags = 0; // 8 = equipped /* 08 */ ItemData data; /* 1C */ + + PlayerInventoryItem() = default; + explicit PlayerInventoryItem(const ItemData& item, bool equipped = false); } __attribute__((packed)); struct PlayerBankItem { diff --git a/src/SaveFileFormats.cc b/src/SaveFileFormats.cc index 461cb484..db10e886 100644 --- a/src/SaveFileFormats.cc +++ b/src/SaveFileFormats.cc @@ -213,9 +213,146 @@ shared_ptr PSOBBCharacterFile::create_from_preview( uint8_t language, const PlayerDispDataBBPreview& preview, shared_ptr level_table) { + static const array, 12> initial_inventory{{ + { + PlayerInventoryItem(ItemData(0x0001000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0001000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0001000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0006000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0006000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0006000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x000A000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x000A000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x000A000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0001000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x000A000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + { + PlayerInventoryItem(ItemData(0x0006000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x0101000000000000, 0x0000000000000000), true), + PlayerInventoryItem(ItemData(0x02000500F4010000, 0x0000000028000012), true), + PlayerInventoryItem(ItemData(0x0300000000040000, 0x0000000000000000), false), + PlayerInventoryItem(ItemData(0x0301000000040000, 0x0000000000000000), false), + }, + }}; + + array config_hunter_ranger{ + {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + array config_force{ + {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + shared_ptr ret(new PSOBBCharacterFile()); + + const auto& initial_items = initial_inventory.at(preview.visual.char_class); + ret->inventory.num_items = initial_items.size(); + for (size_t z = 0; z < initial_items.size(); z++) { + ret->inventory.items[z] = initial_items[z]; + } + ret->inventory.items[13].extension_data2 = 1; + + const auto& config = (ret->disp.visual.class_flags & 0x80) ? config_force : config_hunter_ranger; + for (size_t z = 0; z < config.size(); z++) { + ret->disp.config[z] = config[z]; + } + ret->disp.apply_preview(preview); ret->disp.stats.reset_to_base(ret->disp.visual.char_class, level_table); + ret->disp.technique_levels_v1.clear(0xFF); + if (ret->disp.visual.class_flags & 0x80) { + ret->disp.technique_levels_v1[0] = 0x00; // Forces start with Foie Lv.1 + } ret->inventory.language = language; ret->guild_card.guild_card_number = guild_card_number; ret->guild_card.name = ret->disp.name; @@ -436,7 +573,7 @@ void PSOBBCharacterFile::print_inventory(FILE* stream, GameVersion version, shar } } -const std::array PSOBBCharacterFile::DEFAULT_SYMBOL_CHATS = { +const array PSOBBCharacterFile::DEFAULT_SYMBOL_CHATS = { DefaultSymbolChatEntry{"\tEHello", 0x28, {0xFFFF, 0x000D, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x05, 0x18, 0x1D, 0x00}, {0x05, 0x28, 0x1D, 0x01}, {0x36, 0x20, 0x2A, 0x00}, {0x3C, 0x00, 0x32, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}}, DefaultSymbolChatEntry{"\tEGood-bye", 0x74, {0x0476, 0x000C, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x06, 0x15, 0x14, 0x00}, {0x06, 0x2B, 0x14, 0x01}, {0x05, 0x18, 0x1F, 0x00}, {0x05, 0x28, 0x1F, 0x01}, {0x36, 0x20, 0x2A, 0x00}, {0x3C, 0x00, 0x32, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}}, DefaultSymbolChatEntry{"\tEHurrah!", 0x28, {0x0362, 0x0362, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x09, 0x16, 0x1B, 0x00}, {0x09, 0x2B, 0x1B, 0x01}, {0x37, 0x20, 0x2C, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}}, @@ -445,11 +582,11 @@ const std::array PSOBBCharacterFi DefaultSymbolChatEntry{"\tEHelp me!", 0xEC, {0x065E, 0x0138, 0xFFFF, 0xFFFF}, {SymbolChat::FacePart{0x02, 0x17, 0x1B, 0x01}, {0x02, 0x2A, 0x1B, 0x00}, {0x31, 0x20, 0x2C, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x00}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}, {0xFF, 0x00, 0x00, 0x02}}}, }; -const std::array PSOBBCharacterFile::DEFAULT_TECH_MENU_CONFIG = { +const array PSOBBCharacterFile::DEFAULT_TECH_MENU_CONFIG = { 0x0000, 0x0006, 0x0003, 0x0001, 0x0007, 0x0004, 0x0002, 0x0008, 0x0005, 0x0009, 0x0012, 0x000F, 0x0010, 0x0011, 0x000D, 0x000A, 0x000B, 0x000C, 0x000E, 0x0000}; -const std::array PSOBBBaseSystemFile::DEFAULT_KEY_CONFIG = { +const array PSOBBBaseSystemFile::DEFAULT_KEY_CONFIG = { 0x00, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -474,7 +611,7 @@ const std::array PSOBBBaseSystemFile::DEFAULT_KEY_CONFIG = { 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; -const std::array PSOBBBaseSystemFile::DEFAULT_JOYSTICK_CONFIG = { +const array PSOBBBaseSystemFile::DEFAULT_JOYSTICK_CONFIG = { 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, diff --git a/src/SaveFileFormats.hh b/src/SaveFileFormats.hh index d9694e9c..2376c132 100644 --- a/src/SaveFileFormats.hh +++ b/src/SaveFileFormats.hh @@ -192,7 +192,7 @@ struct PSOBBCharacterFile { /* 04E0 */ le_uint32_t creation_timestamp = 0; /* 04E4 */ le_uint32_t signature = 0xC87ED5B1; /* 04E8 */ le_uint32_t play_time_seconds = 0; - /* 04EC */ le_uint32_t option_flags = 0; + /* 04EC */ le_uint32_t option_flags = 0x00040058; /* 04F0 */ parray unknown_a2; /* 04F4 */ parray, 4> quest_flags; /* 06F4 */ le_uint32_t death_count = 0;