diff --git a/include/game/packet_parsers.hpp b/include/game/packet_parsers.hpp index 03da989d..8885865e 100644 --- a/include/game/packet_parsers.hpp +++ b/include/game/packet_parsers.hpp @@ -110,6 +110,19 @@ public: return CastFailedParser::parse(packet, data); } + /** Parse SMSG_CAST_RESULT header (spellId + result), expansion-aware. + * WotLK: castCount(u8) + spellId(u32) + result(u8) + * TBC/Classic: spellId(u32) + result(u8) (no castCount prefix) + */ + virtual bool parseCastResult(network::Packet& packet, uint32_t& spellId, uint8_t& result) { + // WotLK default: skip castCount, read spellId + result + if (packet.getSize() - packet.getReadPos() < 6) return false; + packet.readUInt8(); // castCount + spellId = packet.readUInt32(); + result = packet.readUInt8(); + return true; + } + /** Parse SMSG_AURA_UPDATE / SMSG_AURA_UPDATE_ALL */ virtual bool parseAuraUpdate(network::Packet& packet, AuraUpdateData& data, bool isAll = false) { return AuraUpdateParser::parse(packet, data, isAll); @@ -307,6 +320,8 @@ public: bool parseMonsterMove(network::Packet& packet, MonsterMoveData& data) override; // TBC 2.4.3 SMSG_GOSSIP_MESSAGE quests lack questFlags(u32)+isRepeatable(u8) (WotLK added them) 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_MAIL_LIST_RESULT: uint8 count (not uint32+uint8), no body field, // attachment uses uint64 itemGuid (not uint32), enchants are 7×u32 id-only (not 7×{id+dur+charges}) bool parseMailList(network::Packet& packet, std::vector& inbox) override; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 0dfe66b7..86f83351 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -1742,28 +1742,28 @@ void GameHandler::handlePacket(network::Packet& packet) { } // ---- Cast result (WotLK extended cast failed) ---- - case Opcode::SMSG_CAST_RESULT: - // WotLK: uint8 castCount + uint32 spellId + uint8 result [+ optional extra] + case Opcode::SMSG_CAST_RESULT: { + // WotLK: castCount(u8) + spellId(u32) + result(u8) + // TBC/Classic: spellId(u32) + result(u8) (no castCount prefix) // If result == 0, the spell successfully began; otherwise treat like SMSG_CAST_FAILED. - if (packet.getSize() - packet.getReadPos() >= 6) { - /*uint8_t castCount =*/ packet.readUInt8(); - /*uint32_t spellId =*/ packet.readUInt32(); - uint8_t result = packet.readUInt8(); - if (result != 0) { - // Failure — clear cast bar and show message + uint32_t castResultSpellId = 0; + uint8_t castResult = 0; + if (packetParsers_->parseCastResult(packet, castResultSpellId, castResult)) { + if (castResult != 0) { casting = false; currentCastSpellId = 0; castTimeRemaining = 0.0f; - const char* reason = getSpellCastResultString(result, -1); + const char* reason = getSpellCastResultString(castResult, -1); MessageChatData msg; msg.type = ChatType::SYSTEM; msg.language = ChatLanguage::UNIVERSAL; msg.message = reason ? reason - : ("Spell cast failed (error " + std::to_string(result) + ")"); + : ("Spell cast failed (error " + std::to_string(castResult) + ")"); addLocalChatMessage(msg); } } break; + } // ---- Spell failed on another unit ---- case Opcode::SMSG_SPELL_FAILED_OTHER: diff --git a/src/game/packet_parsers_tbc.cpp b/src/game/packet_parsers_tbc.cpp index b4d803a9..b13ee058 100644 --- a/src/game/packet_parsers_tbc.cpp +++ b/src/game/packet_parsers_tbc.cpp @@ -977,6 +977,21 @@ bool TbcPacketParsers::parseMailList(network::Packet& packet, std::vector