fix: correct SMSG_SPELL_COOLDOWN parsing for Classic 1.12 expansion

Classic 1.12 sends guid(8) + N×[spellId(4)+itemId(4)+cooldown(4)] with
no flags byte and 12 bytes per entry, while TBC/WotLK send guid(8)+
flags(1) + N×[spellId(4)+cooldown(4)] with 8 bytes per entry.

The previous parser always consumed the WotLK flags byte, which on
Classic servers would corrupt the first spell ID (reading one byte
into spellId) and misalign all subsequent entries. Fixed by detecting
isClassicLikeExpansion() and using the correct 12-byte-per-entry
format (skipping itemId) for Classic builds.
This commit is contained in:
Kelsi 2026-03-10 17:19:43 -07:00
parent 59597ff39e
commit 56588e0dad

View file

@ -13487,20 +13487,35 @@ void GameHandler::handleSpellGo(network::Packet& packet) {
}
void GameHandler::handleSpellCooldown(network::Packet& packet) {
SpellCooldownData data;
if (!SpellCooldownParser::parse(packet, data)) return;
// Classic 1.12: guid(8) + N×[spellId(4) + itemId(4) + cooldown(4)] — no flags byte, 12 bytes/entry
// TBC 2.4.3 / WotLK 3.3.5a: guid(8) + flags(1) + N×[spellId(4) + cooldown(4)] — 8 bytes/entry
const bool isClassicFormat = isClassicLikeExpansion();
if (packet.getSize() - packet.getReadPos() < 8) return;
/*data.guid =*/ packet.readUInt64(); // guid (not used further)
if (!isClassicFormat) {
if (packet.getSize() - packet.getReadPos() < 1) return;
/*data.flags =*/ packet.readUInt8(); // flags (consumed but not stored)
}
const size_t entrySize = isClassicFormat ? 12u : 8u;
while (packet.getSize() - packet.getReadPos() >= entrySize) {
uint32_t spellId = packet.readUInt32();
if (isClassicFormat) packet.readUInt32(); // itemId — consumed, not used
uint32_t cooldownMs = packet.readUInt32();
for (const auto& [spellId, cooldownMs] : data.cooldowns) {
float seconds = cooldownMs / 1000.0f;
spellCooldowns[spellId] = seconds;
// Update action bar cooldowns
for (auto& slot : actionBar) {
if (slot.type == ActionBarSlot::SPELL && slot.id == spellId) {
slot.cooldownTotal = seconds;
slot.cooldownTotal = seconds;
slot.cooldownRemaining = seconds;
}
}
}
LOG_DEBUG("handleSpellCooldown: parsed for ",
isClassicFormat ? "Classic" : "TBC/WotLK", " format");
}
void GameHandler::handleCooldownEvent(network::Packet& packet) {