Commit graph

112 commits

Author SHA1 Message Date
Kelsi
ecef6c8d77 Add hex dump logging for SMSG_QUESTGIVER_QUEST_COMPLETE packet debugging 2026-02-09 23:10:13 -08:00
Kelsi
3859c41319 Add debug logging for quest completion flow
Adds logging to track quest completion from gossip through reward selection:
- selectGossipQuest: logs when quest clicked in gossip
- handleQuestOfferReward: logs when reward window opens
- chooseQuestReward: logs when completing quest
- SMSG_QUESTGIVER_QUEST_COMPLETE: logs server confirmation
2026-02-09 22:56:38 -08:00
Kelsi
463ee4a311 Fix misleading comment in TrainerSpell state field
The comment incorrectly stated state values as:
  0=known(green), 1=available, 2=unavailable(red)

Actual correct values are:
  0=unavailable(grey), 1=available(green), 2=known(green)

This was causing confusion when debugging trainer issues.
2026-02-09 22:19:13 -08:00
Kelsi
01ff6db748 Fix trainer prerequisite checking
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.
2026-02-09 22:13:31 -08:00
Kelsi
5e0d62c2a4 Fix NPC spawning at initial player position
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.
2026-02-09 21:59:00 -08:00
Kelsi
1603456120 Add body type selection for nonbinary characters and reduce preview rotation sensitivity
Nonbinary characters can now choose between masculine and feminine body types in character creation, with real-time preview updates and full appearance customization. Body type preference is saved to character config and persists across sessions. Also reduces character preview drag-to-rotate sensitivity from 0.5 to 0.2 for better control.
2026-02-09 17:56:04 -08:00
Kelsi
0071c24713 Add nonbinary gender support with pronoun system and server compatibility
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.
2026-02-09 17:39:21 -08:00
Kelsi
28d009f7db Add comprehensive NPC voice system with interaction and combat sounds
Implements full NPC voice interaction system supporting 6 different sound categories
for all playable races/genders. System loads ~450+ voice clips from MPQ archives.

Voice Categories:
- Greeting: Play on NPC right-click interaction
- Farewell: Play when closing gossip/dialog windows
- Vendor: Play when opening merchant/vendor windows
- Pissed: Play after clicking NPC 5+ times (spam protection)
- Aggro: Play when NPC enters combat with player
- Flee: Play when NPC is fleeing (ready for low-health triggers)

Features:
- Race/gender detection from NPC display IDs via CreatureDisplayInfoExtra.dbc
- Intelligent click tracking for pissed sounds
- Combat sounds use player character vocal files for humanoid NPCs
- Cooldown system prevents voice spam (2s default, combat sounds bypass)
- Generic fallback voices for unsupported NPC types
- 3D positional audio support

Voice Support:
- All playable races: Human, Dwarf, Gnome, Night Elf, Orc, Tauren, Troll, Undead
- Male and female variants for each race
- StandardNPC sounds for social interactions
- Character vocal sounds for combat

Technical Changes:
- Refactored NpcVoiceManager to support multiple sound categories
- Added callbacks: NpcFarewell, NpcVendor, NpcAggro
- Extended voice loading to parse both StandardNPC and Character vocal paths
- Integrated with GameHandler for gossip, vendor, and combat events
- Added detailed voice detection logging for debugging

Also includes:
- Sound manifest files added to docs/ for reference
- Blacksmith hammer pitch increased to 1.6x (was 1.4x)
- Blacksmith volume reduced 30% to 0.25 (was 0.35)
2026-02-09 16:03:51 -08:00
Kelsi
dab23f1895 Add ambient sound system and eliminate log spam
- Implement AmbientSoundManager with tavern/outdoor ambience
- Fix audio buffer limit (5s → 60s) for long ambient loops
- Set log level to INFO to eliminate DEBUG spam (130MB → 3.2MB logs)
- Remove excessive terrain/model/network logging
- Fix ambient sound timer sharing and pitch parameter bugs
2026-02-09 14:50:14 -08:00
Kelsi
e40ea0c47a Fix taxi window close auto-mounting player on griffin
Fixes issue where closing the flight map window would incorrectly mount the
player on a griffin at spawn point. Added taxiLandingCooldown when closing
taxi window to prevent UNIT_FLAG_TAXI_FLIGHT check from re-triggering mount.
2026-02-09 01:35:29 -08:00
Kelsi
eb288d2064 Implement NPC greeting voice lines
Added NPC voice manager that plays greeting sounds when clicking on NPCs:

Features:
- Voice line library with multiple race/gender voice types (Human, Dwarf,
  Night Elf, etc.)
- 3D positional audio - voice comes from NPC location
- Cooldown system prevents spam clicking same NPC
- Randomized pitch/volume for variety
- Loads greeting sounds from character voice files in MPQ
- Generic fallback voices for NPCs without specific voice types

Voice lines trigger automatically when gossip window opens (SMSG_GOSSIP_MESSAGE).
Uses same audio system as other sound effects with ma_sound_set_position.
2026-02-09 01:29:44 -08:00
Kelsi
0ce23cf7bd Fix unwanted mounting when closing taxi window
Closing the taxi map without selecting a destination now properly dismounts
the player. Previously, selectTaxiNode() would optimistically mount the
player, then closeTaxi() would only clear taxiWindowOpen_ without cleaning
up the mount state, leaving the player mounted.
2026-02-09 01:08:39 -08:00
Kelsi
c047446fb7 Add dynamic memory-based asset caching and aggressive loading
- Add MemoryMonitor class for dynamic cache sizing based on available RAM
- Increase terrain load radius to 8 tiles (17x17 grid, 289 tiles)
- Scale worker threads to 75% of logical cores (no cap)
- Increase cache budget to 80% of available RAM, max file size to 50%
- Increase M2 render distance: 1200 units during taxi, 800 when >2000 instances
- Fix camera positioning during taxi flights (external follow mode)
- Add 2-second landing cooldown to prevent re-entering taxi mode on lag
- Update interval reduced to 33ms for faster streaming responsiveness

Optimized for high-memory systems while scaling gracefully to lower-end hardware.
Cache and render distances now fully utilize available VRAM on minimum spec GPUs.
2026-02-08 23:15:26 -08:00
Kelsi
71b52046e0 Keep M2 models permanently in VRAM to eliminate loading hitches
Modern GPUs have 8-16GB VRAM - leverage this to cache all M2 models permanently.

Changes:
- Disabled cleanupUnusedModels() call when tiles unload
- Models now stay in VRAM after initial load, even when tiles unload
- Increased taxi mounting delay from 3s to 5s for more precache time
- Added logging: M2 model count, instance count, and GPU upload duration
- Added debug logging when M2 models are uploaded per tile

This fixes the "building pops up then pause" issue - models were being:
1. Loaded when tile loads
2. Unloaded when tile unloads (behind taxi)
3. Re-loaded when flying through again (causing hitch)

Now models persist in VRAM permanently (few hundred MB for typical session).
First pass loads to VRAM, subsequent passes are instant.
2026-02-08 22:08:42 -08:00
Kelsi
92031102e4 Add mount pitch and roll for realistic taxi flight animation
Flying mounts now tilt and bank realistically during taxi flights:
- Pitch (up/down): calculated from spline tangent's z-component (altitude change)
- Roll (banking): proportional to turn rate, clamped to ~40 degrees
- Yaw: existing horizontal orientation from spline direction

Implementation:
- Added mountPitch_ and mountRoll_ to Renderer (radians)
- Updated TaxiOrientationCallback to pass yaw, pitch, roll
- Calculate pitch using asin(tangent.z) for altitude tilt
- Calculate roll from yaw change rate: -orientDiff * 2.5, clamped to ±0.7 rad
- Applied to mount rotation: glm::vec3(pitch, roll, yaw)

This fixes the "weirdness" where mounts flew sideways or without natural banking.
2026-02-08 22:05:38 -08:00
Kelsi
2e0a7e0039 Fix taxi mount orientation and eliminate tile loading hitches
Fixes two critical taxi flight issues:

1. Mount orientation now correctly faces flight direction:
   - Prevent camera controller from updating facingYaw during taxi (externalFollow_ check)
   - Taxi orientation callback system updates mount rotation from spline tangent
   - Initial orientation set when flight starts
   - Smooth Catmull-Rom spline interpolation for natural curved paths

2. Eliminate frame hitches from tile loading during flight:
   - New taxiFlightStartCallback uploads ALL precached tiles to GPU before flight begins
   - Previously tiles loaded async during 3s mount delay but uploaded 1/frame during flight
   - Now processAllReadyTiles() blocks briefly after mount delay to batch upload everything
   - Combined with 2.0s terrain update interval and aggressive culling for smooth flight

Additional optimizations:
   - Aggressive taxi culling: skip models <15 units, all foliage/trees, underwater objects
   - Max render distance reduced to 150 units during taxi
   - Movement heartbeat packets disabled during taxi (server controls position)
   - Reduced taxi speed from 32 to 18 units/sec to prevent streaming overload
2026-02-08 22:00:33 -08:00
Kelsi
536b3cea48 Implement comprehensive taxi flight optimizations and proper spline paths
Major improvements:
- Load TaxiPathNode.dbc for actual curved flight paths (no more flying through terrain)
- Add 3-second mounting delay with terrain precaching for entire route
- Implement LOD system for M2 models with distance-based quality reduction
- Add circular terrain loading pattern (13 tiles vs 25, 48% reduction)
- Increase terrain cache from 2GB to 8GB for modern systems

Performance optimizations during taxi:
- Cull small M2 models (boundRadius < 3.0) - not visible from altitude
- Disable particle systems (weather, smoke, M2 emitters) - saves ~7000 particles
- Disable specular lighting on M2 models - saves Blinn-Phong calculations
- Disable shadow mapping on M2 models - saves shadow map sampling and PCF

Technical details:
- Parse TaxiPathNode.dbc spline waypoints for curved paths around terrain
- Build full path from node pairs using TaxiPathEdge lookup
- Precache callback triggers during mounting delay for smooth takeoff
- Circular tile loading uses Euclidean distance check (dx²+dy² <= r²)
- LOD fallback to base mesh when higher LODs unavailable

Result: Buttery smooth taxi flights with no terrain clipping or performance hitches
2026-02-08 21:32:38 -08:00
Kelsi
4e0e54a0f0 Fix taxi dismount: clear currentMountDisplayId_ in client path completion
The client path animation completion was calling mountCallback_(0) but
not clearing currentMountDisplayId_, leaving isMounted() returning true
after landing. All three dismount paths now consistently clear the flag.
2026-02-08 20:01:23 -08:00
Kelsi
ef54f62df0 Add multi-tier unstuck system with void fall detection
Replace broken hardcoded-coordinate unstuck with tiered fallbacks:
last safe position > hearth bind > map spawn. Track safe positions
only on real geometry, let player fall after 500ms with no ground,
and auto-trigger unstuck after 5s of continuous falling.
2026-02-08 15:37:34 -08:00
Kelsi
eb92a71b71 Fix trainer buy packet and grey out unmet prerequisites
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.
2026-02-08 15:03:43 -08:00
Kelsi
ee155c3367 Fix trainer buy spell and add specialization tabs
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).
2026-02-08 14:46:01 -08:00
Kelsi
9a01261401 Add trainer dialog system with spell list UI and buy support 2026-02-08 14:33:39 -08:00
Kelsi
f6eaa2cf70 Add idle yawn emote and hearth home tooltip 2026-02-08 03:39:02 -08:00
Kelsi
189f4a0a58 Add bindpoint support and WMO snap fix 2026-02-08 03:32:00 -08:00
Kelsi
132a6ea3c9 Add /unstuckgy and 2GB terrain tile cache 2026-02-08 03:24:12 -08:00
Kelsi
6736ec328b Fix taxi flights, mounts, and movement recovery 2026-02-08 03:05:38 -08:00
Kelsi
d910073d7a Preload terrain textures on background thread and fix ramp Z-snapping
Load BLP texture data during prepareTile() and upload to GL cache in
finalizeTile(), eliminating file I/O stalls on the main thread. Reduce
ready tiles per frame to 1. Fix camera sweep to snap Z to ramp surfaces.
Change hearthstone action bar slot from spell to item.
2026-02-08 01:16:23 -08:00
Kelsi
0ce38cfb99 Add transport support, gameobject queries, and fix item use
- 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
2026-02-08 00:59:40 -08:00
Kelsi
ed2a8a4e0a Fix tunnel camera, dismount buff clear, and ground sampling
Use WMO-aware floor detection for camera clearance so tunnels don't
push the camera up to terrain. Clear permanent auras on dismount via
mount display field. Use center-only sampling for terrain/WMO floors
to prevent offset probes from snapping to terrain above tunnels.
2026-02-08 00:18:47 -08:00
Kelsi
aa462fdb1f Fix buff bar updates, stair collision, and right-click aura cancel
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.
2026-02-08 00:00:12 -08:00
Kelsi
7a2bb28dc0 Add arena/BG opcodes, fix mount speed, buff bar icons, and autorun cancel
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.
2026-02-07 23:47:43 -08:00
Kelsi
22b9ee9726 Reduce collision trapping and improve /unstuck
Add root, branch, thorn, moss, ivy, and other natural doodads to the no-block foliage list. /unstuck now moves the player 5 units forward instead of resetting in place.
2026-02-07 23:34:28 -08:00
Kelsi
394e1a3f31 Improve chat with local echo, slash shortcuts, colored input, and clickable URLs
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.
2026-02-07 23:32:27 -08:00
Kelsi
6d719f2c52 Fix spirit healer resurrection with correct opcodes
Corrected death/resurrection opcode values (SMSG_SPIRIT_HEALER_CONFIRM=0x222, CMSG_SPIRIT_HEALER_ACTIVATE=0x21C, SMSG_RESURRECT_REQUEST=0x15B, CMSG_RESURRECT_RESPONSE=0x15C) and added resurrect dialog UI.
2026-02-07 23:12:24 -08:00
Kelsi
7cd7ac43a9 Refine resurrection flow 2026-02-07 21:47:14 -08:00
Kelsi
ff6155e2f3 Fix chat focus and spirit healer confirm 2026-02-07 21:12:54 -08:00
Kelsi
38c9fdad6b Improve targeting, minimap, and bridge collisions 2026-02-07 20:51:53 -08:00
Kelsi
9f19d9fa1a Fix movement, mounts, and terrain seams 2026-02-07 20:24:25 -08:00
Kelsi
c5a4d04bf5 Add taxi path BFS for activation 2026-02-07 20:05:14 -08:00
Kelsi
e5c48dc9b7 Add gameobject interaction and taxi activation 2026-02-07 19:44:03 -08:00
Kelsi
8bdf0a2e79 Fix taxi node names and add flight path cost display
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.
2026-02-07 19:04:15 -08:00
Kelsi
0874f4f239 Fix mount stability, speed parsing, combat dismount, and self-targeting
- Fix SMSG_FORCE_RUN_SPEED_CHANGE parsing (missing uint32 field caused garbage speed)
- Always send speed ACK to prevent server stall, even on invalid values
- Defer mount model loading to next frame to avoid render-loop hang
- Compute mount height from tight vertex bounds instead of M2 header bounds
- Dismount when entering combat or casting spells while mounted
- Prevent auto-attacking yourself when self-targeted
- Leave combat when 40+ yards from target, close vendor at 15+ yards
- Pre-open X11 display for reliable mouse release in signal handlers
2026-02-07 18:33:14 -08:00
Kelsi
643611ee79 Add mount system and crash mouse-release handler
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.
2026-02-07 17:59:40 -08:00
Kelsi
3c2a728ec4 Add taxi system, fix WMO interior lighting, ramp collision, and /unstuck
- 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
2026-02-07 16:59:20 -08:00
Kelsi
751e6fdbde Fix vendor buying, improve character select, parallelize WMO culling, and optimize collision
- 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
2026-02-07 15:29:19 -08:00
Kelsi
5bfe4b61aa Track player skills from update fields and display in character screen
Extract skill data from PLAYER_SKILL_INFO_1_1 update fields (636-1019), detect
skill increases with chat messages, and replace placeholder Skills tab with live
data grouped by category with progress bars.
2026-02-07 14:21:50 -08:00
Kelsi
cc6fa12157 Query item info for loot drops so names display instead of IDs 2026-02-07 14:00:56 -08:00
Kelsi
7afae3e768 Add human-readable inventory error messages from InventoryResult enum 2026-02-07 13:59:39 -08:00
kelsi davis
dfc4008ec7 Add Tier 8 commands: advanced targeting system
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.
2026-02-07 13:44:36 -08:00
kelsi davis
bca3f64af6 Add Tier 7 commands: combat and trade
Combat Commands:
- /duel - Challenge target to a duel (CMSG_DUEL_PROPOSED 0x166)
- /trade - Open trade window with target (CMSG_INITIATE_TRADE 0x116)
- /startattack - Begin auto-attacking target
- /stopattack - Stop auto-attacking
- /stopcasting - Cancel current spell cast

New opcodes:
- CMSG_DUEL_PROPOSED (0x166) for initiating duels
- CMSG_INITIATE_TRADE (0x116) for starting trades

Packet builders:
- DuelProposedPacket - sends duel challenge to target GUID
- InitiateTradePacket - sends trade request to target GUID
- AttackSwingPacket, AttackStopPacket, CancelCastPacket reused from existing

Game handler methods:
- proposeDuel(targetGuid) - challenge target to duel
- initiateTrade(targetGuid) - open trade with target
- stopCasting() - cancel current spell cast (uses existing casting state)

All commands include validation for target selection and world state.
Removed duplicate packet class definitions from previous phases.
2026-02-07 13:36:50 -08:00