fix Commander Blade effect in games

This commit is contained in:
Martin Michelsen
2023-12-25 16:29:56 -08:00
parent 9255037f50
commit 441457a873
4 changed files with 59 additions and 58 deletions
-1
View File
@@ -20,5 +20,4 @@
## PSOBB ## PSOBB
- Test all quest item subcommands - 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 - Figure out why Pouilly Slime EXP doesn't work
+1 -1
View File
@@ -265,7 +265,7 @@ void PlayerLobbyDataXB::clear() {
void PlayerLobbyDataBB::clear() { void PlayerLobbyDataBB::clear() {
this->player_tag = 0; this->player_tag = 0;
this->guild_card_number = 0; this->guild_card_number = 0;
this->team_guild_card_number = 0; this->sys_guild_card_number = 0;
this->team_id = 0; this->team_id = 0;
this->unknown_a1.clear(0); this->unknown_a1.clear(0);
this->client_id = 0; this->client_id = 0;
+1 -1
View File
@@ -310,7 +310,7 @@ struct PlayerLobbyDataXB {
struct PlayerLobbyDataBB { struct PlayerLobbyDataBB {
/* 00 */ le_uint32_t player_tag = 0; /* 00 */ le_uint32_t player_tag = 0;
/* 04 */ le_uint32_t guild_card_number = 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; /* 0C */ le_uint32_t team_id = 0;
/* 10 */ parray<uint8_t, 0x0C> unknown_a1; /* 10 */ parray<uint8_t, 0x0C> unknown_a1;
/* 1C */ le_uint32_t client_id = 0; /* 1C */ le_uint32_t client_id = 0;
+57 -55
View File
@@ -1617,6 +1617,48 @@ void send_player_records_t(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr
send_command_vt(c->channel, 0xC5, entries.size(), entries); send_command_vt(c->channel, 0xC5, entries.size(), entries);
} }
template <typename LobbyDataT>
void populate_lobby_data_for_client(LobbyDataT& ret, shared_ptr<const Client> c, shared_ptr<const Client> 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<const Client> c, shared_ptr<const Client> 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>(PlayerLobbyDataBB& ret, shared_ptr<const Client> c, shared_ptr<const Client> 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<Client> c, shared_ptr<Lobby> l) { static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l) {
if (!is_ep3(c->version())) { if (!is_ep3(c->version())) {
throw runtime_error("client is not Episode 3"); throw runtime_error("client is not Episode 3");
@@ -1651,10 +1693,7 @@ static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l)
} }
auto wc_p = wc->character(); auto wc_p = wc->character();
auto& p = cmd.players[z]; auto& p = cmd.players[z];
p.lobby_data.player_tag = 0x00010000; populate_lobby_data_for_client(p.lobby_data, wc, c);
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());
p.inventory = wc_p->inventory; p.inventory = wc_p->inventory;
p.inventory.encode_for_client(c); p.inventory.encode_for_client(c);
p.disp = wc_p->disp.to_dcpcv3(c->language(), p.inventory.language); p.disp = wc_p->disp.to_dcpcv3(c->language(), p.inventory.language);
@@ -1719,10 +1758,7 @@ static void send_join_spectator_team(shared_ptr<Client> c, shared_ptr<Lobby> l)
auto other_p = other_c->character(); auto other_p = other_c->character();
auto& cmd_p = cmd.spectator_players[z - 4]; auto& cmd_p = cmd.spectator_players[z - 4];
auto& cmd_e = cmd.entries[z]; auto& cmd_e = cmd.entries[z];
cmd_p.lobby_data.player_tag = 0x00010000; populate_lobby_data_for_client(cmd_p.lobby_data, other_c, c);
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());
cmd_p.inventory = other_p->inventory; cmd_p.inventory = other_p->inventory;
cmd_p.disp = other_p->disp.to_dcpcv3(c->language(), cmd_p.inventory.language); cmd_p.disp = other_p->disp.to_dcpcv3(c->language(), cmd_p.inventory.language);
cmd_p.disp.enforce_lobby_join_limits_for_client(c); cmd_p.disp.enforce_lobby_join_limits_for_client(c);
@@ -1755,10 +1791,7 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
for (size_t x = 0; x < 4; x++) { for (size_t x = 0; x < 4; x++) {
auto lc = l->clients[x]; auto lc = l->clients[x];
if (lc) { if (lc) {
cmd.lobby_data[x].player_tag = 0x00010000; populate_lobby_data_for_client(cmd.lobby_data[x], lc, c);
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());
player_count++; player_count++;
} else { } else {
cmd.lobby_data[x].clear(); cmd.lobby_data[x].clear();
@@ -1852,16 +1885,6 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
case Version::XB_V3: { case Version::XB_V3: {
S_JoinGame_XB_64 cmd; S_JoinGame_XB_64 cmd;
size_t player_count = populate_v3_cmd(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); send_command_t(c, 0x64, player_count, cmd);
break; break;
} }
@@ -1883,7 +1906,7 @@ void send_join_game(shared_ptr<Client> c, shared_ptr<Lobby> l) {
send_command(c, 0x1D, 0x00); send_command(c, 0x1D, 0x00);
} }
template <typename LobbyDataT, typename DispDataT, typename RecordsT, bool UseLanguageMarkerInName> template <typename LobbyDataT, typename DispDataT, typename RecordsT>
void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Client> joining_client = nullptr) { void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Client> joining_client = nullptr) {
auto s = c->require_server_state(); auto s = c->require_server_state();
@@ -1957,17 +1980,7 @@ void send_join_lobby_t(shared_ptr<Client> c, shared_ptr<Lobby> l, shared_ptr<Cli
for (const auto& lc : lobby_clients) { for (const auto& lc : lobby_clients) {
auto lp = lc->character(); auto lp = lc->character();
auto& e = cmd.entries[used_entries++]; auto& e = cmd.entries[used_entries++];
e.lobby_data.player_tag = 0x00010000; populate_lobby_data_for_client(e.lobby_data, lc, c);
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());
}
e.inventory = lp->inventory; e.inventory = lp->inventory;
e.inventory.encode_for_client(c); e.inventory.encode_for_client(c);
if ((lc == c) && is_v1_or_v2(c->version()) && lc->v1_v2_last_reported_disp) { 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<Client> c, shared_ptr<Lobby> l, shared_ptr<Cl
for (const auto& lc : lobby_clients) { for (const auto& lc : lobby_clients) {
auto lp = lc->character(); auto lp = lc->character();
auto& e = cmd.entries[used_entries++]; auto& e = cmd.entries[used_entries++];
e.lobby_data.player_tag = 0x00010000; populate_lobby_data_for_client(e.lobby_data, lc, c);
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());
e.inventory = lp->inventory; e.inventory = lp->inventory;
e.inventory.encode_for_client(c); e.inventory.encode_for_client(c);
e.disp = convert_player_disp_data<PlayerDispDataDCPCV3>(lp->disp, c->language(), lp->inventory.language); e.disp = convert_player_disp_data<PlayerDispDataDCPCV3>(lp->disp, c->language(), lp->inventory.language);
@@ -2089,10 +2094,7 @@ void send_join_lobby_dc_nte(shared_ptr<Client> c, shared_ptr<Lobby> l,
for (const auto& lc : lobby_clients) { for (const auto& lc : lobby_clients) {
auto lp = lc->character(); auto lp = lc->character();
auto& e = cmd.entries[used_entries++]; auto& e = cmd.entries[used_entries++];
e.lobby_data.player_tag = 0x00010000; populate_lobby_data_for_client(e.lobby_data, lc, c);
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());
e.inventory = lp->inventory; e.inventory = lp->inventory;
e.inventory.encode_for_client(c); e.inventory.encode_for_client(c);
e.disp = convert_player_disp_data<PlayerDispDataDCPCV3>(lp->disp, c->language(), lp->inventory.language); e.disp = convert_player_disp_data<PlayerDispDataDCPCV3>(lp->disp, c->language(), lp->inventory.language);
@@ -2113,23 +2115,23 @@ void send_join_lobby(shared_ptr<Client> c, shared_ptr<Lobby> l) {
break; break;
case Version::DC_V1: case Version::DC_V1:
case Version::DC_V2: case Version::DC_V2:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC, false>(c, l); send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC>(c, l);
break; break;
case Version::PC_NTE: case Version::PC_NTE:
case Version::PC_V2: case Version::PC_V2:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC, false>(c, l); send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC>(c, l);
break; break;
case Version::GC_NTE: case Version::GC_NTE:
case Version::GC_V3: case Version::GC_V3:
case Version::GC_EP3_TRIAL_EDITION: case Version::GC_EP3_TRIAL_EDITION:
case Version::GC_EP3: case Version::GC_EP3:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3, false>(c, l); send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l);
break; break;
case Version::XB_V3: case Version::XB_V3:
send_join_lobby_xb(c, l); send_join_lobby_xb(c, l);
break; break;
case Version::BB_V4: case Version::BB_V4:
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB, true>(c, l); send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB>(c, l);
break; break;
default: default:
throw logic_error("unimplemented versioned command"); throw logic_error("unimplemented versioned command");
@@ -2153,23 +2155,23 @@ void send_player_join_notification(shared_ptr<Client> c,
break; break;
case Version::DC_V1: case Version::DC_V1:
case Version::DC_V2: case Version::DC_V2:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC, false>(c, l, joining_client); send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_DC>(c, l, joining_client);
break; break;
case Version::PC_NTE: case Version::PC_NTE:
case Version::PC_V2: case Version::PC_V2:
send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC, false>(c, l, joining_client); send_join_lobby_t<PlayerLobbyDataPC, PlayerDispDataDCPCV3, PlayerRecordsEntry_PC>(c, l, joining_client);
break; break;
case Version::GC_NTE: case Version::GC_NTE:
case Version::GC_V3: case Version::GC_V3:
case Version::GC_EP3_TRIAL_EDITION: case Version::GC_EP3_TRIAL_EDITION:
case Version::GC_EP3: case Version::GC_EP3:
send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3, false>(c, l, joining_client); send_join_lobby_t<PlayerLobbyDataDCGC, PlayerDispDataDCPCV3, PlayerRecordsEntry_V3>(c, l, joining_client);
break; break;
case Version::XB_V3: case Version::XB_V3:
send_join_lobby_xb(c, l, joining_client); send_join_lobby_xb(c, l, joining_client);
break; break;
case Version::BB_V4: case Version::BB_V4:
send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB, true>(c, l, joining_client); send_join_lobby_t<PlayerLobbyDataBB, PlayerDispDataBB, PlayerRecordsEntry_BB>(c, l, joining_client);
break; break;
default: default:
throw logic_error("unimplemented versioned command"); throw logic_error("unimplemented versioned command");