mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-03 08:03:50 +00:00
game: add Classic 1.12 overrides for parseSpellStart and parseSpellGo
Vanilla 1.12 SMSG_SPELL_START and SMSG_SPELL_GO use: - PackedGuid (variable-length) for caster and target GUIDs, not full uint64 - uint16 castFlags, not uint32 as in TBC/WotLK - uint16 targetFlags in SpellCastTargets, not uint32 Without these overrides Classic inherited TBC's implementations which read 8 bytes for each GUID (over-reading the PackedGuid) and then 4 bytes for castFlags instead of 2, misaligning all subsequent fields and producing garbage spell IDs, cast times, and target GUIDs. Hit and miss target GUIDs in SMSG_SPELL_GO are also PackedGuid in Vanilla (vs full uint64 in TBC), handled by the new parseSpellGo.
This commit is contained in:
parent
c011d724c6
commit
5f06c18a54
2 changed files with 95 additions and 0 deletions
|
|
@ -405,6 +405,9 @@ public:
|
||||||
bool parseMonsterMove(network::Packet& packet, MonsterMoveData& data) override {
|
bool parseMonsterMove(network::Packet& packet, MonsterMoveData& data) override {
|
||||||
return MonsterMoveParser::parseVanilla(packet, data);
|
return MonsterMoveParser::parseVanilla(packet, data);
|
||||||
}
|
}
|
||||||
|
// Classic 1.12 uses PackedGuid (not full uint64) and uint16 castFlags (not uint32)
|
||||||
|
bool parseSpellStart(network::Packet& packet, SpellStartData& data) override;
|
||||||
|
bool parseSpellGo(network::Packet& packet, SpellGoData& data) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -314,6 +314,98 @@ network::Packet ClassicPacketParsers::buildUseItem(uint8_t bagIndex, uint8_t slo
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Classic parseSpellStart — Vanilla 1.12 SMSG_SPELL_START
|
||||||
|
//
|
||||||
|
// Key differences from TBC:
|
||||||
|
// - GUIDs are PackedGuid (variable-length byte mask + non-zero bytes),
|
||||||
|
// NOT full uint64 as in TBC/WotLK.
|
||||||
|
// - castFlags is uint16 (NOT uint32 as in TBC/WotLK).
|
||||||
|
// - SpellCastTargets uses uint16 targetFlags (NOT uint32 as in TBC).
|
||||||
|
//
|
||||||
|
// Format: PackedGuid(casterObj) + PackedGuid(casterUnit) + uint8(castCount)
|
||||||
|
// + uint32(spellId) + uint16(castFlags) + uint32(castTime)
|
||||||
|
// + uint16(targetFlags) [+ PackedGuid(unitTarget) if TARGET_FLAG_UNIT]
|
||||||
|
// ============================================================================
|
||||||
|
bool ClassicPacketParsers::parseSpellStart(network::Packet& packet, SpellStartData& data) {
|
||||||
|
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
|
||||||
|
if (rem() < 2) return false;
|
||||||
|
|
||||||
|
data.casterGuid = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
if (rem() < 1) return false;
|
||||||
|
data.casterUnit = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
|
||||||
|
// uint8 castCount + uint32 spellId + uint16 castFlags + uint32 castTime = 11 bytes
|
||||||
|
if (rem() < 11) return false;
|
||||||
|
data.castCount = packet.readUInt8();
|
||||||
|
data.spellId = packet.readUInt32();
|
||||||
|
data.castFlags = packet.readUInt16(); // uint16 in Vanilla (uint32 in TBC/WotLK)
|
||||||
|
data.castTime = packet.readUInt32();
|
||||||
|
|
||||||
|
// SpellCastTargets: uint16 targetFlags in Vanilla (uint32 in TBC/WotLK)
|
||||||
|
if (rem() < 2) return true;
|
||||||
|
uint16_t targetFlags = packet.readUInt16();
|
||||||
|
// TARGET_FLAG_UNIT (0x02) or TARGET_FLAG_OBJECT (0x800) carry a packed GUID
|
||||||
|
if (((targetFlags & 0x02) || (targetFlags & 0x800)) && rem() >= 1) {
|
||||||
|
data.targetGuid = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("[Classic] Spell start: spell=", data.spellId, " castTime=", data.castTime, "ms");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Classic parseSpellGo — Vanilla 1.12 SMSG_SPELL_GO
|
||||||
|
//
|
||||||
|
// Same GUID and castFlags format differences as parseSpellStart:
|
||||||
|
// - GUIDs are PackedGuid (not full uint64)
|
||||||
|
// - castFlags is uint16 (not uint32)
|
||||||
|
// - Hit/miss target GUIDs are also PackedGuid in Vanilla
|
||||||
|
//
|
||||||
|
// Format: PackedGuid(casterObj) + PackedGuid(casterUnit) + uint8(castCount)
|
||||||
|
// + uint32(spellId) + uint16(castFlags)
|
||||||
|
// + uint8(hitCount) + [PackedGuid(hitTarget) × hitCount]
|
||||||
|
// + uint8(missCount) + [PackedGuid(missTarget) + uint8(missType)] × missCount
|
||||||
|
// ============================================================================
|
||||||
|
bool ClassicPacketParsers::parseSpellGo(network::Packet& packet, SpellGoData& data) {
|
||||||
|
auto rem = [&]() { return packet.getSize() - packet.getReadPos(); };
|
||||||
|
if (rem() < 2) return false;
|
||||||
|
|
||||||
|
data.casterGuid = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
if (rem() < 1) return false;
|
||||||
|
data.casterUnit = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
|
||||||
|
// uint8 castCount + uint32 spellId + uint16 castFlags = 7 bytes
|
||||||
|
if (rem() < 7) return false;
|
||||||
|
data.castCount = packet.readUInt8();
|
||||||
|
data.spellId = packet.readUInt32();
|
||||||
|
data.castFlags = packet.readUInt16(); // uint16 in Vanilla (uint32 in TBC/WotLK)
|
||||||
|
|
||||||
|
// Hit targets
|
||||||
|
if (rem() < 1) return true;
|
||||||
|
data.hitCount = packet.readUInt8();
|
||||||
|
data.hitTargets.reserve(data.hitCount);
|
||||||
|
for (uint8_t i = 0; i < data.hitCount && rem() >= 1; ++i) {
|
||||||
|
data.hitTargets.push_back(UpdateObjectParser::readPackedGuid(packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Miss targets
|
||||||
|
if (rem() < 1) return true;
|
||||||
|
data.missCount = packet.readUInt8();
|
||||||
|
data.missTargets.reserve(data.missCount);
|
||||||
|
for (uint8_t i = 0; i < data.missCount && rem() >= 2; ++i) {
|
||||||
|
SpellGoMissEntry m;
|
||||||
|
m.targetGuid = UpdateObjectParser::readPackedGuid(packet);
|
||||||
|
if (rem() < 1) break;
|
||||||
|
m.missType = packet.readUInt8();
|
||||||
|
data.missTargets.push_back(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("[Classic] Spell go: spell=", data.spellId, " hits=", (int)data.hitCount,
|
||||||
|
" misses=", (int)data.missCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Classic SMSG_CAST_FAILED: no castCount byte (added in TBC/WotLK)
|
// Classic SMSG_CAST_FAILED: no castCount byte (added in TBC/WotLK)
|
||||||
// Format: spellId(u32) + result(u8)
|
// Format: spellId(u32) + result(u8)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue