Commit graph

86 commits

Author SHA1 Message Date
Paul
5ef600098a chore(renderer): refactor renderer and add post-process + spell visuals systems
- Updated core render pipeline and renderer integration in CMakeLists.txt, renderer.cpp, renderer.hpp
- Added post-process pipeline module:
  - post_process_pipeline.hpp
  - post_process_pipeline.cpp
- Added spell visual system module:
  - spell_visual_system.hpp
  - spell_visual_system.cpp
- Adjusted application/audio integration:
  - application.cpp
  - audio_coordinator.cpp
2026-04-02 00:21:21 +03:00
Paul
d43397163e refactor: decouple Application singleton by extracting core subsystems and updating interfaces
- Add `audio::AudioCoordinator` interface and implementation
- Modify `Application` to reduce singleton usage and move controller responsibilities:
  - application.hpp
  - application.cpp
- Update UI and audio headers/sources:
  - game_screen.hpp
  - game_screen.cpp
  - ui_manager.hpp
  - audio_coordinator.hpp
  - audio_coordinator.cpp
- Project config touched:
  - CMakeLists.txt
2026-04-01 20:38:37 +03:00
Kelsi
2c50cc94e1 docs: add why-comments to TBC parsers, bell audio, portrait preview
- packet_parsers_tbc: explain spline waypoint cap (DoS prevention),
  spline compression flags (Catmull-Rom 0x80000 / linear 0x2000 use
  uncompressed format, others use packed delta), spell hit target cap
  (128 >> real AOE max of ~20), guild roster cap (1000 safety limit)
- ambient_sound_manager: explain 1.5s bell toll spacing — matches
  retail WoW cadence, allows each toll to ring out before the next
- character_preview.hpp: explain 4:5 portrait aspect ratio for
  full-body character display in creation/selection screen
2026-03-30 17:26:13 -07:00
Kelsi
ef787624fe refactor: name M2 sequence flag, replace empty loop with std::advance
- m2_loader: define kM2SeqFlagEmbeddedData (0x20) with why-comment —
  when clear, keyframe data lives in external .anim files and M2 offsets
  are file-relative (reading them from M2 produces garbage). Replaces
  3 bare hex literals across parseAnimTrack and ribbon emitter parsing
- audio_engine: replace empty for-loop iterator advance with
  std::advance() for clarity
2026-03-30 14:59:03 -07:00
Kelsi
d2a7d79f60 refactor: add why-comments to zone tiles, audio cache, socket buffer
- zone_manager: document tile-to-zone key encoding (tileX * 100 + tileY,
  safe because tileY < 64 < 100) and explain that ranges are empirically
  derived from the retail WoW map grid
- audio_engine: expand sample rate comment — miniaudio defaults to
  device rate causing pitch distortion if not set explicitly; name
  kMaxCachedSounds constant with memory budget explanation
- tcp_socket: add why-comment on 4 KB recv buffer sizing — covers
  typical 20-500 byte packets and worst-case ~2 KB UPDATE_OBJECT
2026-03-30 14:52:51 -07:00
Kelsi
59bbeaca62 fix: ::toupper/::tolower UB on signed char at 5 remaining call sites
std::toupper(int) and std::tolower(int) have undefined behavior when
passed a negative value. These sites passed raw signed char without
casting to unsigned char first, unlike the rest of the codebase which
already uses the correct pattern. Affects auth (account names), world
packets, and mount sound path matching.
2026-03-29 19:58:36 -07:00
Kelsi
c762688202 refactor: promote static const arrays to constexpr across audio/core/rendering
audio: birdPaths, cricketPaths, races
core/application: componentDirs (4 instances), compDirs
rendering/character_preview: componentDirs
rendering/character_renderer: regionCoords256, regionSizes256
2026-03-27 15:31:21 -07:00
Kelsi
05e85d9fa7 fix: correct melee swing sound paths to match WoW MPQ layout
The melee swing clips used non-existent paths (SwordSwing, MeleeSwing)
instead of the actual WoW 3.3.5a weapon swing files: WeaponSwings/
mWooshMedium and mWooshLarge for hit swings, MissSwings/MissWhoosh
for misses. Fixes "No melee swing SFX found in assets" warning.
2026-03-24 13:46:01 -07:00
Kelsi
503f9ed650 fix: auto-detect CharSections.dbc layout and add Blood Elf/Draenei NPC voices
CharSections.dbc has different field layouts between stock WotLK (textures
at field 4-6) and Classic/TBC/Turtle/HD-textured WotLK (VariationIndex at
field 4). Add detectCharSectionsFields() that probes field-4 values at
runtime to determine the correct layout, so both stock and modded clients
work without JSON changes.

Also add BLOODELF_MALE/FEMALE and DRAENEI_MALE/FEMALE voice types to the
NPC voice system — previously all Blood Elf and Draenei NPCs fell through
to GENERIC (random dwarf/gnome/night elf/orc mix).
2026-03-23 11:00:49 -07:00
Kelsi
180990b9f1 feat: play minimap ping sound when party members ping the map
Add playMinimapPing() to UiSoundManager with MapPing.wav (falls back to
target select sound). Play the ping sound in MSG_MINIMAP_PING handler
when the sender is not the local player. Provides audio feedback for
party member map pings, matching WoW behavior.
2026-03-20 18:21:34 -07:00
Kelsi
39bf8fb01e feat: play audio notification when a whisper is received
Adds UiSoundManager::playWhisperReceived() which uses the dedicated
Whisper_TellMale/Female.wav files (or falls back to iSelectTarget.wav
if absent). The sound is triggered once per new incoming CHAT_MSG_WHISPER
message by scanning new chat history entries in the raid warning overlay
update loop.
2026-03-12 06:12:37 -07:00
Kelsi
9d1616a11b audio: stop precast sound on spell completion, failure, or interrupt
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.
2026-03-09 21:04:24 -07:00
Kelsi
3eded6772d Implement bird/cricket ambient sounds and remove stale renderer TODO
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
- Add birdSounds_ and cricketSounds_ AmbientSample vectors to
  AmbientSoundManager, loaded from WoW MPQ paths:
  BirdAmbience/BirdChirp01-06.wav (up to 6 variants, daytime) and
  Insect/InsectMorning.wav + InsectNight.wav (nighttime). Missing files
  are silently skipped so the game runs without an MPQ too.
- updatePeriodicSounds() now plays a randomly chosen loaded variant
  at the scheduled interval instead of the previous no-op placeholder.
- Remove stale "TODO Phase 6: Vulkan underwater overlay" comment from
  Renderer::initialize(); the feature has been fully implemented in
  renderOverlay() / the swim effects pipeline since that comment was
  written.
2026-03-09 19:00:42 -07:00
vperus
163dc9618a Replace (std::min + std::max) with std::clamp 2026-03-10 03:18:18 +02:00
Kelsi
13e3e5ea35 Implement MusicManager fade-out in stopMusic() — was a stub
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).
2026-03-09 16:30:42 -07:00
Kelsi
68bf3d32b0 Wire ambient sound zone detection: setZoneType/setCityType was never called
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.
2026-03-09 16:24:12 -07:00
Kelsi
46f2c0df85 Fix SoundEntries.dbc field indices for SMSG_PLAY_MUSIC and remove dead NpcVoiceManager code
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.
2026-03-09 16:01:29 -07:00
Kelsi
e4f53ce0c3 Handle SMSG_ACHIEVEMENT_EARNED with toast banner and chat notification
- 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)
2026-03-09 13:53:42 -07:00
Kelsi
3d6e3993d2 Fix water splash sounds bypassing mute via ffplay path
playOneShot() spawns an external ffplay process that bypasses the
miniaudio engine master volume. Now checks getMasterVolume() before
spawning the process.
2026-02-26 02:34:36 -08:00
Kelsi
5cb469e318 Skip sound playback when master volume is muted
Water splash and swimming sounds were bypassing mute because
ma_engine_set_volume(0) didn't fully prevent sound creation.
Now playSound2D and playSound3D early-return when masterVolume
is zero.
2026-02-26 02:31:06 -08:00
Kelsi
2219ccde51 Optimize city performance and harden WMO grounding 2026-02-25 10:22:05 -08:00
Kelsi
aaab2115d1 Fix all remaining build warnings and eliminate UB in binary parsers
Resolve 57 compiler warnings (unused params/vars, ignored return values,
enum mismatch) and replace undefined-behavior reinterpret_cast with
memcpy in DBC, BLP, and Warden module loaders for ARM64 portability.
2026-02-23 19:58:38 -08:00
Kelsi
a250c20d84 Fix audio volume double/triple-scaling and add About tab
Audio was being scaled by master volume multiple times: once via
ma_engine_set_volume, again per-sound in AudioEngine, and again
via pre-multiplication in the UI. Removed redundant master volume
multiplications so each channel volume is independent and master
applies once through the engine. Added About tab to settings with
developer info and GitHub link.
2026-02-23 07:51:10 -08:00
Kelsi
f2f6ffd2cd Fix voice gender using server data and update loading screen UI
- Use authoritative playerRace/playerGender at spawn for voice profiles
  instead of unreliable model name parsing
- Support nonbinary gender with useFemaleModel body type fallback
- Move voice setup into spawnPlayerCharacter() for all spawn paths
- Remove legacy single-player default Human Male clip preloading
- Make loading screen text black and move progress bar to top
2026-02-23 06:22:30 -08:00
Kelsi
44a947163d Smooth login music start and lower auth-screen volume
Add configurable fade-in support to MusicManager playback paths and use it for auth/login intro tracks to avoid abrupt starts. Apply a login-only 20% music attenuation while the auth screen is active, then restore the previous music volume when leaving login so in-game volume remains unchanged.
2026-02-20 20:34:06 -08:00
Kelsi
328ec9ea78 Fix combat vocalizations with correct MPQ paths, add combat idle stance
Use actual WoW 3.3.5a PlayerExertions and Vox sound paths from MPQ
manifests for attack grunts, wounds, and death sounds. Handle Blizzard
naming quirks (HumanFeamle typo, OrcMale no Final suffix, Scourge→Undead).
Add COMBAT_IDLE animation state with ready weapon stance between swings.
Restore deleted MPQ sound manifest docs.
2026-02-19 21:50:32 -08:00
Kelsi
8a9d9f47db Add combat sounds, melee ability animations, and player vocalizations
Wire CombatSoundManager into SMSG_ATTACKERSTATEUPDATE for weapon swing,
impact, and miss sounds. Add attack grunt and wound vocalizations to
ActivitySoundManager using correct WoW MPQ PC-suffix paths. Trigger
attack animation on SMSG_SPELL_GO for warrior melee abilities. Add
client-side melee range and facing checks to prevent server rejections.
Snap charge arrival to target's current position for reliable melee range.
2026-02-19 21:31:37 -08:00
Kelsi
c69457ae3b apply pending protocol, ui, audio, and CodeQL fixes 2026-02-19 16:17:06 -08:00
Kelsi
e778e21f6f Fix minimap mute behavior and shallow-water swim trigger 2026-02-19 02:46:52 -08:00
Kelsi
c998c945bf Implement MPQ-path sound loading in AudioEngine
Add AssetManager hookup to AudioEngine so the path-based playSound2D/3D
overloads can load files on demand rather than requiring preloading.

- Add setAssetManager() to AudioEngine (called during world load alongside
  other audio manager initializations)
- playSound2D(mpqPath) now calls assetManager->readFile() then delegates
  to the vector<uint8_t> overload (removes the "not yet implemented" warning)
- playSound3D(mpqPath, position) same — delegates to the fully spatialized
  vector overload (was previously silently falling back to 2D)
2026-02-17 18:52:19 -08:00
Kelsi
bd70ca17ca Fix auto-attack stalling after SMSG_ATTACKSTOP and remove stale comments
Re-send CMSG_ATTACKSWING every second while auto-attacking so combat
resumes automatically when the server pauses the attack loop (out of
range, etc). Previously the client kept autoAttacking=true but never
re-engaged, requiring the player to manually right-click again.

Also remove leftover single-player/offline references from comments.
2026-02-17 15:37:02 -08:00
Kelsi
827679579f Fix WAV decode cache and spell lookup performance
- audio_engine.cpp: cache key was based on vector pointer address, not
  content — cache never hit since each asset load produces a new
  allocation. Replace with FNV-1a over head+tail bytes + size, giving
  correct content-based identity at O(1) cost. Add 256-entry cap with
  eviction to prevent unbounded growth over long sessions.

- game_handler.hpp/cpp, spellbook_screen, game_screen: knownSpells was
  a std::vector with O(n) std::find lookups scattered across packet
  handlers and UI code. Switch to std::unordered_set for O(1) insert,
  erase, and membership checks. Update all push_back/erase-remove/find
  call sites to use set operations.
2026-02-17 15:13:54 -08:00
Kelsi
36fc1df706 Fix Turtle WoW compatibility: NPC spawning, quests, spells, realm display, and music
- Add TurtlePacketParsers with dedicated movement block parser (Classic format + transport timestamp)
- Fix quest giver status: read uint32 and translate vanilla enum values for Classic/Turtle
- Fix quest accept packet: remove trailing uint32 that vanilla servers reject
- Fix quest details parser: auto-detect vanilla vs WotLK format (informUnit field)
- Fix spellbook and action bar icons: fallback to WotLK DBC field indices when expansion layout fails
- Fix spell cast failure messages: translate vanilla SpellCastResult codes (+1 offset)
- Fix realm list: correct type values (6=RP, 8=RP-PvP) and population thresholds
- Fix music: disable looping for zone music, auto-advance to next random track when finished
- Add music anti-repeat: avoid playing the same track back-to-back
- Make TBC update block parsing resilient (keep parsed blocks on failure instead of aborting)
- Add right-click attack on hostile mobs
- Add name query diagnostic logging
2026-02-17 05:27:03 -08:00
Kelsi
d2b46d410a Add original music to login rotation and zone playlists
11 original tracks in assets/Original Music/ now play on the login
screen and in thematically matched zones across Eastern Kingdoms and
Kalimdor. Added crossfadeToFile to MusicManager for local file
playback during zone transitions. New zones: Tirisfal, Undercity,
Barrens, STV, Duskwood, Burning Steppes, Searing Gorge, Ironforge,
Loch Modan, Orgrimmar, Durotar, Mulgore, Thunder Bluff, Darkshore,
Teldrassil, Darnassus.
2026-02-15 05:53:27 -08:00
Kelsi
09de52f310 Fix UI window hotkey toggles and silent mount sound fallback 2026-02-14 21:56:38 -08:00
Kelsi
d27387d744 Fix mount sounds, grey WMO meshes, taxi landing, tree animations, and classic dismount
- Per-family mount sounds (kodo, tallstrider, mechanostrider, etc.) detected from M2 model path
- Skip WMO groups with SHOW_SKYBOX flag or all-untextured batches (grey mesh in Orgrimmar)
- Freeze physics during taxi landing until terrain loads to prevent falling through void
- Disable bone animations on tropical vegetation (palm, bamboo, banana, etc.) to fix wiggling
- Snap player to final taxi waypoint on flight completion
- Extract mount aura spell ID from classic UNIT_FIELD_AURAS for CMSG_CANCEL_AURA dismount
- Increase /unstuck forward nudge to 5 units
2026-02-14 21:04:20 -08:00
Kelsi
5171f9cad4 Fix taxi state sync and transport authority; reduce runtime log overhead; restore first-person self-hide 2026-02-11 22:27:02 -08:00
Kelsi
f752a4f517 Fix NPC visibility and stabilize world transport/taxi updates 2026-02-11 18:25:04 -08:00
Kelsi
274a88097f Clean repository artifacts and refresh project documentation 2026-02-11 15:28:50 -08:00
Kelsi
b14ffd20df Re-enable jump and land sounds for mounts
Jump effort and landing sounds are fine - issue was with idle fidget
animations, not jump/land action sounds. Strict fidget filtering remains.
2026-02-10 20:33:23 -08:00
Kelsi
fe3c6a6a79 Disable pained sounds and tighten fidget criteria
Removed jump/land sounds (attack/wound sounds had pained growls).
Made fidget discovery much stricter to exclude jerky battle animations.

Changes:
- Disabled playJumpSound for ground mounts (attack sounds too aggressive)
- Disabled playLandSound for ground mounts (wound sounds have growls)
- Fidget criteria now requires BOTH frequency AND replay (not OR)
- Excluded IDs 11-15 (attacks) in addition to 16-21 (combat)
- Only animations with proper idle metadata will be selected
2026-02-10 20:32:43 -08:00
Kelsi
3c58492c8f Add dedicated snort and whinny idle sounds with longer intervals
Created specific idle sound pool using only horse snorts and whinnies.
Re-enabled idle sounds with much longer interval (20-40 seconds).

Changes:
- Added horseIdleSounds_ pool: mHorseStand3A (snort) + mHorseAggroA (whinny)
- Updated playIdleSound() to use dedicated pool instead of mixed breath sounds
- Increased idle sound interval from 8-15s to 20-40s (less frequent)
- Removed flying mount idle sounds (too aggressive)
- Increased volume slightly (0.35x) for better audibility
2026-02-10 20:20:26 -08:00
Kelsi
8d8e780607 Add mount idle fidget animations and ambient sounds
Implements WoW-style mount idle behavior when player is stationary:
- Fidget animations: discovered via property search (non-looping, 500-1500ms, stationary, IDs 1-10)
- Triggers random fidget every 6-12 seconds when standing still
- Ambient idle sounds: snorts/breaths for ground mounts, soft wing sounds for flyers
- Triggers random idle sound every 8-15 seconds when stationary
- Both systems reset timers on movement to avoid triggering while riding
2026-02-10 19:53:23 -08:00
Kelsi
4b9a2394d5 Fix mount sounds with real MPQ paths and family detection
Mount Sound System:
- Use actual creature sounds from MPQ (Horse, Ram, Wolf, Tiger, Dragons)
- Separate sound pools: jump (attack), landing (wound), rear-up (aggro)
- Mount family detection: HORSE, RAM, WOLF, TIGER, RAPTOR, DRAGON
- Family logged on mount for future per-family sound selection

Sound Mappings:
- Flying mounts: Dragon wing flaps + DragonHawk screeches
- Ground mounts: Horse attack (jump), wound (land), aggro (rear-up)
- Ready for family-specific sound selection (TODO)

Mount Lean:
- Procedural lean into turns for ground mounts
- Physics-based: turn rate × 0.15, max ±14°, 6x/sec blend
- Returns to upright when not turning or when flying
- Rider follows mount roll automatically via bone attachment
2026-02-10 19:49:07 -08:00
Kelsi
c623fcef51 Add property-based mount animation discovery and procedural lean
Mount Animation System:
- Property-based jump animation discovery using sequence metadata
- Chain linkage scoring (nextAnimation/aliasNext) for accurate detection
- Correct loop detection: flags & 0x01 == 0 means looping
- Avoids brake/stop animations via blendTime penalties
- Works on any mount model without hardcoded animation IDs

Mount Physics:
- Physics-based jump height: vz = sqrt(2 * g * h)
- Configurable MOUNT_JUMP_HEIGHT constant (1.0m default)
- Procedural lean into turns for ground mounts
- Smooth roll based on turn rate (±14° max, 6x/sec blend)

Audio Improvements:
- State-machine driven mount sounds (jump, land, rear-up)
- Semantic sound methods (no animation ID dependencies)
- Debug logging for missing sound files

Bug Fixes:
- Fixed mount animation sequencing (JumpStart → JumpLoop → JumpEnd)
- Fixed animation loop flag interpretation (0x20 vs 0x21)
- Rider bone attachment working correctly during all mount actions
2026-02-10 19:30:45 -08:00
Kelsi
d8002955a3 Add debug logging for GameObject spawns to diagnose duplicate cathedral
Added detailed logging in spawnOnlineGameObject() to help identify duplicate
game object spawns. Logs displayId, guid, model path, and position for both
new spawns and position updates. This will help diagnose the floating
cathedral model issue in Stormwind by showing which GUIDs are being spawned
and their coordinates.
2026-02-09 18:04:20 -08:00
Kelsi
c002f59699 Add goblin voice support for NPCs
- Added GOBLIN_MALE and GOBLIN_FEMALE to VoiceType enum
- Load greeting, farewell, vendor, and pissed sounds for goblin NPCs
- Prevents goblins from falling back to generic voice flag
- Uses proper goblin sound files from Goblin character folder
2026-02-09 17:14:34 -08:00
Kelsi
016cc01c68 Implement immediate settings application and fix escape menu behavior
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
2026-02-09 17:12:35 -08:00
Kelsi
9741c8ee7c Implement comprehensive audio control panel with tabbed settings interface
Adds complete audio volume controls for all 11 audio systems with master volume. Reorganizes settings window into Video, Audio, and Gameplay tabs for better UX.

Audio Features:
- Master volume control affecting all audio systems
- Individual volume sliders for: Music, Ambient, UI, Combat, Spell, Movement, Footsteps, NPC Voices, Mounts, Activity sounds
- Real-time volume adjustment with master volume multiplier
- Restore defaults button per tab

Technical Changes:
- Added getVolumeScale() getters to all audio managers
- Integrated all 10 audio managers into renderer (UI, Combat, Spell, Movement added)
- Expanded game_screen.hpp with 11 pending volume variables
- Reorganized settings window using ImGui tab bars (Video/Audio/Gameplay)
- Audio settings uses scrollable child window for 11 volume controls
- Settings window expanded to 520x720px to accommodate comprehensive controls
2026-02-09 17:07:22 -08:00
Kelsi
1e23370c0e Add movement sound manager for water splashes and jump/land vocalizations
Implements water splash sounds (enter water + footsteps) with size-based intensity and jump/land vocalizations for all 16 race/gender combinations.
2026-02-09 16:50:37 -08:00