Commit graph

648 commits

Author SHA1 Message Date
Kelsi
6e94a3345f Add upfront validation to CastFailedParser
SMSG_CAST_FAILED (3.3.5a) improvements:
- Validate 6-byte minimum for castCount + spellId + result
- Prevent reading from truncated packets

Ensures consistent error handling for spell failure feedback.
2026-03-11 14:35:29 -07:00
Kelsi
4f3e817913 Harden GossipMessageParser against malformed packets
SMSG_GOSSIP_MESSAGE (3.3.5a) improvements:
- Validate 20-byte minimum for npcGuid + menuId + titleTextId + optionCount
- Cap optionCount to 64 (prevents unbounded memory allocation)
- Validate 12-byte minimum before each option read (fixed fields + 2 strings)
- Cap questCount to 64 (prevents unbounded memory allocation)
- Validate 18-byte minimum before each quest read (fixed fields + title string)
- Graceful truncation with partial list support

Prevents DoS from servers sending malformed gossip menus with huge option/quest lists.
2026-03-11 14:34:20 -07:00
Kelsi
efc394ce9e Cap spell cooldown entries in SpellCooldownParser
SMSG_SPELL_COOLDOWN (3.3.5a) improvements:
- Validate 9-byte minimum for guid + flags
- Cap cooldown entries to 512 (each entry is 8 bytes: spellId + ms)
- Prevent unbounded memory allocation from malformed packets
- Log warning when cap is reached with remaining data ignored

Prevents DoS from servers sending malformed cooldown lists.
2026-03-11 14:33:02 -07:00
Kelsi
1d4f69add3 Harden combat log parsers against malformed packets
SMSG_ATTACKERSTATEUPDATE (3.3.5a) improvements:
- Validate 13-byte minimum for hitInfo + GUIDs + totalDamage + count
- Cap subDamageCount to 64 (each entry is 20 bytes)
- Validate 20-byte minimum before each sub-damage entry read
- Validate 8-byte minimum before victimState/overkill read
- Validate 4-byte minimum before blocked amount read (optional field)

SMSG_SPELLDAMAGELOG (3.3.5a) improvements:
- Validate 30-byte minimum for all required fields
- Validate core fields before reading (21-byte check)
- Validate trailing fields (10-byte check) before reading flags/crit

SMSG_SPELLHEALLOG (3.3.5a) improvements:
- Validate 21-byte minimum for all required fields
- Validate remaining fields (17-byte check) before reading heal data
- Graceful truncation with field initialization

Prevents DoS and undefined behavior from high-frequency combat log packets.
2026-03-11 14:32:03 -07:00
Kelsi
68b3cef0fe Harden AuraUpdateParser against malformed packets
WotLK SMSG_AURA_UPDATE (3.3.5a) improvements:
- Cap entry count to 512 (isAll) or 1 (single) to prevent unbounded loop DoS
- Validate 5-byte minimum before each slot+spellId read
- Validate 3-byte minimum before flags/level/charges read
- Validate space before casterGuid packed GUID read
- Validate 8-byte minimum before duration field reads
- Validate 4-byte minimum before each effect amount read
- Graceful truncation with field initialization and partial read support
- Log all truncation events with entry index information

Prevents DoS and undefined behavior from high-frequency aura update packets.
2026-03-11 14:30:57 -07:00
Kelsi
7034bc5f63 Cap hit/miss counts in Classic and TBC spell parsers
Add DoS protection to Classic and TBC parseSpellGo implementations:
- Cap hitCount and missCount to 128 each (prevents OOM from huge arrays)
- Track actual reads vs expected counts
- Log truncation warnings with index information
- Graceful truncation with count updates

Ensures consistent hardening across all expansion variants (Vanilla/TBC/WotLK).
2026-03-11 14:29:37 -07:00
Kelsi
164124783b Harden SpellStart and SpellGo parsers against malformed packets
WotLK SMSG_SPELL_START (3.3.5a) improvements:
- Validate 22-byte minimum for packed GUIDs + fixed fields
- Validate targetFlags read (4 bytes)
- Validate targetGuid packed read with size check

WotLK SMSG_SPELL_GO (3.3.5a) improvements:
- Validate 24-byte minimum for core fields
- Cap hitCount to 128 to prevent OOM from huge target lists
- Cap missCount to 128 with same protection
- In-loop validation: check 8 bytes before each hit GUID read
- In-loop validation: check 2 bytes minimum before each miss entry (packed GUID + type)
- Graceful truncation with partial read support and count updates

Prevents DoS and undefined behavior from servers sending malformed combat packets.
2026-03-11 14:28:41 -07:00
Kelsi
98739c1610 Harden NameQueryResponseParser against malformed packets
Add upfront and in-loop validation for the WotLK variant of name query responses:
- Validate packed GUID and found flag reads (minimum 2 bytes)
- Validate strings can be read before attempting parse
- Validate 3 final uint8 fields (race/gender/class) exist before reading
- Graceful truncation handling with field initialization

Prevents undefined behavior from servers sending truncated/malformed packets.
2026-03-11 14:27:39 -07:00
Kelsi
2f1b142e14 Add packet size validation to SMSG_CREATURE_QUERY_RESPONSE parsing
Improve robustness of creature query response parsing by adding defensive
size checks to both WotLK/TBC and Classic variants:

- WotLK/TBC (world_packets.cpp): Add upfront validation for entry field,
  validate minimum size (16 bytes) before reading fixed fields
  (typeFlags, creatureType, family, rank), graceful truncation handling
- Classic (packet_parsers_classic.cpp): Add upfront entry validation,
  enhance existing truncation check with default field initialization,
  improve logging consistency
- Both variants now initialize fields to 0 on truncation and log warnings
  with entry context

Part of ongoing Tier 2 work to improve multi-expansion packet parsing robustness
against malformed or truncated server packets.
2026-03-11 14:19:58 -07:00
Kelsi
e464300346 Add pointCount cap to SMSG_MONSTER_MOVE spline parsing
Improve robustness of monster move spline parsing by capping the pointCount
field to prevent excessive iteration from malformed or malicious packets.

- WotLK: Cap pointCount to 1000 waypoints (realistic maximum for movement)
- Vanilla (Turtle): Reduce existing cap from 16384 to 1000 and add warning
  logging when cap is applied
- Both variants now log warnings when cap is exceeded, including guid context

A malicious or corrupted server sending an unrealistic pointCount value (e.g.
uint32_max) could previously cause the client to allocate excessive memory or
iterate excessively. The 1000-waypoint cap aligns with realistic movement
paths while protecting against DoS vectors.

Part of ongoing Tier 2 work to improve multi-expansion packet parsing robustness.
2026-03-11 14:13:09 -07:00
Kelsi
73abbc2a08 Add packet size validation to SMSG_GAMEOBJECT_QUERY_RESPONSE parsing
Improve robustness of game object query response parsing by adding defensive
size checks to both WotLK/TBC and Classic variants:

- WotLK/TBC (world_packets.cpp): Add upfront validation for entry, type,
  displayId fields, and improved in-loop handling for variable-length data
  array with partial data graceful degradation
- Classic (packet_parsers_classic.cpp): Add upfront validation for entry,
  type, displayId fields, and enhanced in-loop data array read with
  truncation detection
- Both variants now log warnings when data fields are truncated

Part of ongoing Tier 2 work to improve multi-expansion packet parsing robustness
against malformed or truncated server packets.
2026-03-11 14:11:45 -07:00
Kelsi
d1414b6a46 Add packet size validation to SMSG_INITIAL_SPELLS parsing
Improve robustness of initial spells parsing by adding defensive size checks:

- Validate minimum packet size for header (talentSpec + spellCount)
- Cap spellCount to max 256 spells to prevent excessive iteration
- Add in-loop size checks for each spell entry before reading (4 bytes
  vanilla, 6 bytes TBC/WotLK)
- Validate minimum size for cooldownCount field (optional, gracefully
  handles truncation before it)
- Cap cooldownCount to max 256 cooldowns to prevent excessive iteration
- Add in-loop size checks for each cooldown entry before reading (14 bytes
  vanilla, 16 bytes TBC/WotLK)
- Log warnings on packet truncation with clear context

Applies to both vanilla format (Classic) and TBC/WotLK format variants.
Part of ongoing Tier 2 work to improve multi-expansion packet parsing
robustness against malformed or truncated server packets.
2026-03-11 14:10:20 -07:00
Kelsi
f472ee3be8 Add packet size validation to SMSG_ITEM_QUERY_SINGLE_RESPONSE parsing
Improve robustness of item query response parsing across all three expansions
by adding defensive size checks and bounds validation:

- WotLK (world_packets.cpp): Add upfront validation for fixed-size fields,
  bounds cap on statsCount (max 10), in-loop size checks for stat pairs,
  and improved logging for truncation detection
- Classic (packet_parsers_classic.cpp): Add upfront validation for fixed fields,
  in-loop checks for 10 fixed stat pairs and 5 damage entries, and graceful
  truncation handling
- TBC (packet_parsers_tbc.cpp): Add upfront validation, statsCount bounds cap,
  and in-loop size checks for variable-length stats and fixed damage entries

All changes are backward compatible and log warnings on packet truncation.
This is part of ongoing Tier 2 work to improve multi-expansion packet parsing
robustness against malformed or truncated server packets.
2026-03-11 14:08:59 -07:00
Kelsi
d7e1a3773c Add validation caps and in-loop size checks to gossip message parsing
Improve gossip message parser robustness by:
- Adding count caps (max 256 options/quests) to prevent excessive memory allocation
- Adding in-loop size validation to detect truncated packets
- Gracefully breaking loops instead of reading garbage when packet runs out
- Logging warnings when packet truncation is detected

Applies to both Classic and TBC parseGossipMessage implementations.
Part of Tier 1/2 work to improve parser robustness across multi-expansion support.
2026-03-11 13:56:16 -07:00
Kelsi
d14f82cb7c Add packet size validation to character enum and movement parsing
Improve parser robustness by adding defensive size checks to prevent reading
beyond packet boundaries. Specifically:

- parseCharEnum (Classic/TBC): Add packet size validation and character count cap
  (max 32 chars) to prevent truncated packets from silently parsing garbage data
- parseMovementBlock (Classic/TBC): Add early validation for minimum packet size
  before reading updateFlags to catch empty packets early
- All changes are backward compatible and log warnings on truncation

This is part of Tier 1/2 work to improve multi-expansion packet parsing robustness
and prevent undefined behavior from malformed or truncated server packets.
2026-03-11 13:55:20 -07:00
Kelsi
593f06bdf7 fix: correct Classic/TBC loot packet format parsing (missing randomSuffix/randomPropId)
SMSG_LOOT_START_ROLL, SMSG_LOOT_ALL_PASSED, and loot roll handlers unconditionally
read randomSuffix and randomPropertyId fields. These fields only exist in WotLK 3.3.5a
and NOT in Classic 1.12 / TBC 2.4.3, causing packet stream corruption on Classic/TBC servers.

Packet format differences:
- WotLK: includes randomSuffix (4) + randomPropId (4) fields
- Classic/TBC: no random property fields

Fix gates the field reads based on active expansion:
- SMSG_LOOT_START_ROLL: WotLK 33 bytes vs Classic/TBC 25 bytes
- SMSG_LOOT_ALL_PASSED: WotLK 24 bytes vs Classic/TBC 16 bytes
- SMSG_LOOT_ROLL: WotLK 34 bytes vs Classic/TBC 26 bytes
- SMSG_LOOT_ROLL_WON: WotLK 34 bytes vs Classic/TBC 26 bytes

This prevents packet stream desynchronization when loot rolls occur on Classic/TBC servers.
2026-03-11 05:09:43 -07:00
Kelsi
dd67c88175 fix: conditionally include trailing byte in CMSG_BUY_ITEM for Classic/TBC
CMSG_BUY_ITEM format differs by expansion:
- WotLK 3.3.5a / AzerothCore: includes trailing uint8(0) after count field (17 bytes)
- Classic 1.12 / TBC 2.4.3: no trailing byte (16 bytes)

The static BuyItemPacket::build() helper always adds the byte (AzerothCore compat).
GameHandler::buyItem() now gates the byte based on active expansion, allowing
Classic/TBC servers to receive correctly-sized packets.
2026-03-11 04:49:18 -07:00
Kelsi
ed48a3c425 fix: replace fragile heuristic in SMSG_INITIAL_SPELLS with explicit Classic format flag
Classic 1.12 uses uint16 spellId + uint16 slot (4 bytes/spell); TBC and WotLK
use uint32 spellId + uint16 unknown (6 bytes/spell). The old size-based heuristic
could misdetect TBC packets that happened to fit both layouts. Add a vanillaFormat
parameter to InitialSpellsParser::parse and override parseInitialSpells in
ClassicPacketParsers to always pass true, eliminating the ambiguity.
2026-03-11 04:38:30 -07:00
Kelsi
9d0da6242d fix: correct Classic/TBC MSG_MOVE_TELEPORT_ACK movement info parsing
Classic 1.12 and TBC 2.4.3 movement packets omit the moveFlags2 (uint16)
field present in WotLK 3.3.5a. The prior handler unconditionally read 2 bytes
for moveFlags2, shifting the timestamp and position reads by 2 bytes and
producing garbage coordinates after a teleport. Now gated by expansion.
2026-03-11 04:32:00 -07:00
Kelsi
d3241dce9e fix: handle Classic 1.12 SMSG_WEATHER missing isAbrupt byte
Classic 1.12 sends weatherType(4)+intensity(4) with no trailing isAbrupt byte;
TBC/WotLK append uint8 isAbrupt. The prior check required >= 9 bytes, so weather
never updated on Classic servers. Now accept >= 8 bytes and read isAbrupt only if
the byte is present.
2026-03-11 04:25:00 -07:00
Kelsi
fed03f970c fix: correct SMSG_BATTLEFIELD_STATUS Classic 1.12 packet layout
Classic uses queueSlot(4)+bgTypeId(4)+unk(2)+instanceId(4)+isReg(1)+statusId(4);
TBC/WotLK prefixes arenaType(1)+unk(1) before bgTypeId. Reading TBC format on
Classic caused bgTypeId to be read from wrong offset, corrupting BG queue state.
2026-03-11 04:22:18 -07:00
Kelsi
8493729a10 fix: use uint16 spellId in Classic 1.12 SMSG_LEARNED/REMOVED/SUPERCEDED_SPELL
Classic 1.12 (vmangos/cmangos) sends uint16 spellIds in SMSG_LEARNED_SPELL,
SMSG_REMOVED_SPELL, and SMSG_SUPERCEDED_SPELL. TBC 2.4.3 and WotLK 3.3.5a
use uint32. The handlers were unconditionally reading uint32, causing the
first byte of the next field to be consumed as part of the spellId on
Classic, producing garbage spell IDs and breaking known-spell tracking.

Apply the same Classic/TBC+WotLK gate used by the SMSG_INITIAL_SPELLS
heuristic: read uint16 for Classic, uint32 for all others.
2026-03-11 04:08:16 -07:00
Kelsi
750b270502 fix: use expansion-aware item size in LootResponseParser for Classic/TBC
The previous per-iteration heuristic (remaining >= 22 → 22 bytes, >= 14 → 14 bytes)
incorrectly parsed Classic/TBC multi-item loots: 2+ items × 14 bytes would
trigger the 22-byte WotLK path for the first item, corrupting subsequent items.

Classic 1.12 and TBC 2.4.3 use 14 bytes/item (slot+itemId+count+displayInfo+slotType).
WotLK 3.3.5a uses 22 bytes/item (adds randomSuffix+randomPropertyId).

Add isWotlkFormat bool parameter to LootResponseParser::parse and pass
isActiveExpansion('wotlk') from handleLootResponse.
2026-03-11 04:01:07 -07:00
Kelsi
dd7d74cb93 fix: correct SMSG_SPELL_FAILURE Classic format and result enum shift
Classic 1.12 SMSG_SPELL_FAILURE omits the castCount byte that TBC/WotLK
include (format: uint64 GUID + uint32 spellId + uint8 failReason).
The previous code read a castCount for all expansions, misaligning
spellId and failReason for Classic by one byte.

Also apply the same +1 enum shift used in parseCastFailed/parseCastResult:
Classic result 0=AFFECTING_COMBAT maps to WotLK 1=AFFECTING_COMBAT,
so Classic failReason=0 now correctly shows an error instead of being
silently swallowed.
2026-03-11 03:54:33 -07:00
Kelsi
d6e398d814 fix: add Classic parseCastResult override with result enum +1 shift
Classic 1.12 SMSG_CAST_RESULT uses an enum starting at 0=AFFECTING_COMBAT
(no SUCCESS entry), while WotLK starts at 0=SUCCESS, 1=AFFECTING_COMBAT.
Without this override, Classic result codes were handled by TBC's
parseCastResult which passed them unshifted, causing result 0
(AFFECTING_COMBAT) to be silently treated as success with no error shown.

This applies the same +1 shift used in parseCastFailed so all Classic
spell failure codes map correctly to getSpellCastResultString.
2026-03-11 03:53:18 -07:00
Kelsi
2f0809b570 fix: correct TBC aura entry minimum-size guard from 13 to 15 bytes
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Each SMSG_INIT/SET_EXTRA_AURA_INFO entry is 15 bytes:
  uint8 slot(1) + uint32 spellId(4) + uint8 effectIndex(1)
  + uint8 flags(1) + uint32 durationMs(4) + uint32 maxDurMs(4) = 15

The previous guard of 13 would allow the loop to start reading a
partial entry, silently returning zeroes for durationMs/maxDurMs
when 13-14 bytes remained in the packet.
2026-03-11 03:49:54 -07:00
Kelsi
144c87a72f feat: show spell failure reason in chat from SMSG_SPELL_FAILURE
SMSG_SPELL_FAILURE carries a failReason byte (same enum as SMSG_CAST_RESULT)
that was previously ignored. Now parse castCount+spellId+failReason and
display the localized reason string for the player's interrupted casts
(e.g. 'Interrupted', 'Stunned', 'Can\'t do that while moving').
2026-03-11 03:42:41 -07:00
Kelsi
1446d4fddd fix: pass player power type to getSpellCastResultString for result 85
Result 85 is 'not enough power' — the message should say 'Not enough
rage', 'Not enough energy', 'Not enough runic power', etc. based on
the player's actual power type rather than always showing 'Not enough
mana'.
2026-03-11 03:41:49 -07:00
Kelsi
84a6ee4801 fix: surface absorb/resist in SMSG_ENVIRONMENTAL_DAMAGE_LOG (Classic/TBC)
The Classic/TBC variant handler was discarding the resisted field entirely
(only reading absorbed but discarding it). Now reads and shows both as
ABSORB/RESIST combat text, matching the WotLK SMSG_ENVIRONMENTALDAMAGELOG
fix from the previous commit.
2026-03-11 03:40:41 -07:00
Kelsi
00db93b7f2 fix: show RESIST (not MISS) for SMSG_PROCRESIST combat text
SMSG_PROCRESIST is sent when a proc effect is resisted. Show 'Resisted'
rather than 'Miss' to correctly communicate what happened to the player.
2026-03-11 03:38:39 -07:00
Kelsi
fb01361837 feat: show blocked amount and reduced damage on VICTIMSTATE_BLOCKS
When an attack is partially blocked, the server sends the remaining
damage in totalDamage and the blocked amount in data.blocked. Show
both: the damage taken and a 'Block N' entry. When block amount is
zero (full block with no damage), just show 'Block'.
2026-03-11 03:36:45 -07:00
Kelsi
d1c5e09127 fix: correct SMSG_PERIODICAURALOG packet format for WotLK 3.3.5a
WotLK adds an overkill(4) field between damage and school for aura type
3/89 (periodic damage), and adds absorbed(4)+isCrit(1) after overHeal
for aura type 8/124/45 (periodic heal). Without these fields the absorb
and resist values were reading out-of-alignment, producing garbage data.

Also surfaces the heal-absorbed amount as ABSORB combat text (e.g. when
a HoT tick is partially absorbed by Vampiric Embrace counter-healing).
2026-03-11 03:34:27 -07:00
Kelsi
f50cb04887 feat: surface absorb/resist from SMSG_ENVIRONMENTALDAMAGELOG
Environmental damage (drowning, lava, fire) also carries absorb/resist
fields. Show these as ABSORB/RESIST combat text so players see the full
picture of incoming environmental hits, consistent with spell/melee.
2026-03-11 03:31:33 -07:00
Kelsi
031448ec6d feat: show absorb/resist on periodic damage (DoT) ticks
SMSG_PERIODICAURALOG already parsed abs/res fields for type 3/89 but
discarded them. Surface these as ABSORB/RESIST combat text so players
see when DoT ticks are being partially absorbed (e.g. vs. PW:Shield).
2026-03-11 03:30:24 -07:00
Kelsi
dfc78572f5 feat: show melee absorb/resist in combat text from SMSG_ATTACKERSTATEUPDATE
Sub-damage entries carry absorbed/resisted per school. Accumulate these
and emit ABSORB/RESIST combat text alongside the hit damage when nonzero,
matching the behavior just added for SMSG_SPELLNONMELEEDAMAGELOG.
2026-03-11 03:29:37 -07:00
Kelsi
d2ae4d8215 feat: show partial absorb/resist amounts in spell combat text
handleSpellDamageLog now emits ABSORB/RESIST entries when data.absorbed
or data.resisted are nonzero, so players see 'Absorbed 123' alongside
damage numbers (e.g. vs. Power Word: Shield or Ice Barrier).
handleSpellHealLog does the same for heal absorbs (e.g. Vampiric Embrace
counter-absorbs). renderCombatText now formats amount when nonzero.
2026-03-11 03:28:19 -07:00
Kelsi
e902375763 feat: add ABSORB and RESIST combat text types for spell misses
Adds dedicated CombatTextEntry::Type entries for ABSORB (miss type 7)
and RESIST (miss type 8), replacing the generic MISS display. Updates
missTypes arrays in SMSG_SPELLLOGMISS and SMSG_SPELL_GO, and adds
light-blue "Absorb" and grey "Resist" rendering in the combat text overlay.
2026-03-11 03:23:01 -07:00
Kelsi
d5196abaec fix: show IMMUNE text for miss type 5 in SMSG_SPELL_GO and SMSG_SPELLLOGMISS
IMMUNE misses (spell miss type 5) were shown as generic MISS text in both
spell cast feedback handlers. Now consistently shows IMMUNE combat text
to match the fix already applied to SMSG_ATTACKERSTATEUPDATE.
2026-03-11 03:13:14 -07:00
Kelsi
35683920ff fix: handle EVADE/IMMUNE/DEFLECT victimStates in melee combat text
SMSG_ATTACKERSTATEUPDATE victimState values 5 (EVADE), 6 (IMMUNE), and
7 (DEFLECT) were previously falling through to the damage display path,
showing incorrect damage numbers instead of the proper miss/immune feedback.
Now correctly shows MISS for evade/deflect and IMMUNE for immune hits.
2026-03-11 03:09:39 -07:00
Kelsi
1646bef1c2 fix: add size guards to spell learn/remove handlers and implement SMSG_SPELLSTEALLOG
handleLearnedSpell, handleRemovedSpell, handleSupercededSpell, and
handleUnlearnSpells all lacked size checks before reading packet fields.
Also implements SMSG_SPELLSTEALLOG (previously silently consumed) with
proper player feedback showing the stolen spell name when the local player
is the caster, matching the same expansion-conditional packed-guid format
as SPELLDISPELLOG.
2026-03-11 03:03:44 -07:00
Kelsi
ae6c2aa056 fix: correct SMSG_SPELLDISPELLOG entry size from 8 to 5 bytes
Each dispelled spell entry is uint32(spellId) + uint8(isPositive) = 5 bytes,
not uint32 + uint32 = 8 bytes as the loop previously assumed.

The incorrect stride caused the second and subsequent entries to be read at
wrong offsets, potentially showing the wrong spell name for multi-dispels.
2026-03-11 02:57:05 -07:00
Kelsi
603e52e5b0 fix: add size check and skip WotLK guid suffix in handleCooldownEvent
SMSG_COOLDOWN_EVENT in WotLK appends an 8-byte unit guid after the spellId.
The handler was reading without a size check and not consuming the trailing
guid, which could misalign subsequent reads.
2026-03-11 02:51:58 -07:00
Kelsi
0a17683545 fix: correct WotLK packed guid format in SMSG_PROCRESIST and SMSG_TOTEM_CREATED
Both opcodes use packed GUIDs in WotLK 3.3.5a but were reading full uint64,
causing incorrect GUID parsing and potentially matching wrong player entities.

SMSG_PROCRESIST: caster + victim guids (packed in WotLK, uint64 in TBC/Classic)
SMSG_TOTEM_CREATED: totem guid (packed in WotLK, uint64 in TBC/Classic)
2026-03-11 02:50:53 -07:00
Kelsi
9cd7e7978d fix: correct SMSG_DISPEL_FAILED packet format and improve message
WotLK sends spellId(4) + packed_guid caster + packed_guid victim, while
TBC/Classic sends full uint64 caster + uint64 victim + spellId(4).
The previous handler assumed TBC format unconditionally, causing incorrect
reads in WotLK mode.

Also use the spell name cache to display "Purge failed to dispel." rather
than a raw "Dispel failed! (spell N)" message.
2026-03-11 02:49:37 -07:00
Kelsi
1f4880985b fix: correct SMSG_SPELLLOGMISS packet format for all expansions
All expansions send spellId(4) before the caster guid — the previous
handler was missing this field entirely, causing the caster guid read
to consume spellId bytes and corrupt all subsequent parsing.

Additionally, in WotLK mode, victim guids inside the per-miss loop are
packed guids (not full uint64), matching the caster guid format.

Also handle the REFLECT (missInfo=11) extra payload in WotLK: the server
appends reflectSpellId(4) + reflectResult(1) for reflected spells, which
previously caused the following loop entries to be mis-parsed.
2026-03-11 02:47:15 -07:00
Kelsi
d696da9227 fix: also use school mask for pre-cast melee range/facing check in castSpell()
Same DBC-driven physical school detection replaces the brittle hardcoded
warrior spell list in the pre-cast range check, so rogue, DK, paladin,
feral druid, and hunter melee abilities get correct range/facing enforcement.
2026-03-11 02:40:27 -07:00
Kelsi
21c55ad6b4 fix: detect melee abilities via spell school mask instead of hardcoded spell ID list
Replace the brittle warrior-only hardcoded spell ID list for melee ability
detection with a DBC-driven check: physical school mask (1) from spellNameCache_
covers warrior, rogue, DK, paladin, feral druid, and all other physical-school
instant abilities generically. Instant detection: spellId != currentCastSpellId.
2026-03-11 02:39:25 -07:00
Kelsi
643d48ee89 fix: show reason-specific messages for SMSG_TRANSFER_ABORTED
Replace generic 'Transfer aborted' message with WotLK TRANSFER_ABORT_*
reason codes: difficulty, expansion required, instance full, too many
instances, zone in combat, etc.
2026-03-11 02:36:55 -07:00
Kelsi
3082df2ac0 fix: use packed guids in SMSG_SPELLDAMAGESHIELD for WotLK and read absorbed field
WotLK 3.3.5a format uses packed guids (not full uint64) for victim and caster,
and adds an absorbed(4) field before schoolMask. Classic/TBC use full uint64 guids.
Previously the handler always read full uint64 guids, causing misparse on WotLK
(e.g. Thorns and Shield Spike damage shield combat text was garbled/wrong).
2026-03-11 02:27:57 -07:00
Kelsi
c4b2089d31 fix: handle OBS_MOD_POWER and PERIODIC_ENERGIZE aura types in SMSG_PERIODICAURALOG
Add PERIODIC_ENERGIZE (91) and OBS_MOD_POWER (46) handling so mana/energy/rage
restore ticks from common WotLK auras (Replenishment, Mana Spring Totem, Divine
Plea, etc.) appear as ENERGIZE in floating combat text. Also handle PERIODIC_MANA_LEECH
(98) to properly consume its 12 bytes instead of halting mid-event parse.
2026-03-11 02:25:42 -07:00