From e9109a68779c6eccc4db0ea0098e46eeeb61dd85 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 12 May 2022 18:46:19 -0700 Subject: [PATCH] fix some BB item bugs --- src/Items.cc | 2 +- src/Lobby.cc | 16 ++++++++-------- src/Main.cc | 2 +- src/ReceiveSubcommands.cc | 11 ++++++++++- src/SendCommands.cc | 12 ++++++------ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Items.cc b/src/Items.cc index 7f1616c3..f8bb9621 100644 --- a/src/Items.cc +++ b/src/Items.cc @@ -456,7 +456,7 @@ ItemData CommonItemCreator::create_drop_item(bool is_box, uint8_t episode, case 0x07: // meseta item.data1[0] = 0x04; - item.data2d = (90 * difficulty) + (random_int(0, 20) * (area * 2)); // meseta amount + item.data2d = (90 * difficulty) + (random_int(1, 20) * (area * 2)); // meseta amount break; default: diff --git a/src/Lobby.cc b/src/Lobby.cc index 5bc5ce9e..12602569 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -12,12 +12,12 @@ using namespace std; Lobby::Lobby() : lobby_id(0), min_level(0), max_level(0xFFFFFFFF), - next_game_item_id(0), version(GameVersion::GC), section_id(0), episode(1), - difficulty(0), mode(0), rare_seed(random_object()), event(0), - block(0), type(0), leader_id(0), max_clients(12), flags(0) { + next_game_item_id(0x00810000), version(GameVersion::GC), section_id(0), + episode(1), difficulty(0), mode(0), rare_seed(random_object()), + event(0), block(0), type(0), leader_id(0), max_clients(12), flags(0) { for (size_t x = 0; x < 12; x++) { - this->next_item_id[x] = 0; + this->next_item_id[x] = 0x00010000 + 0x00200000 * x; } this->next_drop_item = PlayerInventoryItem(); } @@ -84,7 +84,7 @@ void Lobby::add_client(shared_ptr c, bool reverse_indexes) { c->lobby_client_id = index; c->lobby_id = this->lobby_id; - // if there's no one else in the lobby, set the leader id as well + // If there's no one else in the lobby, set the leader id as well if (index == (max_clients - 1) * reverse_indexes) { for (index = 0; index < max_clients; index++) { if (this->clients[index].get() && this->clients[index] != c) { @@ -99,9 +99,9 @@ void Lobby::add_client(shared_ptr c, bool reverse_indexes) { // If the lobby is a game, assign the inventory's item IDs if (this->is_game()) { auto& inv = c->game_data.player()->inventory; - size_t count = max(inv.num_items, 30); + size_t count = min(inv.num_items, 30); for (size_t x = 0; x < count; x++) { - inv.items[x].data.id = 0x00010000 + 0x00200000 * c->lobby_client_id + x; + inv.items[x].data.id = this->generate_item_id(c->lobby_client_id); } c->game_data.player()->print_inventory(stderr); } @@ -118,7 +118,7 @@ void Lobby::remove_client(shared_ptr c) { this->clients[c->lobby_client_id] = nullptr; - // unassign the client's lobby if it matches the current lobby's id (it may + // Unassign the client's lobby if it matches the current lobby's id (it may // not match if the client was already added to another lobby - this can // happen during the lobby change procedure) if (c->lobby_id == this->lobby_id) { diff --git a/src/Main.cc b/src/Main.cc index 1410967b..77fb0d86 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -169,7 +169,7 @@ void populate_state_from_config(shared_ptr s, u"Connect to another\nserver", MenuItem::Flag::GC_ONLY); } s->main_menu.emplace_back(MAIN_MENU_DOWNLOAD_QUESTS, u"Download quests", - u"Download quests", 0); + u"Download quests", MenuItem::Flag::INVISIBLE_ON_BB); s->main_menu.emplace_back(MAIN_MENU_DISCONNECT, u"Disconnect", u"Disconnect", 0); diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index 457765ee..f1820aff 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -341,9 +341,14 @@ static void process_subcommand_drop_partial_stack_bb(shared_ptr, item.data.id = l->generate_item_id(c->lobby_client_id); } + // PSOBB sends a 6x29 command after it receives the 6x5D, so we need to add + // the item back to the player's inventory to correct for this (it will get + // removed again by the 6x29 handler) + c->game_data.player()->add_item(item); + l->add_item(item, cmd->area, cmd->x, cmd->z); - log(INFO, "[Items/%08" PRIX32 "] Player %hhu split stack %08" PRIX32 " (%" PRIu32 " of them) at %hu:(%g, %g)", + log(INFO, "[Items/%08" PRIX32 "/BB] Player %hhu split stack %08" PRIX32 " (%" PRIu32 " of them) at %hu:(%g, %g)", l->lobby_id, cmd->client_id, cmd->item_id.load(), cmd->amount.load(), cmd->area.load(), cmd->x.load(), cmd->z.load()); c->game_data.player()->print_inventory(stderr); @@ -442,6 +447,10 @@ static void process_subcommand_pick_up_item_request(shared_ptr, c->game_data.player()->add_item(l->remove_item(cmd->item_id)); + log(INFO, "[Items/%08" PRIX32 "/BB] Player %hhu picked up %08" PRIX32, + l->lobby_id, cmd->client_id, cmd->item_id.load()); + c->game_data.player()->print_inventory(stderr); + send_pick_up_item(l, c, cmd->item_id, cmd->area); } else { diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 1c27d633..263d2129 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1169,25 +1169,24 @@ void send_revive_player(shared_ptr l, shared_ptr c) { //////////////////////////////////////////////////////////////////////////////// // BB game commands -// notifies other players of a dropped item from a box or enemy void send_drop_item(shared_ptr l, const ItemData& item, bool from_enemy, uint8_t area, float x, float z, uint16_t request_id) { G_DropItem_6x5F cmd = { - 0x5F, 0x0A, 0x0000, area, from_enemy, request_id, x, z, 0, item, 0}; + 0x5F, 0x0B, 0x0000, area, from_enemy, request_id, x, z, 0, item, 0}; send_command_t(l, 0x60, 0x00, cmd); } -// notifies other players that a stack was split and part of it dropped (a new item was created) +// Notifies other players that a stack was split and part of it dropped (a new +// item was created) void send_drop_stacked_item(shared_ptr l, const ItemData& item, uint8_t area, float x, float z) { // TODO: Is this order correct? The original code sent {item, 0}, but it seems // GC sends {0, item} (the last two fields in the struct are switched). G_DropStackedItem_6x5D cmd = { - 0x5D, 0x09, 0x00, 0x00, area, 0, x, z, item, 0}; + 0x5D, 0x0A, 0x00, 0x00, area, 0, x, z, item, 0}; send_command_t(l, 0x60, 0x00, cmd); } -// notifies other players that an item was picked up void send_pick_up_item(shared_ptr l, shared_ptr c, uint32_t item_id, uint8_t area) { G_PickUpItem_6x59 cmd = { @@ -1195,7 +1194,8 @@ void send_pick_up_item(shared_ptr l, shared_ptr c, send_command_t(l, 0x60, 0x00, cmd); } -// creates an item in a player's inventory (used for withdrawing items from the bank) +// Creates an item in a player's inventory (used for withdrawing items from the +// bank) void send_create_inventory_item(shared_ptr l, shared_ptr c, const ItemData& item) { G_CreateInventoryItem_BB_6xBE cmd = {