From 7270a4e6900e0295befe14a7ee63dd4085234da8 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 10 Mar 2026 01:30:06 -0700 Subject: [PATCH] game: fix TBC 2.4.3 SMSG_CAST_FAILED missing parseCastFailed override TBC 2.4.3 SMSG_CAST_FAILED format is spellId(u32) + result(u8), same as Classic. WotLK added a castCount(u8) prefix before spellId. TbcPacketParsers lacked a parseCastFailed override, so it fell through to the WotLK base which read one extra byte as castCount, shifting the spellId read by one byte and corrupting the spell ID and result for every failed cast on TBC. - Add TbcPacketParsers::parseCastFailed override: reads spellId(4)+result(1) - ClassicPacketParsers already overrides this (enum shift +1), so Classic unaffected --- include/game/packet_parsers.hpp | 2 ++ src/game/packet_parsers_tbc.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/game/packet_parsers.hpp b/include/game/packet_parsers.hpp index 8413002c..03fc502e 100644 --- a/include/game/packet_parsers.hpp +++ b/include/game/packet_parsers.hpp @@ -332,6 +332,8 @@ public: bool parseGossipMessage(network::Packet& packet, GossipMessageData& data) override; // TBC 2.4.3 SMSG_CAST_RESULT: spellId(u32) + result(u8) — WotLK added castCount(u8) prefix bool parseCastResult(network::Packet& packet, uint32_t& spellId, uint8_t& result) override; + // TBC 2.4.3 SMSG_CAST_FAILED: spellId(u32) + result(u8) — WotLK added castCount(u8) prefix + bool parseCastFailed(network::Packet& packet, CastFailedData& data) override; // TBC 2.4.3 SMSG_SPELL_START: full uint64 GUIDs (WotLK uses packed GUIDs) bool parseSpellStart(network::Packet& packet, SpellStartData& data) override; // TBC 2.4.3 SMSG_SPELL_GO: full uint64 GUIDs, no timestamp field (WotLK added one) diff --git a/src/game/packet_parsers_tbc.cpp b/src/game/packet_parsers_tbc.cpp index db9d007b..5cef0290 100644 --- a/src/game/packet_parsers_tbc.cpp +++ b/src/game/packet_parsers_tbc.cpp @@ -1080,6 +1080,24 @@ bool TbcPacketParsers::parseCastResult(network::Packet& packet, uint32_t& spellI return true; } +// ============================================================================ +// TbcPacketParsers::parseCastFailed — TBC 2.4.3 SMSG_CAST_FAILED +// +// TBC format: spellId(u32) + result(u8) +// WotLK added castCount(u8) before spellId; reading it on TBC would shift +// the spellId by one byte and corrupt all subsequent fields. +// Classic has the same layout, but the result enum starts differently (offset +1); +// TBC uses the same result values as WotLK so no offset is needed. +// ============================================================================ +bool TbcPacketParsers::parseCastFailed(network::Packet& packet, CastFailedData& data) { + if (packet.getSize() - packet.getReadPos() < 5) return false; + data.castCount = 0; // not present in TBC + data.spellId = packet.readUInt32(); + data.result = packet.readUInt8(); // same enum as WotLK + LOG_DEBUG("[TBC] Cast failed: spell=", data.spellId, " result=", (int)data.result); + return true; +} + // ============================================================================ // TbcPacketParsers::parseAttackerStateUpdate — TBC 2.4.3 SMSG_ATTACKERSTATEUPDATE //