- Route SMSG_UPDATE_OBJECT through polymorphic parsers for correct
vanilla format (uint8 updateFlags, 6 speeds vs WotLK uint16/9)
- Fix SMSG_DESTROY_OBJECT for vanilla (8 bytes, no isDeath field)
- Add MSG_MOVE_* handlers for other player movement relay
- Add ClassicPacketParsers::parseMessageChat with targetGuid read
and monster-type name handling
- Resolve chat sender names from player name cache before display
- Fix CSV DBC field 0 always treated as numeric ID (fixes 16+ garbled
Turtle CSVs including Map, AreaTable, Spell, CreatureDisplayInfo)
- Add CSV DBC validation: reject garbled CSVs (>80% zero IDs) and
fall back to binary DBC files
- Fix ItemDisplayInfo texture component field index (14+ not 15+)
for binary DBC with gender-aware suffix resolution
- Spawn other players as visible M2 models via creature callback
- Map name cache dedup prevents overwrites from duplicate CSV records
Replace hardcoded WotLK protocol constants with a data-driven architecture
supporting Classic 1.12.1, TBC 2.4.3, and WotLK 3.3.5a. Each expansion
has JSON profiles for opcodes, update fields, and DBC layouts, plus C++
polymorphic packet parsers for binary format differences (movement flags,
speed fields, transport data, spline format, char enum layout).
Key components:
- ExpansionRegistry: scans Data/expansions/*/expansion.json at startup
- OpcodeTable: logical enum <-> wire values loaded from JSON
- UpdateFieldTable: field indices loaded from JSON per expansion
- DBCLayout: schema-driven DBC field lookups replacing magic numbers
- PacketParsers: WotLK/TBC/Classic parsers with correct flag positions
- Multi-manifest AssetManager: layered manifests with priority ordering
- HDPackManager: overlay texture packs with expansion compatibility
- Auth screen expansion picker replacing hardcoded version dropdown
Transport System (Phases 1-7):
- Implement TransportManager with Catmull-Rom spline path interpolation
- Add WMO dynamic transforms for moving transport instances
- Implement player attachment via world position composition
- Add test transport with circular path around Stormwind harbor
- Add /transport board and /transport leave console commands
- Reuse taxi flight spline system and external follow camera mode
NPC Spawn Fixes:
- Add smart ocean spawn filter: blocks land creatures at high altitude over water (Z>50)
- Allow legitimate water creatures at sea level (Z≤50) to spawn correctly
- Fixes Elder Grey Bears, Highland Striders, and Plainscreepers spawning over ocean
- Snap online creatures to terrain height when valid ground exists
NpcManager Removal:
- Remove deprecated NpcManager (offline mode no longer supported)
- Delete npc_manager.hpp and npc_manager.cpp
- Simplify NPC animation callbacks to use only creatureInstances_ map
- Move NPC callbacks to game initialization in application.cpp
Water Rendering:
- Fix tile seam gaps caused by per-vertex wave randomization
- Add distance-based blending: seamless waves up close (<150u), grid effect far away (>400u)
- Smooth transition between seamless and grid modes (150-400 unit range)
- Preserves aesthetic grid pattern at horizon while eliminating gaps when swimming
Add complete Blizzard-style time-of-day lighting pipeline:
Spatial Volume System (Light.dbc):
- Light volumes with position + inner/outer radius
- Distance-based weighting with smoothstep falloff
- Multi-volume blending (top 2 with normalized weights)
- X,Z,Y coordinate handling + LIGHT_COORD_SCALE for ×36 quirk
- Smooth zone transitions without popping
Profile Selection (LightParams.dbc):
- Weather variants: clear/rain/underwater
- Links to 18 color + 6 float band curves per profile
- Block indexing: LightParamsID × 18/6 + channel
Time-of-Day Band Sampling (LightIntBand/LightFloatBand):
- Half-minutes format (0-2879) with time clamping
- Keyframe interpolation with midnight wrap
- Wrap-safe initialization for edge cases
- BGR color unpacking
Multi-Volume Blending:
- Weighted sum of all lighting params
- Proper direction blending: normalize(sum(dir × weight))
- Blends ambient, diffuse, fog, sky, cloud density
Temporal Smoothing:
- Exponential blend to prevent frame snapping
- Smooths ALL parameters (colors, fog, direction, sky)
Game Time Support:
- Accepts server-sent game time (WoW standard)
- Falls back to local time if not provided
- Manual override for testing
Debug Features:
- Volume distance/weight logging
- Fog params logging
- Coordinate scale verification
Also: Move buff bar to top-left under player frame
Replace 2D ImGui text markers with proper 3D billboard sprites using BLP textures.
Features:
- Billboard rendering using Interface\GossipFrame\ BLP textures (yellow !, yellow ?, grey ?)
- WoW-style visual effects: bob animation, distance-based scaling, glow pass, distance fade
- Proper NPC height positioning with bounding box detection
- Camera-facing quads with depth testing but no depth write
- Shader-based alpha modulation for glow and fade effects
Technical changes:
- Created QuestMarkerRenderer class with billboard sprite system
- Integrated into Renderer initialization for both online and offline terrain loading
- Rewrote updateQuestMarkers() to use billboard system instead of M2 models
- Disabled old 2D ImGui renderQuestMarkers() in game_screen.cpp
- Added debug logging for initialization and marker tracking
Quest markers now render with proper WoW visual fidelity.
Issue: Trainer buttons were all greyed out because alreadyKnown was incorrectly
calculated using (state == 0 || isKnown(spellId)), which marked spells with
state=0 as 'already known' even when they weren't in the knownSpells list.
This caused prerequisite checks to fail since they only check knownSpells.
Fix: Changed alreadyKnown to only check isKnown(spellId), removing the state==0
check. Now prerequisites work correctly.
Added extensive debug logging to track:
- Known spells count and spell IDs
- Individual prerequisite checks (chain1, chain2, chain3)
- Whether spells are in initial SMSG_INITIAL_SPELLS packet
Note: Some trainers may still show greyed buttons due to server-side data issues
where prerequisite spells are marked as unavailable (state=0) even though they
haven't been learned yet. This is correct client behavior.
NPCs were not spawning when the player first entered the world because
spawnNpcs() was defined but never called. Added call to spawnNpcs() in
Application::update() when in IN_GAME state.
The function has a guard (npcsSpawned flag) so it only runs once. NPCs now
appear immediately at spawn instead of requiring the player to walk away first.
Added logging to help debug spawn preconditions.
Adds $n placeholder for player character names in quest and gossip dialog. Enhances documentation for three-option gender placeholders to clarify support for neutral terms like friend/champion/sibling. Player name defaults to 'Adventurer' when character not loaded.
Extends gender system beyond WoW's binary male/female to support nonbinary characters with proper they/them pronouns. Implements client-side gender mapping (nonbinary→male) for 3.3.5a server compatibility while preserving player identity through local config persistence. Adds pronoun placeholders ($p/$o/$s/$S) and three-option gender text parsing ($g<male>:<female>:<nonbinary>;) for inclusive quest and dialog text.
Settings Changes:
- All settings now apply immediately without Apply button
- Each slider/checkbox instantly updates the game state and saves
- Escape key closes settings window if open (no longer shows escape menu behind it)
- Restore Defaults buttons now also apply settings immediately
Audio Changes:
- Increased NPC voice volume from 0.6 to 1.0 (60% to 100% base volume)
- Helper lambda in Audio tab for efficient volume application
- Master volume multiplier applied to all audio systems in real-time
UX Improvements:
- Removed redundant Apply button
- Settings save automatically on every change
- More intuitive settings flow - see changes instantly
- Cleaner escape key handling priority
The ImGuiWindowFlags_NoInputs flag was blocking all input including mouse clicks.
Removed this flag to restore action bar clickability while keeping keyboard shortcuts functional.
Removed the "N" indicator that was showing on the minimap when rotation
was enabled. The indicator was confusing and not needed - when rotation
is disabled (default), north is always at the top of the minimap, and
when rotation is enabled, the map itself rotating shows the orientation.
Changed default value from true to false in three places:
- Minimap class (rotateWithCamera member)
- GameScreen settings (minimapRotate_ and pendingMinimapRotate)
- Restore Interface Defaults button
The minimap will now remain fixed/north-up by default, and the settings
checkbox properly controls the rotation behavior.
Added ImGuiWindowFlags_NoInputs to action bar window so it doesn't capture
keyboard input. Previously, hovering over or clicking the action bar would
set WantCaptureKeyboard=true, blocking the 1-9,0,-,= hotkeys from working.
CMSG_TRAINER_BUY_SPELL was missing the trainerId field — server expects
guid(8) + trainerId(4) + spellId(4) = 16 bytes, not 12. Spells with
unmet prerequisites (chainNode1/2/3), insufficient level, or already
known are now greyed out with disabled Train buttons. Tooltips show
prerequisite status in green/red.
Fix SMSG_BINDPOINTUPDATE opcode from 0x1B3 to 0x155 — the old value
collided with SMSG_TRAINER_BUY_SUCCEEDED, causing buy responses to be
misinterpreted as bindpoint updates. Add specialization tabs using
SkillLineAbility.dbc to group spells by class spec (category 7).
- Add setInstancePosition() to M2Renderer and WMORenderer for moving
transport instances at runtime
- Detect UPDATEFLAG_TRANSPORT on gameobjects and track transport GUIDs
- Parse player-on-transport state from movement blocks
- Wire transport move callback in Application to update render positions
- Implement CMSG_GAMEOBJECT_QUERY / SMSG_GAMEOBJECT_QUERY_RESPONSE so
gameobjects display proper names instead of "Unknown"
- Add name/entry fields to GameObject entity class
- Fix CMSG_USE_ITEM packet: remove extra uint8 that shifted the item
GUID by one byte, breaking hearthstone and all item usage
- Remove redundant CMSG_LOOT after CMSG_GAMEOBJECT_USE for chests
- Show PvP enabled/disabled state in toggle message
- Relax WMO ramp wall-collision step-up check to allow walking on
gentle ramps where floor rise per step is under 0.1 units
- Add M2 fallback when WMO group files fail to load for gameobjects
- Handle re-creation of existing gameobject render instances by
updating position instead of silently ignoring
Clear aura list on AURA_UPDATE_ALL so dismount/WMO transitions refresh
properly. Increase WMO step height thresholds to reduce stair blocking.
Change buff cancel to right-click and support dismount via buff bar.
Add 36 arena and battleground opcodes with handlers for queue status, team events, invites, and errors. Fix SMSG_FORCE_RUN_SPEED_CHANGE parsing (uint8 not uint32) and remove manual mount speed tracking. Buff bar now shows spell icons and is positioned below the minimap. Both mouse buttons cancel autorun.
Sent messages now appear immediately in chat log. Channel shortcuts (/s, /g, /p, /w, etc.) switch the chat type dropdown and color the input text to match. URLs in chat are clickable and open in the system browser.
TaxiNodes.dbc name was read from field 6 (Korean locale, empty) instead
of field 5 (enUS). Add BFS-based cost computation from TaxiPath.dbc
edges and display gold/silver/copper next to each destination.
Render mount M2 model under player with seated animation, apply creature
skin textures, server-driven speed via SMSG_FORCE_RUN_SPEED_CHANGE, and
/dismount command. X11 XUngrabPointer on crash/hang to always release mouse.
- Implement flight path system: SMSG_SHOWTAXINODES parser, CMSG_ACTIVATETAXIEXPRESS builder, BFS multi-hop pathfinding through TaxiNodes/TaxiPath DBC, taxi destination UI, movement blocking during flight
- Fix WMO interiors too dark by boosting vertex color lighting multiplier
- Dim M2 objects inside WMO interiors (rugs, furniture) via per-instance interior detection
- Fix ramp/stair clipping by lowering wall collision normal threshold from 0.85 to 0.55
- Restore 5-sample cardinal footprint for ground detection to fix rug slipping
- Fix /unstuck command to reset player Z to WMO/terrain floor height
- Handle MSG_MOVE_TELEPORT_ACK and SMSG_TRANSFER_PENDING for hearthstone teleports
- Fix spawning under Stormwind with online-mode camera controller reset
Sweep step size reduced from 1.0f back to 0.65f with max 3 steps (was 2)
to prevent clipping through ramps in Stormwind. All paths updated: follow,
free-fly, and swimming.
Shadows disabled by default in renderer, settings UI, and settings defaults.
- Fix CMSG_BUY_ITEM count field from uint8 to uint32 (server silently dropped undersized packets)
- Character select screen: remember last selected character, two-column layout with details panel, double-click to enter world, responsive window sizing
- Fix stale character data between logins by replacing static init flag with per-character GUID tracking
- Parallelize WMO visibility culling across worker threads (same pattern as M2 renderer)
- Optimize WMO collision queries with world-space group bounds early rejection in getFloorHeight, checkWallCollision, isInsideWMO, and raycastBoundingBoxes
- Reduce camera ground samples from 5 to 3 movement-aligned probes
- Add WMO interior lighting, unlit materials, vertex color multiply, and alpha blending support
Targeting Commands:
- /cleartarget - Clear current target selection
- /targetenemy - Cycle to next hostile target (Tab equivalent)
- /targetfriend - Cycle to next friendly player
- /targetlasttarget, /targetlast - Switch to previous target
- /targetlastenemy - Cycle to previous hostile target
- /targetlastfriend - Cycle to previous friendly player
- /focus - Set current target as focus (client-side)
- /clearfocus - Clear focus target
Implementation:
- Added focusGuid and lastTargetGuid to GameHandler for client-side tracking
- setTarget() now automatically saves previous target to lastTargetGuid
- setFocus() and clearFocus() manage focus target with user feedback
- targetLastTarget() swaps current and previous targets
- targetEnemy() cycles through hostile entities (Units)
- targetFriend() cycles through friendly entities (Players)
- Both targetEnemy/targetFriend support reverse parameter for backwards cycling
Features:
- Focus targeting is client-side (no server opcode in 3.3.5a)
- Last target tracking happens automatically on every target change
- Enemy/friend cycling iterates through visible entities
- Provides user feedback when no targets available
- Tab-like cycling behavior with wraparound
All commands work entirely client-side for responsive targeting.
- Uninvite/kick: /uninvite, /kick <player name> to remove player from party/raid
- Leave party: /leave, /leaveparty to leave current group
- Main tank: /maintank, /mt to set target as main tank (uses raid marker index 0)
- Main assist: /mainassist, /ma to set target as main assist (uses raid marker index 1)
- Clear markers: /clearmaintank, /clearmainassist to remove designations
- Raid info: /raidinfo to display raid lockouts and saved instances
Added opcodes:
- CMSG_REQUEST_RAID_INFO (0x2CD) for requesting raid lockout info
- SMSG_RAID_INSTANCE_INFO (0x2CC) for receiving raid info response
New packet builders:
- GroupUninvitePacket for removing players from group
- GroupDisbandPacket for leaving party (with logging)
- RaidTargetUpdatePacket for setting raid markers (main tank/assist)
- RequestRaidInfoPacket for querying raid lockouts
All commands include proper validation and user feedback.