From 441457a8733c7fa6449b95b936405aa982eaf177 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 25 Dec 2023 16:29:56 -0800 Subject: [PATCH] fix Commander Blade effect in games --- TODO.md | 1 - src/PlayerSubordinates.cc | 2 +- src/PlayerSubordinates.hh | 2 +- src/SendCommands.cc | 112 +++++++++++++++++++------------------- 4 files changed, 59 insertions(+), 58 deletions(-) diff --git a/TODO.md b/TODO.md index 21ec9003..0f9eaa4e 100644 --- a/TODO.md +++ b/TODO.md @@ -20,5 +20,4 @@ ## PSOBB - Test all quest item subcommands -- Check if Commander Blade effect works and implement it if not - Figure out why Pouilly Slime EXP doesn't work diff --git a/src/PlayerSubordinates.cc b/src/PlayerSubordinates.cc index 6bc5bc7e..3e1bd957 100644 --- a/src/PlayerSubordinates.cc +++ b/src/PlayerSubordinates.cc @@ -265,7 +265,7 @@ void PlayerLobbyDataXB::clear() { void PlayerLobbyDataBB::clear() { this->player_tag = 0; this->guild_card_number = 0; - this->team_guild_card_number = 0; + this->sys_guild_card_number = 0; this->team_id = 0; this->unknown_a1.clear(0); this->client_id = 0; diff --git a/src/PlayerSubordinates.hh b/src/PlayerSubordinates.hh index ee2ad27c..7f6cfc98 100644 --- a/src/PlayerSubordinates.hh +++ b/src/PlayerSubordinates.hh @@ -310,7 +310,7 @@ struct PlayerLobbyDataXB { struct PlayerLobbyDataBB { /* 00 */ le_uint32_t player_tag = 0; /* 04 */ le_uint32_t guild_card_number = 0; - /* 08 */ le_uint32_t team_guild_card_number = 0; + /* 08 */ le_uint32_t sys_guild_card_number = 0; /* 0C */ le_uint32_t team_id = 0; /* 10 */ parray unknown_a1; /* 1C */ le_uint32_t client_id = 0; diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 9d305dd3..eafcb07d 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1617,6 +1617,48 @@ void send_player_records_t(shared_ptr c, shared_ptr l, shared_ptr send_command_vt(c->channel, 0xC5, entries.size(), entries); } +template +void populate_lobby_data_for_client(LobbyDataT& ret, shared_ptr c, shared_ptr viewer_c) { + ret.player_tag = 0x00010000; + ret.guild_card_number = c->license->serial_number; + ret.client_id = c->lobby_client_id; + string name = c->character()->disp.name.decode(c->language()); + ret.name.encode(name, viewer_c->language()); +} + +template <> +void populate_lobby_data_for_client(PlayerLobbyDataXB& ret, shared_ptr c, shared_ptr viewer_c) { + ret.player_tag = 0x00010000; + ret.guild_card_number = c->license->serial_number; + if (c->xb_netloc) { + ret.netloc = *c->xb_netloc; + } else { + ret.netloc.account_id = 0xAE00000000000000 | c->license->serial_number; + } + ret.client_id = c->lobby_client_id; + string name = c->character()->disp.name.decode(c->language()); + ret.name.encode(name, viewer_c->language()); +} + +template <> +void populate_lobby_data_for_client(PlayerLobbyDataBB& ret, shared_ptr c, shared_ptr viewer_c) { + ret.player_tag = 0x00010000; + ret.guild_card_number = c->license->serial_number; + ret.sys_guild_card_number = viewer_c->license->serial_number; + ret.client_id = c->lobby_client_id; + auto team = c->team(); + if (team) { + ret.team_id = team->team_id; + } + string name = c->character()->disp.name.decode(c->language()); + if ((name.size() >= 2) && (name[0] == '\t') && (name[1] != 'C')) { + ret.name.encode(name, viewer_c->language()); + } else { + const char* marker = c->language() ? "\tE" : "\tJ"; + ret.name.encode(marker + name, viewer_c->language()); + } +} + static void send_join_spectator_team(shared_ptr c, shared_ptr l) { if (!is_ep3(c->version())) { throw runtime_error("client is not Episode 3"); @@ -1651,10 +1693,7 @@ static void send_join_spectator_team(shared_ptr c, shared_ptr l) } auto wc_p = wc->character(); auto& p = cmd.players[z]; - p.lobby_data.player_tag = 0x00010000; - p.lobby_data.guild_card_number = wc->license->serial_number; - p.lobby_data.client_id = wc->lobby_client_id; - p.lobby_data.name.encode(wc_p->disp.name.decode(wc_p->inventory.language), c->language()); + populate_lobby_data_for_client(p.lobby_data, wc, c); p.inventory = wc_p->inventory; p.inventory.encode_for_client(c); p.disp = wc_p->disp.to_dcpcv3(c->language(), p.inventory.language); @@ -1719,10 +1758,7 @@ static void send_join_spectator_team(shared_ptr c, shared_ptr l) auto other_p = other_c->character(); auto& cmd_p = cmd.spectator_players[z - 4]; auto& cmd_e = cmd.entries[z]; - cmd_p.lobby_data.player_tag = 0x00010000; - cmd_p.lobby_data.guild_card_number = other_c->license->serial_number; - cmd_p.lobby_data.client_id = other_c->lobby_client_id; - cmd_p.lobby_data.name.encode(other_p->disp.name.decode(other_p->inventory.language), c->language()); + populate_lobby_data_for_client(cmd_p.lobby_data, other_c, c); cmd_p.inventory = other_p->inventory; cmd_p.disp = other_p->disp.to_dcpcv3(c->language(), cmd_p.inventory.language); cmd_p.disp.enforce_lobby_join_limits_for_client(c); @@ -1755,10 +1791,7 @@ void send_join_game(shared_ptr c, shared_ptr l) { for (size_t x = 0; x < 4; x++) { auto lc = l->clients[x]; if (lc) { - cmd.lobby_data[x].player_tag = 0x00010000; - cmd.lobby_data[x].guild_card_number = lc->license->serial_number; - cmd.lobby_data[x].client_id = lc->lobby_client_id; - cmd.lobby_data[x].name.encode(lc->character()->disp.name.decode(lc->language()), c->language()); + populate_lobby_data_for_client(cmd.lobby_data[x], lc, c); player_count++; } else { cmd.lobby_data[x].clear(); @@ -1852,16 +1885,6 @@ void send_join_game(shared_ptr c, shared_ptr l) { case Version::XB_V3: { S_JoinGame_XB_64 cmd; size_t player_count = populate_v3_cmd(cmd); - for (size_t x = 0; x < 4; x++) { - auto lc = l->clients[x]; - if (lc) { - if (lc->xb_netloc) { - cmd.lobby_data[x].netloc = *lc->xb_netloc; - } else { - cmd.lobby_data[x].netloc.account_id = 0xAE00000000000000 | lc->license->serial_number; - } - } - } send_command_t(c, 0x64, player_count, cmd); break; } @@ -1883,7 +1906,7 @@ void send_join_game(shared_ptr c, shared_ptr l) { send_command(c, 0x1D, 0x00); } -template +template void send_join_lobby_t(shared_ptr c, shared_ptr l, shared_ptr joining_client = nullptr) { auto s = c->require_server_state(); @@ -1957,17 +1980,7 @@ void send_join_lobby_t(shared_ptr c, shared_ptr l, shared_ptrcharacter(); auto& e = cmd.entries[used_entries++]; - e.lobby_data.player_tag = 0x00010000; - e.lobby_data.guild_card_number = lc->license->serial_number; - e.lobby_data.client_id = lc->lobby_client_id; - string name = lp->disp.name.decode(lp->inventory.language); - bool name_has_marker = (name.size() >= 2) && (name[0] == '\t') && (name[1] != 'C'); - if (UseLanguageMarkerInName && !name_has_marker) { - const char* marker = c->language() ? "\tE" : "\tJ"; - e.lobby_data.name.encode(marker + name, c->language()); - } else { - e.lobby_data.name.encode(name, c->language()); - } + populate_lobby_data_for_client(e.lobby_data, lc, c); e.inventory = lp->inventory; e.inventory.encode_for_client(c); if ((lc == c) && is_v1_or_v2(c->version()) && lc->v1_v2_last_reported_disp) { @@ -2036,15 +2049,7 @@ void send_join_lobby_xb(shared_ptr c, shared_ptr l, shared_ptrcharacter(); auto& e = cmd.entries[used_entries++]; - e.lobby_data.player_tag = 0x00010000; - e.lobby_data.guild_card_number = lc->license->serial_number; - if (lc->xb_netloc) { - e.lobby_data.netloc = *lc->xb_netloc; - } else { - e.lobby_data.netloc.account_id = 0xAE00000000000000 | lc->license->serial_number; - } - e.lobby_data.client_id = lc->lobby_client_id; - e.lobby_data.name.encode(lp->disp.name.decode(lp->inventory.language), c->language()); + populate_lobby_data_for_client(e.lobby_data, lc, c); e.inventory = lp->inventory; e.inventory.encode_for_client(c); e.disp = convert_player_disp_data(lp->disp, c->language(), lp->inventory.language); @@ -2089,10 +2094,7 @@ void send_join_lobby_dc_nte(shared_ptr c, shared_ptr l, for (const auto& lc : lobby_clients) { auto lp = lc->character(); auto& e = cmd.entries[used_entries++]; - e.lobby_data.player_tag = 0x00010000; - e.lobby_data.guild_card_number = lc->license->serial_number; - e.lobby_data.client_id = lc->lobby_client_id; - e.lobby_data.name.encode(lp->disp.name.decode(lp->inventory.language), c->language()); + populate_lobby_data_for_client(e.lobby_data, lc, c); e.inventory = lp->inventory; e.inventory.encode_for_client(c); e.disp = convert_player_disp_data(lp->disp, c->language(), lp->inventory.language); @@ -2113,23 +2115,23 @@ void send_join_lobby(shared_ptr c, shared_ptr l) { break; case Version::DC_V1: case Version::DC_V2: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; case Version::PC_NTE: case Version::PC_V2: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; case Version::GC_NTE: case Version::GC_V3: case Version::GC_EP3_TRIAL_EDITION: case Version::GC_EP3: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; case Version::XB_V3: send_join_lobby_xb(c, l); break; case Version::BB_V4: - send_join_lobby_t(c, l); + send_join_lobby_t(c, l); break; default: throw logic_error("unimplemented versioned command"); @@ -2153,23 +2155,23 @@ void send_player_join_notification(shared_ptr c, break; case Version::DC_V1: case Version::DC_V2: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; case Version::PC_NTE: case Version::PC_V2: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; case Version::GC_NTE: case Version::GC_V3: case Version::GC_EP3_TRIAL_EDITION: case Version::GC_EP3: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; case Version::XB_V3: send_join_lobby_xb(c, l, joining_client); break; case Version::BB_V4: - send_join_lobby_t(c, l, joining_client); + send_join_lobby_t(c, l, joining_client); break; default: throw logic_error("unimplemented versioned command");