implement BB trade window

This commit is contained in:
Martin Michelsen
2023-11-15 22:19:44 -08:00
parent 5834a41cec
commit 82c651a3ad
3 changed files with 42 additions and 6 deletions
-1
View File
@@ -34,7 +34,6 @@
- Find any remaining mismatches in enemy indexes / experience
- Support EXP multipliers in config.json
- Implement trade window
- Fix some edge cases on the BB proxy server (e.g. Change Ship)
- Implement less-common subcommands
- 6xAC: Sort inventory
+5 -1
View File
@@ -2588,7 +2588,11 @@ struct SC_TradeItems_D0_D3 { // D0 when sent by client, D3 when sent by server
// See D0 description for usage information.
// D3 (S->C): Execute trade (V3/BB)
// Same format as D0. See D0 description for usage information.
// On V3, this command has the same format as D0. See the D0 description for
// usage information.
// On BB, this command has no arguments (and the server generates the
// appropriate delete and create inventory item commands), but the D3 command
// must still must be sent before the D4 command to advance the trade state.
// D4 (C->S): Trade failed (V3/BB)
// No arguments
+37 -4
View File
@@ -4116,12 +4116,45 @@ static void on_D2_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data)
throw runtime_error("player executed a trade with no other side pending");
}
auto complete_trade_for_side = [&](shared_ptr<Client> to_c, shared_ptr<Client> from_c) {
if (c->version() == GameVersion::BB) {
// On BB, the server is expected to generate the delete item and create
// item commands
auto to_p = to_c->game_data.character();
auto from_p = from_c->game_data.character();
for (const auto& trade_item : from_c->game_data.pending_item_trade->items) {
size_t amount = trade_item.stack_size();
auto item = from_p->remove_item(trade_item.id, amount, false);
// This is a special case: when the trade is executed, the client
// deletes the traded items from its own inventory automatically, so we
// should NOT send the 6x29 to that client; we should only send it to
// the other clients in the game.
G_DeleteInventoryItem_6x29 cmd = {{0x29, 0x03, from_c->lobby_client_id}, item.id, amount};
for (auto lc : l->clients) {
if (lc && (lc != from_c)) {
send_command_t(l, 0x60, 0x00, cmd);
}
}
to_p->add_item(trade_item);
send_create_inventory_item(to_c, item);
}
send_command(to_c, 0xD3, 0x00);
} else {
// On V3, the clients will handle it; we just send their final trade lists
// to each other
send_execute_item_trade(to_c, target_c->game_data.pending_item_trade->items);
}
send_command(to_c, 0xD4, 0x01);
};
c->game_data.pending_item_trade->confirmed = true;
if (target_c->game_data.pending_item_trade->confirmed) {
send_execute_item_trade(c, target_c->game_data.pending_item_trade->items);
send_execute_item_trade(target_c, c->game_data.pending_item_trade->items);
send_command(c, 0xD4, 0x01);
send_command(target_c, 0xD4, 0x01);
complete_trade_for_side(c, target_c);
complete_trade_for_side(target_c, c);
c->game_data.pending_item_trade.reset();
target_c->game_data.pending_item_trade.reset();
}