From d79d551c68dcbb9da68b156d4aab5a6c5ac6b790 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 25 Dec 2025 22:19:54 -0800 Subject: [PATCH] fix Momoka item exchange via menu object --- src/CommandFormats.hh | 8 ++- src/ReceiveSubcommands.cc | 49 ++++++++++++------- .../MomokaItemExchangeFix.5___.patch.s | 2 +- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 777c92fd..771e61d0 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -812,8 +812,12 @@ struct SC_GameGuardCheck_BB_0022 { // used in the case described above; there are no other conditions that cause it to be sent. // 23 (S->C): Momoka Item Exchange result (BB) -// Sent in response to a 6xD9 command from the client. header.flag indicates if an item was exchanged: 0 means success, -// 1 means failure. This command is not valid on BB Trial Edition. +// Sent in response to a 6xD9 command from the client. This command is not valid on BB Trial Edition. header.flag +// indicates the result code: +// 0 = success +// 1 = currency item not found +// 2 = inventory is full +// Anything else = generic failure // 24 (S->C): Secret Lottery Ticket exchange result (BB) // Sent in response to a 6xDE command from the client. The client sets 8 sequential quest registers, starting with diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index a53d784a..2c52a035 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -5293,30 +5293,43 @@ static asio::awaitable on_momoka_item_exchange_bb(shared_ptr c, Su const auto& cmd = msg.check_size_t(0xFFFF); auto s = c->require_server_state(); auto p = c->character_file(); + + const auto& limits = *s->item_stack_limits(c->version()); + + ItemData new_item = cmd.replace_item; + assert_quest_item_create_allowed(l, new_item); + new_item.enforce_stack_size_limits(limits); + + bool failed = false; + ItemData found_item; try { - const auto& limits = *s->item_stack_limits(c->version()); - - ItemData new_item = cmd.replace_item; - assert_quest_item_create_allowed(l, new_item); - new_item.enforce_stack_size_limits(limits); - size_t found_index = p->inventory.find_item_by_primary_identifier(cmd.find_item.primary_identifier()); - auto found_item = p->remove_item(p->inventory.items[found_index].data.id, 1, limits); - - G_ExchangeItemInQuest_BB_6xDB cmd_6xDB = {{0xDB, 0x04, c->lobby_client_id}, 1, found_item.id, 1}; - send_command_t(c, 0x60, 0x00, cmd_6xDB); - - send_destroy_item_to_lobby(c, found_item.id, 1); + found_item = p->remove_item(p->inventory.items[found_index].data.id, 1, limits); + } catch (const std::out_of_range& e) { + failed = true; + } + if (failed) { + send_command(c, 0x23, 0x01); + co_return; + } + try { new_item.id = l->generate_item_id(c->lobby_client_id); p->add_item(new_item, limits); - send_create_inventory_item_to_lobby(c, c->lobby_client_id, new_item); - - send_command(c, 0x23, 0x00); - } catch (const exception& e) { - c->log.warning_f("Momoka item exchange failed: {}", e.what()); - send_command(c, 0x23, 0x01); + } catch (const std::out_of_range& e) { + failed = true; } + if (failed) { + p->add_item(found_item, limits); // Add found_item back since we're cancelling the exchange + send_command(c, 0x23, 0x02); + co_return; + } + + G_ExchangeItemInQuest_BB_6xDB cmd_6xDB = {{0xDB, 0x04, c->lobby_client_id}, 1, found_item.id, 1}; + send_command_t(c, 0x60, 0x00, cmd_6xDB); + send_destroy_item_to_lobby(c, found_item.id, 1); + send_create_inventory_item_to_lobby(c, c->lobby_client_id, new_item); + send_command(c, 0x23, 0x00); co_return; } diff --git a/system/client-functions/BlueBurstExclusive/MomokaItemExchangeFix.5___.patch.s b/system/client-functions/BlueBurstExclusive/MomokaItemExchangeFix.5___.patch.s index 875ad717..324d3825 100644 --- a/system/client-functions/BlueBurstExclusive/MomokaItemExchangeFix.5___.patch.s +++ b/system/client-functions/BlueBurstExclusive/MomokaItemExchangeFix.5___.patch.s @@ -54,7 +54,7 @@ send_6xD9_start: # [std](void* this @ ecx) -> void call # send_and_handle_60[std](void* cmd @ ecx) -> void add esp, 0x38 - mov dword [ebx], 6 + mov dword [ebx + 0x20], 6 push 0 call # time[std](void* t @ [esp + 4] = nullptr) -> uint32_t @ eax add esp, 4