From d8ab69f9c32658f4e8267cfa6f68e5689cfac470 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 20 Feb 2026 01:13:01 -0800 Subject: [PATCH] Fix stale opcode mappings and handler wiring across expansions --- Data/expansions/classic/opcodes.json | 46 ++++++++++++++++++++- Data/expansions/tbc/opcodes.json | 58 ++++++++++++++++++++++++++- Data/expansions/turtle/opcodes.json | 17 ++++++-- Data/expansions/wotlk/opcodes.json | 60 ++++++++++++++++++++++++++-- include/game/opcode_table.hpp | 6 ++- include/game/world_packets.hpp | 2 +- src/game/game_handler.cpp | 12 ++++-- src/game/opcode_table.cpp | 4 +- src/game/world_packets.cpp | 8 ++-- 9 files changed, 190 insertions(+), 23 deletions(-) diff --git a/Data/expansions/classic/opcodes.json b/Data/expansions/classic/opcodes.json index e5387453..025ea4f5 100644 --- a/Data/expansions/classic/opcodes.json +++ b/Data/expansions/classic/opcodes.json @@ -159,6 +159,7 @@ "CMSG_QUESTGIVER_STATUS_QUERY": "0x182", "SMSG_QUESTGIVER_STATUS": "0x183", "CMSG_QUESTGIVER_HELLO": "0x184", + "SMSG_QUESTGIVER_QUEST_LIST": "0x185", "CMSG_QUESTGIVER_QUERY_QUEST": "0x186", "SMSG_QUESTGIVER_QUEST_DETAILS": "0x188", "CMSG_QUESTGIVER_ACCEPT_QUEST": "0x189", @@ -180,7 +181,7 @@ "CMSG_SELL_ITEM": "0x1A0", "SMSG_SELL_ITEM": "0x1A1", "CMSG_BUY_ITEM": "0x1A2", - "CMSG_BUYBACK_ITEM": "0x1A6", + "CMSG_BUYBACK_ITEM": "0x290", "SMSG_BUY_FAILED": "0x1A5", "CMSG_TRAINER_LIST": "0x1B0", "SMSG_TRAINER_LIST": "0x1B1", @@ -242,5 +243,46 @@ "SMSG_CHANNEL_NOTIFY": "0x099", "CMSG_CHANNEL_LIST": "0x09A", "SMSG_CHANNEL_LIST": "0x09B", - "SMSG_DUEL_REQUESTED": "0x167" + + "SMSG_INIT_WORLD_STATES": "0x2C2", + "SMSG_INITIALIZE_FACTIONS": "0x122", + "SMSG_CLIENT_CONTROL_UPDATE": "0x159", + "SMSG_WEATHER": "0x2F4", + "SMSG_AI_REACTION": "0x13C", + "SMSG_PLAY_SPELL_VISUAL": "0x1F3", + "SMSG_CANCEL_AUTO_REPEAT": "0x29C", + + "SMSG_SPLINE_MOVE_SET_WALK_MODE": "0x30E", + "SMSG_SPLINE_MOVE_SET_RUN_MODE": "0x30D", + "SMSG_SPLINE_MOVE_SET_RUN_SPEED": "0x2FE", + "SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED": "0x2FF", + "SMSG_SPLINE_MOVE_SET_SWIM_SPEED": "0x300", + + "SMSG_QUESTUPDATE_ADD_ITEM": "0x19A", + + "CMSG_GUILD_DISBAND": "0x08F", + "CMSG_GUILD_LEADER": "0x090", + "CMSG_GUILD_SET_PUBLIC_NOTE": "0x234", + "CMSG_GUILD_SET_OFFICER_NOTE": "0x235", + + "CMSG_BANKER_ACTIVATE": "0x1B7", + "SMSG_SHOW_BANK": "0x1B8", + "CMSG_BUY_BANK_SLOT": "0x1B9", + "SMSG_BUY_BANK_SLOT_RESULT": "0x1BA", + "CMSG_AUTOSTORE_BANK_ITEM": "0x282", + "CMSG_AUTOBANK_ITEM": "0x283", + + "MSG_AUCTION_HELLO": "0x255", + "CMSG_AUCTION_SELL_ITEM": "0x256", + "CMSG_AUCTION_REMOVE_ITEM": "0x257", + "CMSG_AUCTION_LIST_ITEMS": "0x258", + "CMSG_AUCTION_LIST_OWNER_ITEMS": "0x259", + "CMSG_AUCTION_PLACE_BID": "0x25A", + "SMSG_AUCTION_COMMAND_RESULT": "0x25B", + "SMSG_AUCTION_LIST_RESULT": "0x25C", + "SMSG_AUCTION_OWNER_LIST_RESULT": "0x25D", + "SMSG_AUCTION_BIDDER_NOTIFICATION": "0x25E", + "SMSG_AUCTION_OWNER_NOTIFICATION": "0x25F", + "CMSG_AUCTION_LIST_BIDDER_ITEMS": "0x264", + "SMSG_AUCTION_BIDDER_LIST_RESULT": "0x265" } diff --git a/Data/expansions/tbc/opcodes.json b/Data/expansions/tbc/opcodes.json index e4e4a435..d0c17cd6 100644 --- a/Data/expansions/tbc/opcodes.json +++ b/Data/expansions/tbc/opcodes.json @@ -80,7 +80,7 @@ "SMSG_GUILD_COMMAND_RESULT": "0x093", "MSG_RAID_READY_CHECK": "0x322", "MSG_RAID_READY_CHECK_CONFIRM": "0x3AE", - "CMSG_DUEL_PROPOSED": "0x166", + "SMSG_ITEM_PUSH_RESULT": "0x166", "CMSG_DUEL_ACCEPTED": "0x16C", "CMSG_DUEL_CANCELLED": "0x16D", "SMSG_DUEL_REQUESTED": "0x167", @@ -161,6 +161,7 @@ "SMSG_QUESTGIVER_STATUS": "0x183", "SMSG_QUESTGIVER_STATUS_MULTIPLE": "0x417", "CMSG_QUESTGIVER_HELLO": "0x184", + "SMSG_QUESTGIVER_QUEST_LIST": "0x185", "CMSG_QUESTGIVER_QUERY_QUEST": "0x186", "SMSG_QUESTGIVER_QUEST_DETAILS": "0x188", "CMSG_QUESTGIVER_ACCEPT_QUEST": "0x189", @@ -269,5 +270,58 @@ "SMSG_CHANNEL_NOTIFY": "0x099", "CMSG_CHANNEL_LIST": "0x09A", "SMSG_CHANNEL_LIST": "0x09B", - "SMSG_INSPECT_TALENT": "0x3F3" + "SMSG_INSPECT_TALENT": "0x3F3", + + "SMSG_INIT_WORLD_STATES": "0x2C2", + "SMSG_INITIALIZE_FACTIONS": "0x122", + "SMSG_CLIENT_CONTROL_UPDATE": "0x159", + "SMSG_CONTACT_LIST": "0x067", + "SMSG_WEATHER": "0x2F4", + "SMSG_AI_REACTION": "0x13C", + "SMSG_PLAY_SPELL_VISUAL": "0x1F3", + "SMSG_CANCEL_AUTO_REPEAT": "0x29C", + + "SMSG_SPLINE_MOVE_SET_WALK_MODE": "0x30E", + "SMSG_SPLINE_MOVE_SET_RUN_MODE": "0x30D", + "SMSG_SPLINE_MOVE_SET_RUN_SPEED": "0x2FE", + "SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED": "0x2FF", + "SMSG_SPLINE_MOVE_SET_SWIM_SPEED": "0x300", + + "SMSG_QUESTUPDATE_ADD_ITEM": "0x19A", + "SMSG_QUEST_FORCE_REMOVE": "0x21E", + + "CMSG_GUILD_DISBAND": "0x08F", + "CMSG_GUILD_LEADER": "0x090", + "CMSG_GUILD_SET_PUBLIC_NOTE": "0x234", + "CMSG_GUILD_SET_OFFICER_NOTE": "0x235", + + "CMSG_BANKER_ACTIVATE": "0x1B7", + "SMSG_SHOW_BANK": "0x1B8", + "CMSG_BUY_BANK_SLOT": "0x1B9", + "SMSG_BUY_BANK_SLOT_RESULT": "0x1BA", + "CMSG_AUTOSTORE_BANK_ITEM": "0x282", + "CMSG_AUTOBANK_ITEM": "0x283", + + "CMSG_GUILD_BANKER_ACTIVATE": "0x3E5", + "CMSG_GUILD_BANK_QUERY_TAB": "0x3E6", + "SMSG_GUILD_BANK_LIST": "0x3E7", + "CMSG_GUILD_BANK_SWAP_ITEMS": "0x3E8", + "CMSG_GUILD_BANK_BUY_TAB": "0x3E9", + "CMSG_GUILD_BANK_UPDATE_TAB": "0x3EA", + "CMSG_GUILD_BANK_DEPOSIT_MONEY": "0x3EB", + "CMSG_GUILD_BANK_WITHDRAW_MONEY": "0x3EC", + + "MSG_AUCTION_HELLO": "0x255", + "CMSG_AUCTION_SELL_ITEM": "0x256", + "CMSG_AUCTION_REMOVE_ITEM": "0x257", + "CMSG_AUCTION_LIST_ITEMS": "0x258", + "CMSG_AUCTION_LIST_OWNER_ITEMS": "0x259", + "CMSG_AUCTION_PLACE_BID": "0x25A", + "SMSG_AUCTION_COMMAND_RESULT": "0x25B", + "SMSG_AUCTION_LIST_RESULT": "0x25C", + "SMSG_AUCTION_OWNER_LIST_RESULT": "0x25D", + "SMSG_AUCTION_BIDDER_NOTIFICATION": "0x25E", + "SMSG_AUCTION_OWNER_NOTIFICATION": "0x25F", + "CMSG_AUCTION_LIST_BIDDER_ITEMS": "0x264", + "SMSG_AUCTION_BIDDER_LIST_RESULT": "0x265" } diff --git a/Data/expansions/turtle/opcodes.json b/Data/expansions/turtle/opcodes.json index 9a9e1806..dab26819 100644 --- a/Data/expansions/turtle/opcodes.json +++ b/Data/expansions/turtle/opcodes.json @@ -40,8 +40,8 @@ "SMSG_COMPRESSED_UPDATE_OBJECT": "0x1F6", "SMSG_UNKNOWN_1F5": "0x1F5", "SMSG_MONSTER_MOVE_TRANSPORT": "0x2AE", - "SMSG_SPLINE_MOVE_SET_WALK_MODE": "0x30D", - "SMSG_SPLINE_MOVE_SET_RUN_MODE": "0x30E", + "SMSG_SPLINE_MOVE_SET_WALK_MODE": "0x30E", + "SMSG_SPLINE_MOVE_SET_RUN_MODE": "0x30D", "SMSG_SPLINE_MOVE_SET_RUN_SPEED": "0x2FE", "SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED": "0x2FF", "SMSG_SPLINE_MOVE_SET_SWIM_SPEED": "0x300", @@ -87,7 +87,7 @@ "SMSG_GUILD_EVENT": "0x092", "SMSG_GUILD_COMMAND_RESULT": "0x093", "MSG_RAID_READY_CHECK": "0x322", - "CMSG_DUEL_PROPOSED": "0x166", + "SMSG_ITEM_PUSH_RESULT": "0x166", "CMSG_DUEL_ACCEPTED": "0x16C", "CMSG_DUEL_CANCELLED": "0x16D", "SMSG_DUEL_REQUESTED": "0x167", @@ -171,6 +171,7 @@ "CMSG_QUESTGIVER_STATUS_QUERY": "0x182", "SMSG_QUESTGIVER_STATUS": "0x183", "CMSG_QUESTGIVER_HELLO": "0x184", + "SMSG_QUESTGIVER_QUEST_LIST": "0x185", "CMSG_QUESTGIVER_QUERY_QUEST": "0x186", "SMSG_QUESTGIVER_QUEST_DETAILS": "0x188", "CMSG_QUESTGIVER_ACCEPT_QUEST": "0x189", @@ -289,5 +290,13 @@ "SMSG_AUCTION_BIDDER_NOTIFICATION": "0x260", "CMSG_AUCTION_LIST_BIDDER_ITEMS": "0x264", "SMSG_AUCTION_BIDDER_LIST_RESULT": "0x265", - "SMSG_UNKNOWN_319": "0x319" + "SMSG_UNKNOWN_319": "0x319", + + "SMSG_CANCEL_AUTO_REPEAT": "0x29C", + "SMSG_WEATHER": "0x2F4", + "SMSG_QUESTUPDATE_ADD_ITEM": "0x19A", + "CMSG_GUILD_DISBAND": "0x08F", + "CMSG_GUILD_LEADER": "0x090", + "CMSG_GUILD_SET_PUBLIC_NOTE": "0x234", + "CMSG_GUILD_SET_OFFICER_NOTE": "0x235" } diff --git a/Data/expansions/wotlk/opcodes.json b/Data/expansions/wotlk/opcodes.json index d5a02f68..267f46e7 100644 --- a/Data/expansions/wotlk/opcodes.json +++ b/Data/expansions/wotlk/opcodes.json @@ -82,7 +82,7 @@ "SMSG_GUILD_COMMAND_RESULT": "0x093", "MSG_RAID_READY_CHECK": "0x322", "MSG_RAID_READY_CHECK_CONFIRM": "0x3AE", - "CMSG_DUEL_PROPOSED": "0x166", + "SMSG_ITEM_PUSH_RESULT": "0x166", "CMSG_DUEL_ACCEPTED": "0x16C", "CMSG_DUEL_CANCELLED": "0x16D", "SMSG_DUEL_REQUESTED": "0x167", @@ -167,6 +167,7 @@ "SMSG_QUESTGIVER_STATUS": "0x183", "SMSG_QUESTGIVER_STATUS_MULTIPLE": "0x418", "CMSG_QUESTGIVER_HELLO": "0x184", + "SMSG_QUESTGIVER_QUEST_LIST": "0x185", "CMSG_QUESTGIVER_QUERY_QUEST": "0x186", "SMSG_QUESTGIVER_QUEST_DETAILS": "0x188", "CMSG_QUESTGIVER_ACCEPT_QUEST": "0x189", @@ -219,7 +220,7 @@ "CMSG_CANCEL_MOUNT_AURA": "0x0375", "SMSG_SHOWTAXINODES": "0x01A9", "SMSG_ACTIVATETAXIREPLY": "0x01AE", - "SMSG_ACTIVATETAXIREPLY_ALT": "0x029D", + "SMSG_STANDSTATE_UPDATE": "0x29D", "SMSG_NEW_TAXI_PATH": "0x01AF", "CMSG_ACTIVATETAXIEXPRESS": "0x0312", "SMSG_BATTLEFIELD_PORT_DENIED": "0x014B", @@ -280,5 +281,58 @@ "CMSG_MAIL_DELETE": "0x249", "CMSG_MAIL_MARK_AS_READ": "0x247", "SMSG_RECEIVED_MAIL": "0x285", - "MSG_QUERY_NEXT_MAIL_TIME": "0x284" + "MSG_QUERY_NEXT_MAIL_TIME": "0x284", + + "SMSG_INIT_WORLD_STATES": "0x2C2", + "SMSG_INITIALIZE_FACTIONS": "0x122", + "SMSG_CLIENT_CONTROL_UPDATE": "0x159", + "SMSG_CONTACT_LIST": "0x067", + "SMSG_WEATHER": "0x2F4", + "SMSG_AI_REACTION": "0x13C", + "SMSG_PLAY_SPELL_VISUAL": "0x1F3", + "SMSG_CANCEL_AUTO_REPEAT": "0x29C", + + "SMSG_SPLINE_MOVE_SET_WALK_MODE": "0x30E", + "SMSG_SPLINE_MOVE_SET_RUN_MODE": "0x30D", + "SMSG_SPLINE_MOVE_SET_RUN_SPEED": "0x2FE", + "SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED": "0x2FF", + "SMSG_SPLINE_MOVE_SET_SWIM_SPEED": "0x300", + + "SMSG_QUESTUPDATE_ADD_ITEM": "0x19A", + "SMSG_QUEST_FORCE_REMOVE": "0x21E", + + "CMSG_GUILD_DISBAND": "0x08F", + "CMSG_GUILD_LEADER": "0x090", + "CMSG_GUILD_SET_PUBLIC_NOTE": "0x234", + "CMSG_GUILD_SET_OFFICER_NOTE": "0x235", + + "CMSG_BANKER_ACTIVATE": "0x1B7", + "SMSG_SHOW_BANK": "0x1B8", + "CMSG_BUY_BANK_SLOT": "0x1B9", + "SMSG_BUY_BANK_SLOT_RESULT": "0x1BA", + "CMSG_AUTOSTORE_BANK_ITEM": "0x282", + "CMSG_AUTOBANK_ITEM": "0x283", + + "CMSG_GUILD_BANKER_ACTIVATE": "0x3E6", + "CMSG_GUILD_BANK_QUERY_TAB": "0x3E7", + "SMSG_GUILD_BANK_LIST": "0x3E8", + "CMSG_GUILD_BANK_SWAP_ITEMS": "0x3E9", + "CMSG_GUILD_BANK_BUY_TAB": "0x3EA", + "CMSG_GUILD_BANK_UPDATE_TAB": "0x3EB", + "CMSG_GUILD_BANK_DEPOSIT_MONEY": "0x3EC", + "CMSG_GUILD_BANK_WITHDRAW_MONEY": "0x3ED", + + "MSG_AUCTION_HELLO": "0x255", + "CMSG_AUCTION_SELL_ITEM": "0x256", + "CMSG_AUCTION_REMOVE_ITEM": "0x257", + "CMSG_AUCTION_LIST_ITEMS": "0x258", + "CMSG_AUCTION_LIST_OWNER_ITEMS": "0x259", + "CMSG_AUCTION_PLACE_BID": "0x25A", + "SMSG_AUCTION_COMMAND_RESULT": "0x25B", + "SMSG_AUCTION_LIST_RESULT": "0x25C", + "SMSG_AUCTION_OWNER_LIST_RESULT": "0x25D", + "SMSG_AUCTION_OWNER_NOTIFICATION": "0x25F", + "SMSG_AUCTION_BIDDER_NOTIFICATION": "0x25E", + "CMSG_AUCTION_LIST_BIDDER_ITEMS": "0x264", + "SMSG_AUCTION_BIDDER_LIST_RESULT": "0x265" } diff --git a/include/game/opcode_table.hpp b/include/game/opcode_table.hpp index 274c15c5..1e17ed5b 100644 --- a/include/game/opcode_table.hpp +++ b/include/game/opcode_table.hpp @@ -139,8 +139,10 @@ enum class LogicalOpcode : uint16_t { MSG_RAID_READY_CHECK, MSG_RAID_READY_CHECK_CONFIRM, + // ---- Items ---- + SMSG_ITEM_PUSH_RESULT, + // ---- Duel ---- - CMSG_DUEL_PROPOSED, CMSG_DUEL_ACCEPTED, CMSG_DUEL_CANCELLED, SMSG_DUEL_REQUESTED, @@ -330,7 +332,7 @@ enum class LogicalOpcode : uint16_t { // ---- Taxi / Flight Paths ---- SMSG_SHOWTAXINODES, SMSG_ACTIVATETAXIREPLY, - SMSG_ACTIVATETAXIREPLY_ALT, + SMSG_STANDSTATE_UPDATE, SMSG_NEW_TAXI_PATH, CMSG_ACTIVATETAXIEXPRESS, diff --git a/include/game/world_packets.hpp b/include/game/world_packets.hpp index 0f3fbf6b..e682f023 100644 --- a/include/game/world_packets.hpp +++ b/include/game/world_packets.hpp @@ -1246,7 +1246,7 @@ public: // Combat and Trade // ============================================================ -/** CMSG_DUEL_PROPOSED packet builder */ +/** Duel request packet builder (implemented via CMSG_CAST_SPELL, spell 7266) */ class DuelProposedPacket { public: static network::Packet build(uint64_t targetGuid); diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index aef0a4c7..5275ac8f 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -1229,9 +1229,9 @@ void GameHandler::handlePacket(network::Packet& packet) { handleRandomRoll(packet); } break; - case Opcode::CMSG_DUEL_PROPOSED: - // Some servers reuse this wire value for an outbound server packet variant. - // Consume safely until we have a concrete parser. + case Opcode::SMSG_ITEM_PUSH_RESULT: + // Item received notification (new item in bags, loot, quest reward, etc.) + // TODO: parse and show "item received" UI notification packet.setReadPos(packet.getSize()); break; @@ -2247,9 +2247,13 @@ void GameHandler::handlePacket(network::Packet& packet) { handleShowTaxiNodes(packet); break; case Opcode::SMSG_ACTIVATETAXIREPLY: - case Opcode::SMSG_ACTIVATETAXIREPLY_ALT: handleActivateTaxiReply(packet); break; + case Opcode::SMSG_STANDSTATE_UPDATE: + // Server confirms stand state change (sit/stand/sleep/kneel) + // TODO: parse uint8 standState and update player entity + packet.setReadPos(packet.getSize()); + break; case Opcode::SMSG_NEW_TAXI_PATH: // Empty packet - server signals a new flight path was learned // The actual node details come in the next SMSG_SHOWTAXINODES diff --git a/src/game/opcode_table.cpp b/src/game/opcode_table.cpp index d62a4256..3cf822e7 100644 --- a/src/game/opcode_table.cpp +++ b/src/game/opcode_table.cpp @@ -119,7 +119,7 @@ static const OpcodeNameEntry kOpcodeNames[] = { {"SMSG_GUILD_COMMAND_RESULT", LogicalOpcode::SMSG_GUILD_COMMAND_RESULT}, {"MSG_RAID_READY_CHECK", LogicalOpcode::MSG_RAID_READY_CHECK}, {"MSG_RAID_READY_CHECK_CONFIRM", LogicalOpcode::MSG_RAID_READY_CHECK_CONFIRM}, - {"CMSG_DUEL_PROPOSED", LogicalOpcode::CMSG_DUEL_PROPOSED}, + {"SMSG_ITEM_PUSH_RESULT", LogicalOpcode::SMSG_ITEM_PUSH_RESULT}, {"CMSG_DUEL_ACCEPTED", LogicalOpcode::CMSG_DUEL_ACCEPTED}, {"CMSG_DUEL_CANCELLED", LogicalOpcode::CMSG_DUEL_CANCELLED}, {"SMSG_DUEL_REQUESTED", LogicalOpcode::SMSG_DUEL_REQUESTED}, @@ -264,7 +264,7 @@ static const OpcodeNameEntry kOpcodeNames[] = { {"CMSG_CANCEL_MOUNT_AURA", LogicalOpcode::CMSG_CANCEL_MOUNT_AURA}, {"SMSG_SHOWTAXINODES", LogicalOpcode::SMSG_SHOWTAXINODES}, {"SMSG_ACTIVATETAXIREPLY", LogicalOpcode::SMSG_ACTIVATETAXIREPLY}, - {"SMSG_ACTIVATETAXIREPLY_ALT", LogicalOpcode::SMSG_ACTIVATETAXIREPLY_ALT}, + {"SMSG_STANDSTATE_UPDATE", LogicalOpcode::SMSG_STANDSTATE_UPDATE}, {"SMSG_NEW_TAXI_PATH", LogicalOpcode::SMSG_NEW_TAXI_PATH}, {"CMSG_ACTIVATETAXIEXPRESS", LogicalOpcode::CMSG_ACTIVATETAXIEXPRESS}, {"SMSG_BATTLEFIELD_PORT_DENIED", LogicalOpcode::SMSG_BATTLEFIELD_PORT_DENIED}, diff --git a/src/game/world_packets.cpp b/src/game/world_packets.cpp index 8fa3767a..fe8db5d0 100644 --- a/src/game/world_packets.cpp +++ b/src/game/world_packets.cpp @@ -1885,9 +1885,11 @@ network::Packet RequestRaidInfoPacket::build() { // ============================================================ network::Packet DuelProposedPacket::build(uint64_t targetGuid) { - network::Packet packet(wireOpcode(Opcode::CMSG_DUEL_PROPOSED)); - packet.writeUInt64(targetGuid); - LOG_DEBUG("Built CMSG_DUEL_PROPOSED for target: 0x", std::hex, targetGuid, std::dec); + // TODO: Duels are initiated via CMSG_CAST_SPELL with spell 7266, + // not a dedicated CMSG_DUEL_PROPOSED opcode (which doesn't exist in WoW). + // For now, build a cast spell packet targeting the opponent. + auto packet = CastSpellPacket::build(7266, targetGuid, 0); + LOG_DEBUG("Built duel request (spell 7266) for target: 0x", std::hex, targetGuid, std::dec); return packet; }