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
- SMSG_HEALTH_UPDATE / SMSG_POWER_UPDATE: update entity HP/power via entityManager
- SMSG_UPDATE_WORLD_STATE: single world state variable update (companion to INIT)
- SMSG_UPDATE_COMBO_POINTS: store comboPoints_/comboTarget_ in GameHandler
- SMSG_START_MIRROR_TIMER / SMSG_STOP_MIRROR_TIMER / SMSG_PAUSE_MIRROR_TIMER: breath/fatigue/feign timer state
- MirrorTimer struct + getMirrorTimer() public getter; renderMirrorTimers() draws colored breath/fatigue bars above cast bar
- SMSG_CAST_RESULT: WotLK extended cast result; clear cast bar and show reason on failure (result != 0)
- SMSG_SPELL_FAILED_OTHER / SMSG_PROCRESIST: consume silently
- SMSG_LOOT_START_ROLL: correct trigger for Need/Greed popup (replaces rollType=128 heuristic)
- SMSG_STABLE_RESULT: show pet stable feedback in system chat (store/retrieve/buy slot/error)
- SMSG_TITLE_EARNED: system chat notification for title earned/removed
- SMSG_PLAYERBOUND / SMSG_BINDER_CONFIRM: hearthstone binding notification
- SMSG_SET_PHASE_SHIFT: consume (WotLK phasing, no client action needed)
- SMSG_TOGGLE_XP_GAIN: system chat notification
- SMSG_DISPEL_FAILED: parse caster/victim/spellId, show "Dispel failed!" chat
- SMSG_TOTEM_CREATED: parse slot/guid/duration/spellId, log (no totem bar yet)
- SMSG_AREA_SPIRIT_HEALER_TIME: show "resurrect in N seconds" message
- SMSG_DURABILITY_DAMAGE_DEATH: show durability loss notification on death
- Parse SMSG_ITEM_TEXT_QUERY_RESPONSE (guid + isEmpty + string text),
store in itemText_ and open book window when non-empty
- queryItemText(guid) sends CMSG_ITEM_TEXT_QUERY for readable items
- renderItemTextWindow(): scrollable book window with parchment-toned
text, "Close" button; opens via isItemTextOpen() flag
- Parse SMSG_QUEST_CONFIRM_ACCEPT (questId + title + sharerGuid),
show chat notification with quest title and sharer name
- acceptSharedQuest() sends CMSG_QUEST_CONFIRM_ACCEPT with questId
- renderSharedQuestPopup(): shows sharer name, gold quest title,
Accept/Decline buttons (stacked below other social popups)
- SMSG_SERVER_MESSAGE: parse type+string, show as [Server] chat message
- SMSG_CHAT_SERVER_MESSAGE: parse type+string, show as [Announcement]
- SMSG_AREA_TRIGGER_MESSAGE: parse len+string, display as system chat
- SMSG_TRIGGER_CINEMATIC: consume silently (no cinematic playback)
- Parse SMSG_LOOT_ROLL: if rollType==128 and it's our player, store
pending roll (itemId, slot, name from itemInfoCache_) and show popup;
otherwise show chat notification of another player's roll result
- Parse SMSG_LOOT_ROLL_WON: show winner announcement in chat with item
name and roll type/value
- sendLootRoll() sends CMSG_LOOT_ROLL (objectGuid+slot+rollType) and
clears pending roll state
- SMSG_LOOT_MASTER_LIST consumed silently (no UI yet)
- renderLootRollPopup(): ImGui window with Need/Greed/Disenchant/Pass
buttons; item name colored by quality (poor/common/uncommon/rare/epic/
legendary color scale)
- Parse SMSG_DUEL_REQUESTED: store challenger guid/name, set
pendingDuelRequest_ flag, show chat notification
- Parse SMSG_DUEL_COMPLETE: clear pending flag, notify on cancel
- Parse SMSG_DUEL_WINNER: show "X defeated Y in a duel!" chat message
- Handle SMSG_DUEL_OUTOFBOUNDS with warning message
- Add acceptDuel() method sending CMSG_DUEL_ACCEPTED (new builder)
- Wire forfeitDuel() to clear pendingDuelRequest_ on decline
- Add renderDuelRequestPopup() ImGui window (Accept/Decline buttons)
positioned near group invite popup; shown when challenge is pending
- Add DuelAcceptPacket builder to world_packets.hpp/cpp
- Parse SMSG_ACHIEVEMENT_EARNED (guid + achievementId + PackedTime date)
and fire AchievementEarnedCallback for self, chat notify for others
- Add renderAchievementToast() to GameScreen: slides in from right,
gold-bordered panel with "Achievement Earned!" title + ID, 5s duration
with 0.4s slide-in/out animation and fade at end
- Add triggerAchievementToast(uint32_t) public method on GameScreen
- Wire AchievementEarnedCallback in application.cpp
- Add playAchievementAlert() to UiSoundManager, loads
Sound\Interface\AchievementSound.wav with level-up fallback
- SMSG_ALL_ACHIEVEMENT_DATA silently consumed (no tracker UI yet)
- Add renderDungeonFinderWindow() with status display (not queued /
role check / queued+wait time / proposal / in dungeon / finished)
- Role checkboxes (Tank/Healer/DPS) and dungeon combo (25 entries
covering Vanilla, TBC, and WotLK including Random/Heroic)
- Accept/Decline buttons during Proposal state, Teleport button
while InDungeon, Leave Queue button while Queued/RoleCheck
- Store lfgProposalId_ on GameHandler so UI can pass it to
lfgAcceptProposal(); expose getLfgProposalId() and
getLfgTimeInQueueMs() getters
- Toggle window with I key (when chat input is not active)
SMSG_CLEAR_COOLDOWN: remove spell cooldown from cache and clear action bar
slot's remaining cooldown immediately (e.g. after item use, trinket proc).
SMSG_MODIFY_COOLDOWN: adjust an existing cooldown duration by a signed delta
in milliseconds (used by glyphs, Borrowed Time, etc.).
- SMSG_INSTANCE_SAVE_CREATED: notify player they are saved to instance
- SMSG_RAID_INSTANCE_MESSAGE: surface warning/save/welcome notifications
- SMSG_INSTANCE_RESET: clear matching lockout from cache + notify
- SMSG_INSTANCE_RESET_FAILED: report reset failure reason to player
- SMSG_INSTANCE_LOCK_WARNING_QUERY: auto-confirm with CMSG_INSTANCE_LOCK_RESPONSE
(entering a saved instance; sends acceptance so the player can proceed)
Parse and store dungeon/raid lockout data sent on login:
- mapId, difficulty, resetTime (Unix timestamp), locked, extended flags
- Stored in instanceLockouts_ vector for UI / LFG / dungeon state queries
- Public InstanceLockout struct + getInstanceLockouts() accessor