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.
Focus (2, orange), Happiness (4, green), Runic Power (6, crimson), and
Soul Shards (7, purple) were falling through to the default blue colour.
Applied consistently to the player frame, target frame, and party frames.
When an aura has more than 1 charge, render the count in gold in the
upper-left corner of the icon (with drop shadow) — same position as WoW's
stack counter. Applied to both the player buff bar and target frame auras.
Polls the renderer's currentZoneName each frame and triggers a 5-second
fade-in/hold/fade-out toast at the upper-centre of screen when the zone
changes. Matches WoW's standard zone transition display.
Prefix each nameplate name with the unit's level number. When the unit
is more than 10 levels above the player (skull-equivalent) display '??'
instead of the raw level, matching WoW's UI convention.
For each visible Unit entity within 40 yards, projects the canonical WoW
position (converted to render space) through the camera view-projection
matrix to screen pixels. Draws a health bar (hostile=red, friendly=green,
target=gold border) and name label with drop shadow using ImGui's background
draw list. Fades out smoothly in the last 5 yards of range.
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.
Shows the name and health bar of whoever your current target is
targeting. Reads UNIT_FIELD_TARGET_LO/HI update fields which are
populated from SMSG_UPDATE_OBJECT. Frame is positioned below and
right-aligned with the main target frame.
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".
Matches the same fix applied to the player buff bar: icons in the
target frame now show their remaining duration at the icon bottom edge
with a drop shadow, shared between the always-visible overlay and the
hover tooltip.
Icons now show remaining time (e.g. "1:30", "45") rendered directly
on the icon bottom edge with a drop shadow, matching WoW's standard
buff display. Tooltip still shows full name + seconds on hover.
Deduplicates the nowMs/remainMs computation that was previously
recomputed in the tooltip-only path.
stopMusic(fadeMs) previously had (void)fadeMs with no fade logic.
Added fadingOut/fadeOutTimer/fadeOutDuration/fadeOutStartVolume state
and wired update() to interpolate volume to zero then stop playback.
Also clean up DuelProposedPacket comment (removed misleading TODO label).
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.
Add AmbientSoundManager::setZoneId() that maps WoW zone IDs to the
appropriate ZoneType (forest/grasslands/desert/jungle/marsh/beach) or
CityType (Stormwind/Ironforge/Darnassus/Orgrimmar/Undercity/ThunderBluff)
and delegates to setZoneType/setCityType. Call it from the renderer's
zone transition handler so zone ambience (looping sounds, city bells,
etc.) actually activates when the player enters a zone.
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.
In online mode, SMSG_INIT_WORLD_STATES delivers the server-authoritative
zone ID when entering a new area. Prefer this over the tile-based fallback
so music transitions are accurate for small zones (city districts, caves,
dungeon entrances) that don't align with 533-unit tile boundaries.
Call enrichFromDBC() again when loadOnlineWorld() sets cachedAssetManager,
so enrichment is guaranteed even when the asset manager was null at renderer
construction. enrichFromDBC() is idempotent (skips duplicate paths).
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.
These were declared to handle per-vertex WMO liquid height variation but
never actually used below — the surface is built with a flat adjustedZ
height throughout. Remove to eliminate -Wunused-variable warnings.
texture.hpp / texture.cpp implemented an unfinished OpenGL texture loader
(loadFromFile was a TODO stub) that had no callers — the project's texture
loading is entirely handled by VkTexture (vk_texture.hpp/cpp) after the
Vulkan migration. Remove both files and their CMakeLists entries.
Add ZoneManager::enrichFromDBC() which walks AreaTable.dbc (field 8 = ZoneMusicId)
→ ZoneMusic.dbc (fields 6/7 = day/night SoundEntryIds) → SoundEntries.dbc
(fields 3-12 = files, field 23 = DirectoryBase) and appends MPQ music paths for
all zones in the DBC, covering ~2300+ areas vs the previous ~15 hardcoded entries.
Existing hardcoded paths are preserved as the primary pool; DBC paths are added
only if not already present. Called from Renderer::init() after initialize().
Correct SoundEntries.dbc field access in the PlayMusic callback: file names are at
fields 3-12 (not 2-11) and DirectoryBase is at field 23 (not 22). Field 2 is the
Name label string, not a file path.
Remove dead detectVoiceType(creatureEntry) from NpcVoiceManager — it was never
called; actual voice detection uses detectVoiceTypeFromDisplayId() in Application.
Remove TODO comments from World::update() and World::loadMap() and
replace with explanatory comments. World is an intentional thin token;
the actual work happens in Application (TerrainManager, camera) and
GameHandler (packet processing). This reflects the current architecture
rather than implying missing work.
- 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
- Show up to 5 active quests with objective progress (kills, items, text)
- Gold title for complete quests, white for in-progress
- Item objectives show item name via getItemInfo() lookup
- Transparent semi-opaque background, docked below minimap on right
- 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