- vk_context: name FNV-1a hash constants (kFnv1aOffsetBasis/kFnv1aPrime)
with why-comment on algorithm choice for sampler cache
- transport_manager: collapse redundant if/else that both set
looping=false into single unconditional assignment, add why-comment
explaining the time-closed path design
- transport_manager: hoist duplicate kMinFallbackZOffset constants out
of separate if-blocks, add why-comment on icebreaker Z clamping
- entity: expand velocity smoothing comment — explain 65/35 EMA ratio
and its tradeoff (jitter suppression vs direction change lag)
elapsedTime_ was float (32-bit, ~7 significant digits). At 16384
seconds the float can only represent integers, so elapsedTime_*1000
jumps in 1-second steps — ships and elevators visibly jerk. Changed to
double (53-bit mantissa) which maintains sub-millisecond precision for
~285 million years. Also changed lastServerUpdate to double to match.
Squared distance optimizations across 30 files:
- Convert glm::length() comparisons to glm::dot() (no sqrt)
- Use glm::inversesqrt() for check-then-normalize patterns (1 rsqrt vs 2 sqrt)
- Defer sqrt to after early-out checks in collision/movement code
- Hottest paths: camera_controller (21), weather particles, WMO collision,
transport movement, creature interpolation, nameplate culling
Container and algorithm improvements:
- std::map<string> → std::unordered_map for asset/DBC/MPQ/warden caches
- std::mutex → std::shared_mutex for asset_manager and mpq_manager caches
- std::sort → std::partial_sort in lighting_manager (top-2 of N volumes)
- Double-lookup find()+operator[] → insert_or_assign in game_handler
- Add reserve() for per-frame vectors: weather, swim_effects, WMO/M2 collision
Threading and synchronization:
- Replace 1ms busy-wait polling with condition_variable in character_renderer
- Move timestamp capture before mutex in logger
- Use memory_order_acquire/release for normal map completion signaling
API additions:
- DBC getStringView()/getStringViewByOffset() for zero-copy string access
- Parse creature display IDs from SMSG_CREATURE_QUERY_SINGLE_RESPONSE
Replace ~37 remaining C-style casts with static_cast across 16 files.
Extract named color constants (kColorRed/Green/Yellow/Gray) and dialog
window flags (kDialogFlags) in game_screen.cpp, replacing 72 inline
literals. Normalize keybinding_manager.hpp to #pragma once.
- Extract guidToUnitId(), getQuestTitle(), findQuestLogEntry() helpers
to replace 14 duplicated GUID-to-unitId patterns and 7 quest log
search patterns in game_handler.cpp
- Remove duplicate #include in renderer.cpp
- Remove commented-out model cleanup code in terrain_manager.cpp
- Replace C-style casts with static_cast in auth and transport code
- Fix NULL renderer pointers by moving TransportManager connection after
initializeRenderers for WMO-only maps
- Fix tram direction by negating DBC TransportAnimation X/Y local offsets
before serverToCanonical conversion
- Implement client-side M2 transport boarding via proximity detection
(server doesn't send transport attachment for trams)
- Use position-delta approach: player keeps normal movement while
transport's frame-to-frame motion is applied on top
- Prevent server movement packets from clearing client-side M2 transport
state (isClientM2Transport guard)
- Fix getPlayerWorldPosition for M2 transports: simple canonical addition
instead of render-space matrix multiplication
- Parse MCLQ sub-chunks in vanilla ADTs for water rendering (WotLK uses MH2O)
- Load TaxiPathNode.dbc for MO_TRANSPORT world-coordinate paths (vanilla boats)
- Parse data[] from SMSG_GAMEOBJECT_QUERY_RESPONSE (taxiPathId for transports)
- Support vanilla M2 particle emitters (504-byte struct, different from WotLK 476)
- Add character preview texture diagnostic logging
- Fix disconnect handling on character screen (show error only when no chars)
- Added transport fields to MovementInfo struct (transportGuid, transportX/Y/Z/O, transportTime)
- Updated MovementPacket::build() to serialize transport data when ONTRANSPORT flag set
- Modified GameHandler::sendMovement() to include transport info when player on transport
- Fixed coordinate conversion for transport offsets (server↔canonical)
- Added transport tracking in both CREATE_OBJECT and MOVEMENT update handlers
- Connected M2Renderer to WMORenderer for hierarchical doodad transforms
- Server-authoritative transport movement (no client-side animation)
Issue: Server not sending MOVEMENT updates for transports, so they remain stationary.
Transports register successfully but don't animate without server position updates.
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