fix Momoka item exchange via menu object

This commit is contained in:
Martin Michelsen
2025-12-25 22:19:54 -08:00
parent 4b43333ce9
commit d79d551c68
3 changed files with 38 additions and 21 deletions
+6 -2
View File
@@ -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
+31 -18
View File
@@ -5293,30 +5293,43 @@ static asio::awaitable<void> on_momoka_item_exchange_bb(shared_ptr<Client> c, Su
const auto& cmd = msg.check_size_t<G_MomokaItemExchange_BB_6xD9>(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;
}
@@ -54,7 +54,7 @@ send_6xD9_start: # [std](void* this @ ecx) -> void
call <VERS 0x00801150 0x008003E0> # send_and_handle_60[std](void* cmd @ ecx) -> void
add esp, 0x38
mov dword [ebx], 6
mov dword [ebx + 0x20], 6
push 0
call <VERS 0x0083746D 0x00859D2D> # time[std](void* t @ [esp + 4] = nullptr) -> uint32_t @ eax
add esp, 4