From c1c28d421634d5b816c23a233b26d00b1d38e6bc Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 29 Mar 2026 22:04:23 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20quest=20objective=20GOs=20never=20grante?= =?UTF-8?q?d=20credit=20=E2=80=94=20REPORT=5FUSE=20skipped=20for=20chests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CMSG_GAMEOBJ_REPORT_USE was only sent for non-chest GOs. Chest-type (type=3) and name-matched chest-like GOs (Bundle of Wood, etc.) went through a separate path that sent CMSG_GAMEOBJ_USE + CMSG_LOOT but skipped REPORT_USE. On AzerothCore, REPORT_USE triggers the server-side HandleGameobjectReportUse which calls GossipHello on the GO script — this is where many quest objective scripts grant credit. Restructured so CMSG_GAMEOBJ_USE is sent first for all GO types, then chest-like GOs additionally send CMSG_LOOT, and REPORT_USE fires for everything except mailboxes. --- src/game/game_handler.cpp | 58 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 1362f5e9..e07aab41 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -6213,39 +6213,37 @@ void GameHandler::performGameObjectInteractionNow(uint64_t guid) { " entry=", goEntry, " type=", goType, " name='", goName, "' chestLike=", chestLike, " isMailbox=", isMailbox); + // Always send CMSG_GAMEOBJ_USE first — this triggers the server-side + // GameObject::Use() handler for all GO types. + auto usePacket = GameObjectUsePacket::build(guid); + socket->send(usePacket); + lastInteractedGoGuid_ = guid; + if (chestLike) { - // For chest-like GOs: send CMSG_GAMEOBJ_USE (opens the chest) followed - // immediately by CMSG_LOOT (requests loot contents). Both sent in the - // same frame so the server processes them sequentially: USE transitions - // the GO to lootable state, then LOOT reads the contents. - auto usePacket = GameObjectUsePacket::build(guid); - socket->send(usePacket); + // Chest-like GOs also need a CMSG_LOOT to open the loot window. + // Sent in the same frame: USE transitions the GO to lootable state, + // then LOOT requests the contents. lootTarget(guid); - lastInteractedGoGuid_ = guid; - } else { - // Non-chest GOs (doors, buttons, quest givers, etc.): use CMSG_GAMEOBJ_USE - auto packet = GameObjectUsePacket::build(guid); - socket->send(packet); - lastInteractedGoGuid_ = guid; + } else if (isMailbox) { + LOG_INFO("Mailbox interaction: opening mail UI and requesting mail list"); + mailboxGuid_ = guid; + mailboxOpen_ = true; + hasNewMail_ = false; + selectedMailIndex_ = -1; + showMailCompose_ = false; + refreshMailList(); + } - if (isMailbox) { - LOG_INFO("Mailbox interaction: opening mail UI and requesting mail list"); - mailboxGuid_ = guid; - mailboxOpen_ = true; - hasNewMail_ = false; - selectedMailIndex_ = -1; - showMailCompose_ = false; - refreshMailList(); - } - - // CMSG_GAMEOBJ_REPORT_USE for GO AI scripts (quest givers, etc.) - if (!isMailbox) { - const auto* table = getActiveOpcodeTable(); - if (table && table->hasOpcode(Opcode::CMSG_GAMEOBJ_REPORT_USE)) { - network::Packet reportUse(wireOpcode(Opcode::CMSG_GAMEOBJ_REPORT_USE)); - reportUse.writeUInt64(guid); - socket->send(reportUse); - } + // CMSG_GAMEOBJ_REPORT_USE triggers GO AI scripts (SmartAI, ScriptAI) which + // is where many quest objectives grant credit. Previously this was only sent + // for non-chest GOs, so chest-type quest objectives (Bundle of Wood, etc.) + // never triggered the server-side quest credit script. + if (!isMailbox) { + const auto* table = getActiveOpcodeTable(); + if (table && table->hasOpcode(Opcode::CMSG_GAMEOBJ_REPORT_USE)) { + network::Packet reportUse(wireOpcode(Opcode::CMSG_GAMEOBJ_REPORT_USE)); + reportUse.writeUInt64(guid); + socket->send(reportUse); } } }