diff --git a/include/game/packet_parsers.hpp b/include/game/packet_parsers.hpp index 41b4b9be..1b74c240 100644 --- a/include/game/packet_parsers.hpp +++ b/include/game/packet_parsers.hpp @@ -95,6 +95,11 @@ public: return InitialSpellsParser::parse(packet, data); } + /** Parse SMSG_CAST_FAILED */ + virtual bool parseCastFailed(network::Packet& packet, CastFailedData& data) { + return CastFailedParser::parse(packet, data); + } + /** 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); @@ -207,6 +212,7 @@ public: const MovementInfo& info, uint64_t playerGuid = 0) override; network::Packet buildCastSpell(uint32_t spellId, uint64_t targetGuid, uint8_t castCount) override; + bool parseCastFailed(network::Packet& packet, CastFailedData& data) override; bool parseMessageChat(network::Packet& packet, MessageChatData& data) override; bool parseGuildRoster(network::Packet& packet, GuildRosterData& data) override; bool parseGuildQueryResponse(network::Packet& packet, GuildQueryResponseData& data) override; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 04266f2d..f5543477 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -6570,7 +6570,9 @@ void GameHandler::handleInitialSpells(network::Packet& packet) { void GameHandler::handleCastFailed(network::Packet& packet) { CastFailedData data; - if (!CastFailedParser::parse(packet, data)) return; + bool ok = packetParsers_ ? packetParsers_->parseCastFailed(packet, data) + : CastFailedParser::parse(packet, data); + if (!ok) return; casting = false; currentCastSpellId = 0; diff --git a/src/game/packet_parsers_classic.cpp b/src/game/packet_parsers_classic.cpp index f17c6cac..5e6c5e6e 100644 --- a/src/game/packet_parsers_classic.cpp +++ b/src/game/packet_parsers_classic.cpp @@ -267,9 +267,9 @@ network::Packet ClassicPacketParsers::buildCastSpell(uint32_t spellId, uint64_t packet.writeUInt32(spellId); - // SpellCastTargets — vanilla uses uint16 target mask (not uint32 like WotLK) + // SpellCastTargets — vanilla/CMaNGOS uses uint32 target mask (same as WotLK) if (targetGuid != 0) { - packet.writeUInt16(0x02); // TARGET_FLAG_UNIT + packet.writeUInt32(0x02); // TARGET_FLAG_UNIT // Write packed GUID uint8_t mask = 0; @@ -289,12 +289,24 @@ network::Packet ClassicPacketParsers::buildCastSpell(uint32_t spellId, uint64_t packet.writeUInt8(bytes[i]); } } else { - packet.writeUInt16(0x00); // TARGET_FLAG_SELF + packet.writeUInt32(0x00); // TARGET_FLAG_SELF } return packet; } +// ============================================================================ +// Classic SMSG_CAST_FAILED: no castCount byte (added in TBC/WotLK) +// Format: spellId(u32) + result(u8) +// ============================================================================ +bool ClassicPacketParsers::parseCastFailed(network::Packet& packet, CastFailedData& data) { + data.castCount = 0; + data.spellId = packet.readUInt32(); + data.result = packet.readUInt8(); + LOG_INFO("[Classic] Cast failed: spell=", data.spellId, " result=", (int)data.result); + return true; +} + // ============================================================================ // Classic 1.12.1 parseCharEnum // Differences from TBC: @@ -437,16 +449,9 @@ bool ClassicPacketParsers::parseMessageChat(network::Packet& packet, MessageChat } } - // Vanilla/Classic: target GUID follows type-specific header for non-monster types - // (Monster types already read target/receiver in their switch case) - if (data.type != ChatType::MONSTER_SAY && - data.type != ChatType::MONSTER_YELL && - data.type != ChatType::MONSTER_EMOTE && - data.type != ChatType::CHANNEL) { - if (packet.getReadPos() + 12 <= packet.getSize()) { // 8 (guid) + 4 (msgLen) minimum - data.receiverGuid = packet.readUInt64(); - } - } + // Classic SAY/YELL/PARTY/GUILD/etc: NO second GUID before message. + // Only WHISPER_INFORM has a receiver GUID (same as sender for echo). + // Do NOT read an extra uint64 here — it would consume messageLen + message bytes. // Read message length uint32_t messageLen = packet.readUInt32();