AuraUpdateParser and InitialSpellsParser were called as static functions
in the game handler, bypassing the expansion-specific overrides added to
TbcPacketParsers. Switch them to packetParsers_->parseAuraUpdate() and
packetParsers_->parseInitialSpells() so TBC 2.4.3 servers get the correct
parser for each.
Add TbcPacketParsers::parseSpellHealLog override using full uint64 GUIDs
(TBC) instead of packed GUIDs (WotLK). Route handleAttackerStateUpdate,
handleSpellDamageLog, and handleSpellHealLog through the virtual
packetParsers_ interface so expansion-specific overrides are actually
called. Previously the game handler bypassed virtual dispatch with
direct static parser calls, making all three TBC overrides dead code.
Add AudioEngine::playSound2DStoppable() + stopSound() so callers can
hold a handle and cancel playback early. SpellSoundManager::playPrecast()
now stores the handle in activePrecastId_; stopPrecast() cuts the sound.
playCast() calls stopPrecast() before playing the release sound, so the
channeling audio never bleeds past cast time. SMSG_SPELL_FAILURE and
SMSG_CAST_FAILED both call stopPrecast() so interrupted casts silence
immediately.
SMSG_LOOT_LIST, SMSG_COMPLAIN_RESULT, SMSG_ITEM_REFUND_INFO_RESPONSE,
and SMSG_ITEM_ENCHANT_TIME_UPDATE were incorrectly falling through to the
SMSG_RESUME_CAST_BAR handler, causing those packets to be parsed as
cast bar resume data with a completely different wire format.
- Parse uint64 killerGuid + uint64 victimGuid
- Resolve names from playerNameCache (players) and entity manager (NPCs)
- Show "[Killer] killed [Victim]." as system chat when both names are known
- Parse uint8 itemClass + uint32 subClassMask from SMSG_SET_PROFICIENCY
- Store weaponProficiency_ (itemClass=2) and armorProficiency_ (itemClass=4)
- Expose getWeaponProficiency(), getArmorProficiency(), canUseWeaponSubclass(n),
canUseArmorSubclass(n) on GameHandler for use by equipment UI
- Enables future equipment slot validation (grey out non-proficient items)
- SMSG_SPELLDISPELLOG: parse packed caster/victim + dispel spell + isStolen +
dispelled spell list; show system message when player dispels or has a buff
dispelled/stolen (e.g. "Shadow Word: Pain was dispelled." / "You dispelled Renew.")
- SMSG_SPELLSTEALLOG: separated from SPELLDISPELLOG consume group with comment
explaining the relationship (same wire format, player-facing covered by SPELLDISPELLOG)
- SMSG_SPELLDAMAGESHIELD: parse victim/caster/damage fields and show SPELL_DAMAGE
combat text for player-relevant events (damage shields like Thorns)
- SMSG_SPELLORDAMAGE_IMMUNE: parse packed caster/victim guids and show new
IMMUNE combat text type when player is involved in an immunity event
- Add CombatTextEntry::IMMUNE type to spell_defines.hpp and render it as
white "Immune!" in the combat text overlay
- handleCompressedMoves: add MSG_MOVE_* routing so SMSG_MULTIPLE_MOVES
sub-packets (player movement batches) are dispatched to handleOtherPlayerMovement
instead of logged as unhandled; fix runtime-opcode lookup (non-static array)
- SMSG_RESUME_CAST_BAR: parse packed_guid caster/target + spellId + remainingMs +
totalMs; restores cast bar state when server re-syncs a cast in progress
- SMSG_THREAT_UPDATE: properly consume packed_guid host/target + threat entries
to suppress unhandled packet warnings
- SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT: track up to 5 boss encounter unit guids
per slot; expose via getEncounterUnitGuid(slot); clear on world transfer
These guids identify active boss units for raid/boss frame display.
These two opcodes were accidentally falling through to the PERIODICAURALOG
handler which expects packed_guid+packed_guid+uint32+uint32 — wrong format.
Now:
- SMSG_SPELL_DELAYED: parse caster guid + delayMs, extend castTimeRemaining
on player cast pushback (spell cast bar stays accurate under pushback)
- SMSG_EQUIPMENT_SET_SAVED: simple acknowledge log (no payload needed)
- SMSG_MULTIPLE_MOVES uses the same uint8-size+uint16-opcode format as
SMSG_COMPRESSED_MOVES; route it to handleCompressedMoves() so bundled
monster movement updates are processed instead of dropped
- SMSG_PROCRESIST: parse caster/victim GUIDs and show MISS combat text
when the player's proc was resisted by an enemy spell
- Play SpellSoundManager::playImpact() with correct school when the player
is hit by another unit's spell (SMSG_SPELL_GO hitTargets check)
- Show achievement name in SMSG_SERVER_FIRST_ACHIEVEMENT notifications
using the already-loaded achievementNameCache_
- playImpact was fully implemented but never called; now wired up
Previously "Achievement earned! (ID 1234)" was the only message. Now
loadAchievementNameCache() lazily loads Achievement.dbc (field 4 = Title,
verified against WotLK 3.3.5a binary) on first earned event and shows
"Achievement earned: Level 10" or "Player has earned the achievement: ..."
Falls back to ID if DBC is unavailable or entry is missing.
Parse the flight-master POI status packet (guid + uint8 status) and cache
it per-NPC in taxiNpcHasRoutes_. Exposes taxiNpcHasRoutes(guid) accessor
for future nameplate/interaction indicators. Previously this packet was
silently consumed without any state tracking.
Previously all player spell casts played ARCANE school sounds regardless
of the actual spell school. Now loadSpellNameCache() reads SchoolMask
(bitmask, TBC/WotLK) or SchoolEnum (Vanilla/Classic) from Spell.dbc and
stores it in SpellNameEntry. handleSpellStart/handleSpellGo look up the
spell's school and select the correct MagicSchool for cast sounds.
DBC field indices: WotLK SchoolMask=225 (verified), TBC=215, Classic/Turtle
SchoolEnum=1 (Vanilla enum 0-6 converted to bitmask).
- Parse bundled sub-packets from SMSG_MULTIPLE_PACKETS using the WotLK
standard wire format (uint16_be size + uint16_le opcode + payload),
dispatching each through handlePacket() instead of silently discarding.
Rate-limited warning for malformed sub-packet overruns.
- Remove unused cullRadiusSq variable in TerrainRenderer::renderShadow()
that produced a -Wunused-variable warning.
Parse SMSG_RESYNC_RUNES, SMSG_ADD_RUNE_POWER, and SMSG_CONVERT_RUNE to
track the state of all 6 DK runes (Blood/Unholy/Frost/Death type,
ready flag, and cooldown fraction). Render a six-square rune bar below
the Runic Power bar when the player is class 6, with per-type colors
(Blood=red, Unholy=green, Frost=blue, Death=purple) and client-side
fill animation so runes visibly refill over the 10s cooldown.
WotLK 3.3.5a sends a raw uint64 victim GUID in this packet, not a
packed GUID. Update the handler format to match (uint64 + uint8 type
+ uint32 damage + uint32 absorb). Remove the now-dead SMSG_ENVIRONMENTALDAMAGELOG
handler since the opcode alias always routes to SMSG_ENVIRONMENTAL_DAMAGE_LOG.
- Implement SMSG_ENVIRONMENTAL_DAMAGE_LOG: show fall/lava/fire/drowning
damage as ENVIRONMENTAL combat text (orange -N) for the local player
- Color nameplate unit names: hostile units red, non-hostile yellow
(matches WoW's standard red=enemy / yellow=neutral convention)
XP gain was previously shown as a HEAL entry (green +N) which conflates
it with actual healing. New XP_GAIN type renders as purple '+N XP' in the
outgoing column, matching WoW's floating XP style.
Block rolls previously fell through to the damage case and were shown as
a 0-damage hit. Now correctly emitted as a BLOCK combat text entry, which
renderCombatText already handles with 'Block' / 'You Block' label.
Parse SPELLENERGIZELOG (victim/caster packed GUIDs + spellId + powerType +
amount) and emit ENERGIZE combat text for mana/energy gains. Add ENERGIZE
to CombatTextEntry::Type enum (blue +N text).
Also add explicit renderCombatText cases for BLOCK, PERIODIC_DAMAGE,
PERIODIC_HEAL, and ENVIRONMENTAL — previously all fell through to the
colourless default handler.
SMSG_SPELLENERGIZELOG, SMSG_ENVIRONMENTAL_DAMAGE_LOG, and
SMSG_SET_PROFICIENCY were incorrectly grouped with the
SMSG_ACTION_BUTTONS case block introduced in the previous commit,
causing their payloads to be misinterpreted as action button data
which could corrupt the action bar. Each now safely consumes
its packet.
Previously the 144-button server payload was silently dropped.
Now parses the first 12 buttons (one bar) and populates the local
action bar with server-side spells and items. Macros and unknown
button types are skipped. Empty/zero slots are preserved as-is to
avoid wiping hardcoded Attack/Hearthstone defaults.
Previously all periodic aura ticks were silently discarded.
Now parses victim/caster GUIDs, auraType, and damage/heal value
for the two most common types (PERIODIC_DAMAGE=3 and PERIODIC_HEAL=8)
and generates PERIODIC_DAMAGE/PERIODIC_HEAL combat text entries.
Falls back safely to consume-all on unknown aura types.
Previously the packet was silently consumed. Some servers send
SMSG_REALM_SPLIT during login and expect a CMSG_REALM_SPLIT
acknowledgement, otherwise they may time out the session.
Responds with splitType echoed back and patchVersion "3.3.5".
SMSG_BINDER_CONFIRM confirms the bind point was set. Previously silently
consumed; now shows "This innkeeper is now your home location." in system
chat so the player gets feedback after using an innkeeper.
Server sends periodic game time corrections via SMSG_GAMETIME_SET and
SMSG_GAMETIME_UPDATE (uint32 gameTimePacked). SMSG_GAMESPEED_SET also
sends an updated timeSpeed float. Applying these keeps gameTime_/timeSpeed_
in sync with the server, preventing day/night drift in the sky renderer
over long play sessions.
Add PlayPositionalSoundCallback that carries both soundId and sourceGuid.
In Application, look up the source entity position and play via
AudioEngine::playSound3D(); fall back to playSound2D() when the entity
is unknown. Also read the 8-byte sourceGuid field from the packet
(previously the full 12-byte payload was ignored).
Both opcodes send uint32 soundId as first field. Extend PlaySoundCallback to
cover them so environmental object sounds and spell impact sounds are audible
in-game (resolved through SoundEntries.dbc → AudioEngine::playSound2D).
Add PlaySoundCallback to GameHandler (same pattern as PlayMusicCallback).
When SMSG_PLAY_SOUND arrives, resolve the soundId through SoundEntries.dbc
(fields 3-12 = files, field 23 = DirectoryBase) and play the first found
file as a 2-D sound effect via AudioEngine::playSound2D(). Previously the
opcode was parsed and dropped.
- Add Escape Menu → Instance Lockouts button opening a new panel
that lists active lockouts with instance name (from Map.dbc),
difficulty, time-until-reset countdown, and locked/extended status.
map name lookup is cached on first open.
- Fix uninitialized ChatType in sendChatMessage (default to SAY)
- Remove unused startWorld variable in handleMonsterMoveTransport
- Remove unused modelCached variable in spawnOnlineCreature
Eliminates all -Wunused-but-set-variable and -Wmaybe-uninitialized
warnings in the main translation units.
Add PlayMusicCallback to GameHandler so SMSG_PLAY_MUSIC (and the
vanilla 0x0103 alias) dispatch a soundId to the registered handler
instead of being silently consumed. Application.cpp registers the
callback, loads SoundEntries.dbc, resolves the first non-empty
Name+DirectoryBase into an MPQ path, and passes it to MusicManager
for non-looping playback. Resolves the TODO in the SMSG_PLAY_MUSIC
handler.
- Send CMSG_QUERY_QUESTS_COMPLETED on initial world entry so
completedQuests_ is populated from the server response
- Clear completedQuests_ on world entry to avoid stale data across sessions
- Add isQuestCompleted(questId) and getCompletedQuests() public accessors
to allow UI layers to filter NPC quest offers by completion state
- SMSG_ITEM_QUERY_MULTIPLE_RESPONSE: route to handleItemQueryResponse
- SMSG_QUERY_OBJECT_POSITION/ROTATION: consume
- SMSG_VOICESESSION_FULL: consume
All non-trivial, non-debug SMSG opcodes now have explicit case handlers.
- SMSG_DEFENSE_MESSAGE: display PvP zone attack alerts in system chat
- SMSG_CORPSE_RECLAIM_DELAY: notify player of corpse reclaim timer
- SMSG_DEATH_RELEASE_LOC: log spirit healer coordinates after death
- SMSG_ENABLE_BARBER_SHOP: log barber shop activation (no UI yet)
- SMSG_FEIGN_DEATH_RESISTED: show resisted feign death message
- SMSG_CHANNEL_MEMBER_COUNT: consume channel member count update
- SMSG_GAMETIME_SET/UPDATE/BIAS, SMSG_GAMESPEED_SET: consume server time sync
- SMSG_ACHIEVEMENT_DELETED/CRITERIA_DELETED: consume removal notifications
- Fix unused screenH variable warning in quest objective tracker
- SMSG_CHAT_PLAYER_NOT_FOUND: show "No player named X is currently playing" in chat
- SMSG_CHAT_PLAYER_AMBIGUOUS: show ambiguous name message
- SMSG_CHAT_WRONG_FACTION/NOT_IN_PARTY/RESTRICTED: appropriate chat error messages
- SMSG_THREAT_CLEAR: log threat wipe (Vanish, Feign Death)
- SMSG_THREAT_REMOVE: consume packed GUIDs
- SMSG_HIGHEST_THREAT_UPDATE: consume (no threat UI yet)
- SMSG_GROUP_DESTROYED: clear party members and notify player
- SMSG_GROUP_CANCEL: notify player that invite was cancelled
- SMSG_SPLINE_MOVE_*: consume packed GUID for 10 entity movement state flag opcodes
- SMSG_WORLD_STATE_UI_TIMER_UPDATE: consume server timestamp (arena/BG timer sync)
- SMSG_PVP_CREDIT: log honor gain and show chat notification
- SMSG_BUY_ITEM: log successful purchase and clear pending buy state
- SMSG_CRITERIA_UPDATE: log achievement criteria progress (no UI yet)
- SMSG_BARBER_SHOP_RESULT: show success/failure message in chat
- SMSG_OVERRIDE_LIGHT: store zone light override id + transition time, expose via getOverrideLightId()/getOverrideLightTransMs()
- Add Reputation tab in character screen tab bar (Equipment/Stats/Reputation/Skills)
- Implement renderReputationPanel() showing all tracked factions sorted alphabetically
- Progress bars colored per WoW reputation tier: Hated/Hostile/Unfriendly/Neutral/Friendly/Honored/Revered/Exalted
- Add public getFactionNamePublic() backed by DBC name cache with lazy load
- Implement renderReadyCheckPopup() showing initiator name with Ready/Not Ready buttons
- Fix MSG_RAID_READY_CHECK fallback: use partyData.leaderGuid instead of non-existent isLeader field
- Add faction standing handler with loadFactionNameCache() (Faction.dbc field 22)
- Add gossip POI handler writing canonical WoW coords to gossipPois_ for minimap rendering
- SMSG_GOSSIP_POI: parse map POI markers (x/y/icon/name) from quest NPCs, render as
cyan diamonds on the minimap with hover tooltips for quest navigation
- SMSG_ATTACKSWING_DEADTARGET: clear auto-attack when target dies mid-swing
- SMSG_CANCEL_COMBAT: server-side combat reset (clears autoAttacking + target)
- SMSG_BREAK_TARGET / SMSG_CLEAR_TARGET: server-side targeting clears
- SMSG_DISMOUNT: server-forced dismount triggers mountCallback(0)
- SMSG_MOUNTRESULT / SMSG_DISMOUNTRESULT: mount feedback in system chat
- SMSG_LOOT_ALL_PASSED: "Everyone passed on [Item]" system message, clears loot roll
- SMSG_LOOT_ITEM_NOTIFY / SMSG_LOOT_SLOT_CHANGED: consumed
- SMSG_SPELLLOGMISS: decode miss/dodge/parry/block from spell casts into combat text
- SMSG_ENVIRONMENTALDAMAGELOG: environmental damage (drowning/lava/fall) in combat text
- GossipPoi struct + gossipPois_ vector in GameHandler with public getters/clearers