Current working version:
0.7.0-alpha
This addon restores old TBC-era Blood Elf NPC voice lines in Midnight-era Quel'Thalas while muting the newer Midnight replacement voice set.
It also now includes a scoped Midnight Quel'Thalas music replacement layer for Silvermoon City, Eversong Woods, Sunstrider Isle, southern Eversong remastered subzones, Ruins of Deatholme, and selected interiors. That layer mutes tracked supported-zone music FileDataIDs, injects old TBC music on Master, temporarily forces native Sound_MusicVolume=0 while replacement music owns a supported region, and intentionally leaves unrelated zones native.
Main behavior:
- Mutes tracked Midnight Blood Elf voice FileDataIDs from
SoundData.lua - Plays TBC greet lines on left-click target selection
- Plays TBC greet lines on gossip open when a target-select greet did not just fire
- Plays TBC bye lines on gossip close
- Plays TBC bye lines when you click away from a previously greeted target
- Plays TBC pissed lines after repeated clicks on the same NPC
- Mutes tracked supported-zone music FileDataIDs from
SoundData.luaplus generated Midnight catalog data - Injects region-aware TBC intro/day/night music while you remain in supported Midnight Quel'Thalas zones
- Uses a shuffle-with-cooldown music picker so the same TBC music track is strongly discouraged from repeating immediately
Config.lua- User-editable policy layer
- Owns safe voice/music/UI policy knobs with commented examples and safety warnings
- Covers behavior timing, fallback scope/classification, built-in name/ID overrides, music routing/scope/timing, intro cooldowns, trace limits, and UI tuning
SoundData.lua- Holds all mute IDs for new Midnight voices
- Holds all old TBC male/female voice FileDataIDs
- Holds manual Midnight music seed IDs
- Holds supplemental supported-zone music mute IDs for non-Midnight Blizzard zonemusic
- Holds TBC Silvermoon intro/day/night music FileDataIDs
Debug.lua- DebugChatFrame integration + global
c()/cp()logging shortcuts - 2000-line ring-buffer log capture in
BElfVRDB.debugLog - Pre-init buffer for lines logged before
BElfVRDBexists - Copyable dump frame via
BElfVR_ShowLogDump() - Falls back to
print()when DebugChatFrame is not installed
- DebugChatFrame integration + global
BElfRestore.lua- Main addon logic
- UI
- Target/gossip event handling
- Zone/music event handling
- NPC classification
- Role and gender overrides
bloodElfRestore.toc- Correct TOC name matching the addon folder
- Loads
Midnight_ID_catalog.luabeforeSoundData.lua - Loads
Debug.luabeforeBElfRestore.lua
Midnight_ID_catalog.lua- Generated Midnight
mus_120_*music catalog used at runtime - Source-of-truth dataset for bulk Midnight music muting
- Generated Midnight
Midnight_ID_Index.md- Human-readable Midnight music family index generated from wowdev/wow-listfile
- Documents runtime exclusions and supplemental supported-zone notes
TBC_ID_CATALOG.lua- Generated TBC zone-music ID database for config/data authoring
- Includes Quel'Thalas focus (
Eversong,Ghostlands,Zulaman,Sunwell) - Includes Outland and key TBC instance music folders
TBC_ID_INDEX.md- Human-readable index and zone counts for the generated catalog
- Renamed the TOC to
bloodElfRestore.toc - Aligned
ADDON_NAMEwith the folder/TOC name (bloodElfRestore) - This fixed WoW not listing the addon at all
The addon now has an in-game UI window opened with:
/belr- Legacy alias:
/belvrstill maps to the same handler.
Current UI includes:
VoiceandMusictabs instead of one long control stack- Enable addon toggle
- Mute new Midnight VO toggle
- Verbose debug toggle
- Fallback classifier toggle
- Left-click greet toggle
- Invert NPC sex mapping toggle
- Status text
- Test buttons for male/female noble, standard, and military greet/bye/pissed
- Re-apply mutes
- Restore Midnight VO
- Music enable toggle
- Music mute toggle
- Music verbose debug toggle
- Music trace recorder toggle
- Music intro-on-entry toggle
- Music test buttons for intro/day/night
- Re-apply music mutes
- Clear music trace
- Restore Midnight music
- Force music refresh
- Optional semi-transparent panel background art (
assets/tbc_art.jpg) with tunable margins and manual X/Y art scaling
Behavior note:
Re-apply mutesnow also turns the mute option back on if it had been disabled- Hovering checkboxes now shows plain-English help text for non-technical users
- Verbose logs now include NPC names in key trigger messages
- Music trace logs are stored in SavedVariables, not in a standalone text file, and are written to disk on
/reloador logout - Music-tab action rows are anchored below the live music status text so status growth does not overlap the buttons
Original issue:
UnitRace("target")was not usable for these Midnight NPCs
Fixes added:
- Hidden tooltip scan for
"Blood Elf"text - Humanoid fallback classifier when race text is hidden
- Hidden-race humanoid fallback on target selection is limited to positive Blood Elf name/profile hints instead of generic humanoids
- The hidden-race humanoid fallback is now limited to Blood Elf zones so unrelated humanoids elsewhere do not get Blood Elf VO
- Built-in name profile fallback for repeated NPC names that hide useful metadata
Added:
PLAYER_TARGET_CHANGEDhandling so greet can fire on normal left-click target selection- Left-click target-select greet uses fake distance falloff buckets:
- close: always plays
- near: usually plays
- far: rarely plays
- out of range: never plays
- Dedupe window so right-click gossip does not immediately double-fire another greet
- Bye playback when target is cleared/switched away from a previously greeted NPC
- Target-loss bye now has both a minimum delay and a maximum believable age so late fly-away disengages do not still play point-blank farewell audio
Added:
- Saved per-NPC gender overrides
- Saved per-NPC role overrides
- Built-in default name-based profiles
Current built-in defaults (defined in Config.lua voice.profiles.byName):
Lyrendal- role:
standard, vendor greet category
- role:
Mahra Treebender- excluded from Blood Elf fallback classification
Silvermoon Resident- role:
standard
- role:
Doomsayer- role:
standard
- role:
Household Attendant- role:
standard
- role:
Cousin Slowhands,Mystic Birdhat,Collector Unta,Merchant Maku,Killia,Melanie Morten- excluded (mount service vendors, not Blood Elf NPCs)
Sin'dorei Child,Sin'dorei Children,Sindorei Child,Blood Elf Child,Silvermoon Child,Sin'dorei Orphan- excluded (no TBC child voice pool)
Manual override commands still exist:
/belr force male/belr force female/belr force clear/belr role military/belr role noble/belr role standard/belr role clear
Important:
/belr force ...and/belr role ...now apply to the current target's full unitGUID- This is intentional because Midnight can reuse the same
npc=...ID across different actual NPCs - Legacy saved
npc=...overrides are migrated once intoBElfVRDB.legacyOverrideBackup, then cleared so old bad mappings do not keep applying
New name-wide override commands also exist:
/belr force-name male/belr force-name female/belr force-name clear/belr invert/belr invert on/belr invert off/belr suppress/belr suppress on/belr suppress off/belr role-name military/belr role-name noble/belr role-name standard/belr role-name clear/belr verbose on/belr verbose off
These apply to every NPC that shares the current target's displayed name, which helps when
Blizzard uses multiple npc=... IDs for visually identical Midnight NPCs.
- TBC replacement playback now runs only when
Mute new Midnight VOis enabled - If muting is disabled, the addon stops injecting TBC lines so you do not hear both TBC and Midnight VO layered together
- Before playing a new injected TBC line, the addon stops the previous injected TBC sound handle to prevent overlap on rapid retargeting/clicks
- Injected TBC lines are also rate-limited with a short minimum gap, so rapid greet/bye/greet chains are suppressed instead of stacking
- Target-loss bye playback now waits for a short post-greet delay, so instant click-off does not overlap the greet but normal click-away still gets a bye
- Injected TBC playback can briefly suppress the native dialog channel and plays on
Masterto block unknown/untracked Midnight VO from stacking - Native dialog suppression is now user-toggleable for compatibility testing
- Event-driven playback applies the suppression window before the TBC rate-limit check, so even skipped replacement lines can still block a leaking native Midnight line
- Injected TBC playback now respects WoW sound disable states, including the usual
Ctrl+Ssound-effects toggle
- TBC replacement music runs only when
Enable addon logic,Enable replacement music logic, andMute tracked supported-zone music filesare all enabled - If tracked music muting is disabled, the addon stops injecting TBC music so native and TBC music do not stack
- Music ownership is now scoped to Midnight Quel'Thalas map lineage, not only broad zone text:
- zone name
- subzone name
- parent map lineage tokens
- Native-only guards now explicitly keep some areas on Blizzard music even if the parent zone would otherwise qualify:
Harandar
- Supported broad music routing currently includes:
Silvermoon CitySanctum of LightEversong Woods
- Region routing now groups playback into:
silvermoonsilvermoon_interioreversongsunstridereversong_southdeatholmeamani
- Supported subzone fallback and override routing now includes:
The BazaarWayfarer's Restmapped into the dedicatedsilvermoon_interiorfamilySunstrider IsleTranquillienSanctum of the Moon- several southern remastered subzones mapped into the
eversong_southfamily Ruins of Deatholmemapped into the dedicateddeatholmefamily- narrow token fallback for subzones containing
deatholme Amani Pass,Zeb'Nowa, andZeb'tela Ruinsmapped into the dedicatedamanifamily- dynamic pattern fallback for troll-style subzone names containing
amaniorzeb'
- The runtime mute set is now composed from three layers:
- generated Midnight
mus_120_*family coverage fromMidnight_ID_catalog.lua - manual non-catalog Midnight seed IDs in
BElfVR_NewMusicIDs(formus_1200_*and similar gaps) - supplemental Blizzard zonemusic IDs in
BElfVR_SupplementalMusicMuteIDsfor supported interiors such as inns / taverns
- generated Midnight
- Runtime Midnight catalog exclusions now intentionally preserve Harandar families:
harandar_1harandar_2harandar_3lightbloom_harandar
- The music system checks:
- zone changes
- indoor-like subzone changes
- resting state changes
- in-game day/night phase
- relevant
CVAR_UPDATEchanges
- An intro cue can optionally play on entry into supported zones before the day/night rotation
- Intro cues use a 10-minute cooldown persisted in SavedVariables so they do not spam on quick re-entry, including across relogs and game restarts
- Intro cooldown history is persisted in
BElfVRDB.musicIntroHistory, so/reloaddoes not reset the intro timer - Intro cooldown policy is read from
Config.luaand can be scoped by region, zone, subzone, area (zone||subzone), pool, and exact FileDataID - Known-duration tracks are now allowed to finish naturally instead of being cut off by the old coarse rotation timer
- Long stays in the same supported area still have fallback periodic rotation for unknown-duration cases
- The music shuffle system keeps recently played TBC tracks on a cooldown so the same track does not immediately repeat
- Playback routing now keys off a stable region + day/night signature instead of tiny subzone churn, which greatly reduces constant restarts while moving around Silvermoon
- Loading-screen arrivals into supported music space now arm a short world-entry settle window before addon playback is allowed to start
- Active injected-music ownership is now tracked separately from the player's current area context, so supported-region swaps can force an immediate handoff instead of waiting for the stale track to finish
- Injected replacement music currently plays on
Master, notMusic, so the addon can hard-suppress Blizzard's native music channel without cutting its own replacement track - The steady-state
Sound_MusicVolume=0suppression path was reinstated for supported replacement ownership after some Silvermoon load-screen arrivals kept native Midnight music alive through tracked muting and repeatedStopMusic()guards - Temporary audio-setting backups are persisted in
BElfVRDB.pendingCVarRestoresand restored on area exit, addon load,/reload, andPLAYER_LOGOUT Sound_EnableAmbiencesuppression remains a narrow Deatholme-specific fallback path, with the same persisted-restore safety- Ctrl+M and global music toggles now trigger immediate re-evaluation through
CVAR_UPDATEhandling - Intro cues are now queued only on true fresh supported-entry, not on every internal region swap
- Music debug output now indicates:
- support source
- scope source
- override source
- native-only state
- GUID parsing and debug logging now fail closed on protected or nonstandard gossip-object GUID values instead of assuming every interactable target is a normal creature GUID
/belr music stopnow creates a real manual stop state and stays idle until a meaningful resume trigger occurs- Slash music test commands now use the same region-aware pool selection as the live music system
/belr statusnow reports:- current music zone
- current subzone
- current region
- catalog counts
- supplemental counts
/belr music note <text>adds a one-line manual marker intomusicTraceLogwith current zone/subzone/region context (useful during high-speed flight mapping)- Music trace recording can capture:
- context changes
- support source (zone vs subzone)
- scope source
- override source
- selected pool
- selected track
- skip reasons
- unsupported-region exits
Original issue:
- Greet lines were mixed with vendor lines, so guards/residents could say vendor-only barks like "I have one of a kind items"
Fix applied:
- The TBC
greettables are now split internally into:vendorgreet
- Standard greet playback now uses only the non-vendor
greetsub-pool - This is split by role:
militarynoblestandard
Important:
- This split depends on the current ordering in
SoundData.lua - If the TBC sound lists are reordered, the layout offsets in
BElfRestore.luamust also be updated
Add them to:
BElfVR_NewVoiceIDsinSoundData.luaBElfVR_NewMusicIDsinSoundData.luafor manual music-specific non-catalog IDs such asmus_1200_*BElfVR_SupplementalMusicMuteIDsinSoundData.luafor non-Midnight Blizzard zonemusic that still appears inside supported Midnight Quel'Thalas interiors
Preferred workflow for Midnight music coverage:
- regenerate
Midnight_ID_catalog.luaandMidnight_ID_Index.md - keep broad family coverage in the generated catalog
- keep only true exceptions or non-catalog gaps in
SoundData.lua
Add them to:
BElfVR_TBCVoices_MaleBElfVR_TBCVoices_FemaleBElfVR_TBCMusic.introBElfVR_TBCMusic.dayBElfVR_TBCMusic.nightBElfVR_TBCMusicRegions.<region>.introBElfVR_TBCMusicRegions.<region>.dayBElfVR_TBCMusicRegions.<region>.night
TBC_ID_CATALOG.luaandTBC_ID_INDEX.mdare generated from wowdev/wow-listfile release202603051942.- Scope is TBC-era zone-music families (not every possible TBC-era asset path in the client).
- Use this catalog as the source-of-truth dataset for future
config.luarouting work. - Regeneration command:
tools/generate_tbc_catalog.ps1 -ListfilePath <community-listfile-withcapitals.csv> -ReleaseTag <release-tag>
Midnight_ID_catalog.luaandMidnight_ID_Index.mdare generated from wowdev/wow-listfile release202603061837.- Scope is Midnight music families under
sound/music/midnight/mus_120_*.mp3. - The generated catalog is now loaded at runtime before
SoundData.lua. - Runtime muting intentionally excludes Harandar families through
MIDNIGHT_CATALOG_MUTE_FAMILY_EXCLUSIONS. - Runtime muting also supplements the catalog with manual
mus_1200_*seeds and Blizzard tavern / inn zonemusic IDs for supported interiors. - Regeneration command:
tools/generate_midnight_catalog.ps1 -ListfilePath <community-listfile.csv> -ReleaseTag <release-tag>
Keep the current grouping/order:
- noble block first
- standard block second
- military block third
Inside each role block:
- keep vendor lines together
- keep greeting lines together
If that ordering changes, update the role layout tables in:
BElfRestore.lua
In Config.lua (read by BElfRestore.lua at startup):
voice.overrides.genderByNPCID→ buildsDEFAULT_GENDER_OVERRIDES- For known NPC IDs with wrong client-reported gender
voice.overrides.roleByNPCID→ buildsDEFAULT_ROLE_OVERRIDES- For known NPC IDs with wrong role classification
voice.profiles.byName→ buildsDEFAULT_NAME_PROFILES- For repeated NPC names that need fallback handling without exact IDs
- Supports
role, optionalvendor=true, and optionalexclude=true
BElfVRDB.guidGenderOverrides- User-saved gender overrides by full target GUID (best for exact individual NPCs)
BElfVRDB.guidRoleOverrides- User-saved role overrides by full target GUID (best for exact individual NPCs)
BElfVRDB.nameGenderOverrides- User-saved gender overrides by lowercase NPC name
BElfVRDB.nameRoleOverrides- User-saved role overrides by lowercase NPC name
BLOOD_ELF_MUSIC_ZONES- Lowercase zone names that should keep TBC music active
BLOOD_ELF_MUSIC_SUBZONES- Lowercase subzone names that should keep TBC music active even when Blizzard reports a different top-level zone
BLOOD_ELF_MUSIC_SCOPE_TOKENS- Normalized map-lineage / zone tokens that allow the music system to take control
BLOOD_ELF_MUSIC_NATIVE_ONLY_TOKENS- Normalized area tokens that must stay native even inside a broader supported parent zone
MUSIC_SUBZONE_REGION_OVERRIDES- Exact lowercase subzone names that should route into a different TBC region family
MUSIC_SUBZONE_REGION_TOKEN_OVERRIDES- Narrow token fallbacks for subzones whose exact names may drift slightly
MIDNIGHT_CATALOG_MUTE_FAMILY_EXCLUSIONS- Midnight catalog families that should stay native even though they exist in the generated dataset
BElfVR_SupplementalMusicMuteIDs- Non-Midnight Blizzard zonemusic IDs still worth muting inside supported interiors
BElfVRDB.musicTraceLog- User-captured music route trace buffer stored in SavedVariables
BElfVRDB.pendingCVarRestores- Persisted temporary audio-setting backups for recovery after
/reloador logout
- Persisted temporary audio-setting backups for recovery after
BElfVRDB.musicIntroHistory- Persisted intro cooldown timestamps keyed by config bucket (
default,region:...,pool:...,track:..., etc.)
- Persisted intro cooldown timestamps keyed by config bucket (
- Some Midnight NPCs hide race text entirely
- Some NPCs may report the wrong sex from the client (
UnitSex) - Current behavior treats Midnight Blood Elf
UnitSexas reversed by default - The UI includes an
Invert NPC sex mappingtoggle to flip back if Blizzard data is correct for a given case - Hidden-race fallback is intentionally zone-limited and should not be trusted as a global classifier
- Name-based role heuristics are simple:
- names containing
guard,ranger,captain,blood knight,champion->military - names containing
lord,lady,noble->noble - otherwise ->
standard
- names containing
- Music replacement is a first-pass addon-side injector, not a true engine-level replacement of Blizzard's internal zone-music resolver
- The addon can log area context changes for music, but it cannot reliably read the exact native Midnight music FileDataID that Blizzard's engine picked at runtime
- The generated Midnight catalog covers
mus_120_*families only; anonymousmus_1200_*IDs and non-listfile SoundKit playback still need manual discovery - Track rotation currently uses a configurable approximate timer, because addon Lua does not get a clean "this injected FileDataID finished" callback for this playback path
- The music trace recorder is a capped ring buffer and intentionally trims old entries; it is meant for focused capture sessions, not permanent long-term logging
- Add a richer role model if needed:
- vendor
- questgiver
- trainer
- civilian
- Add more built-in Midnight Silvermoon NPC overrides by exact
npc=...IDs - Add more comments near role layout offsets if more community editing is expected
- Consider deprecating the old
genderOverrides/roleOverridessaved-variable fields entirely in a cleanup pass - Expand the Midnight Quel'Thalas scope tokens, native-only tokens, and subzone allow-lists from recorded trace sessions
- Use recorded trace sessions to identify additional anonymous
mus_1200_*or non-listfile music playback that still leaks through
This session added full DebugChatFrame integration, a persistent debug log system, and fixed the long-standing intro music bug.
- Added
Debug.luaas a new file loaded beforeBElfRestore.lua - Integrates with the optional DebugChatFrame addon for a dedicated
BElfVRchat tab - Provides global
c(...)for standard logging andcp(moduleName, ...)for module-prefixed logging - Falls back to
print()when DebugChatFrame is not installed - All
c()/cp()output is also captured to a 2000-line ring buffer inBElfVRDB.debugLog - Pre-init buffer holds lines logged before
ADDON_LOADEDand flushes them onceBElfVR_InitDebug()runs - Includes programmatic
LoadAddOn("DebugChatFrame")fallback for both modern (C_AddOns) and legacy API paths BElfVR_InitDebug()is called from theADDON_LOADEDblock inBElfRestore.lua
- Added
/belr dumplog(also/belr dump) — opens a draggable, scrollable EditBox frame with the full ring-buffer contents - Users can
Ctrl+AthenCtrl+Cto copy the entire log - Added
/belr log clearto wipe the buffer - The raw log is also available at
WTF/Account/<ACCOUNT>/SavedVariables/bloodElfRestore.luaafter logout
- Added
c()calls at all major event handlers inBElfRestore.lua:ADDON_LOADED,PLAYER_LOGIN,PLAYER_ENTERING_WORLD,PLAYER_TARGET_CHANGEDGOSSIP_SHOW,GOSSIP_CLOSED, zone changes,CVAR_UPDATE,PLAYER_LOGOUT
- Bridged existing
Log()→c("Voice", ...)andLogMusic()→c("Music", ...)so all existing verbose output also routes to DebugChatFrame - Added entry logging to
PlayRandomTBC(),ApplyMutes(), andEvaluateMusicState() - Filtered
CVAR_UPDATElogging toSound_*CVars only (camera, perks, splash screen CVars are ignored) - Suppressed
EvaluateMusicState: periodicheartbeat logging (~1s interval) to prevent log flooding
Root cause: loading-screen arrivals (login, reload, zone portals) always set musicSkipIntroOnWorldEntry = true, which unconditionally bypassed the cooldown system. The intro could never play on any entry that came through a loading screen — which is every login and most zone transitions.
Fix:
- Removed the unconditional intro skip for loading-screen arrivals
- All supported-zone entries now queue the intro via
ShouldQueueMusicIntro()and defer toShouldPlayMusicIntro()for cooldown enforcement - The existing 10-minute SavedVariables-persisted cooldown (
MUSIC_INTRO_REPEAT_COOLDOWN = 600) prevents spam across rapid relogs - The world-entry settle window no longer clears
musicIntroPending, so the intro survives the brief startup purge delay
Result: first login of the day → intro plays. Quick relog → cooldown blocks it, plays day/night track. Come back after 10+ minutes → intro plays again.
- Added
.luarc.jsonwith WoW API global declarations for Lua language server (gitignored) - Updated
.gitignorewith.luarc.json
This session added dedicated Silvermoon City interior music support and resolved several README-to-code discrepancies found during a full cross-reference review.
What changed:
- Added
silvermoon_interiormusic region with GL_ScenicWalk TBC tracks (53513,53514,53515) inSoundData.lua - Added
IsIndoors()detection inGetMusicContext():- When the player is inside Silvermoon City and
IsIndoors()returns true, the region swaps fromsilvermoontosilvermoon_interior - Explicit subzone overrides still win over the
IsIndoors()fallback - Walking back outside returns to the normal
silvermoonoutdoor day/night cycle - The
ZONE_CHANGED_INDOORSevent (already registered) triggers re-evaluation automatically
- When the player is inside Silvermoon City and
- Added
Wayfarer's Restas an explicit supported subzone inConfig.luawithsilvermoon_interiorrouting - Added fallback in
GetMusicTrackPool()so emptysilvermoon_interiorcategories (like intro) fall back to the regular Silvermoon outdoor chain, then to the legacyBElfVR_TBCMusicglobal pool - Added
MUSIC_REGION_SILVERMOON_INTERIORconstant inBElfRestore.lua
Documentation fixes from the cross-reference review:
- Fixed
README.mdLICENSE link from an absolute Windows path to a relative[LICENSE](LICENSE)link - Fixed
README.mdscope config attribution fromBElfRestore.luatoConfig.lua(line 103) - Added all six voice test slash commands to
README.mdCommands section - Added Installation and Addon Structure sections to
README.mdwith a folder tree and TOC load order - Updated interior and region routing descriptions across
README.mdandDEV_NOTES.md
Known limitation:
IsIndoors()returns nil for large indoor spaces where WoW allows mounting, so some Silvermoon interiors may not trigger the swap- Interiors that change native Midnight music without any zone/subzone text change or
IsIndoors()flag cannot be detected by addon Lua - Additional interior subzones can be added to
Config.luabySubZonerouting as they are discovered during testing
This follow-up came after the Silvermoon world-entry overlap fix, when two more regressions showed up during live retesting:
- moving between supported Quel'Thalas music regions could keep the old injected TBC track playing until its natural end instead of handing off immediately
- interacting with a non-NPC dungeon gossip object (
Light-Starved Blossom) triggered a taint/secret-string error path while the addon tried to parse and log the target GUID like a normal creature
What changed:
- Split music state into two responsibilities:
- current player context (
musicCurrentAreaKey,musicCurrentRegionKey) - currently playing injected track ownership (
musicPlaybackAreaKey,musicPlaybackRegionKey)
- current player context (
- Supported-region swaps now compare the active injected track's ownership against the live player context and force an immediate music handoff when they diverge
- Added explicit verbose tracing for playback/context mismatch swaps so future region-handoff bugs are easier to spot in
music verbose - Hardened
GetNPCIDFromGUID()with protected-call parsing so nonstandard or protected GUID values fail closed instead of exploding onstrsplit - Added guarded debug-string formatting so logging protected GUID-like values no longer taints or crashes gossip/object interactions
Practical outcome:
- traveling from
Silvermoon CitytoSunstrider Isleand similar supported-region swaps now changes TBC music immediately - gossip objects and non-creature interactables no longer crash the addon just because
UnitGUID()returned a protected or non-creature value
This follow-up was specifically for the stubborn Silvermoon double-music bug that still happened on reload, hearth, teleport, and other loading-screen arrivals after the broader 0.6.1-alpha hotfix pass.
Observed failure mode:
- Native Midnight Silvermoon music could survive:
- tracked music FileDataID muting
- startup music purge ordering
- repeated
StopMusic()guards - delayed world-entry settle windows
- The overlap was easiest to reproduce on
ZONE_CHANGED_NEW_AREAarrivals intoSilvermoon City, where Blizzard's native track would keep playing underneath injected TBC day music.
What changed:
- Added explicit world-entry settle handling for supported music arrivals:
- pending world-entry tracking across loading screens
- intro suppression for loading-screen arrivals
- short post-arrival settle window before replacement playback is allowed
- repeated native
StopMusic()guard pulses during the settle window - direct
ZONE_CHANGED_NEW_AREAarming so the fix does not depend on Blizzard event ordering
- Reverted supported-zone replacement playback back to
Master - Re-enabled supported-zone steady-state native suppression through
Sound_MusicVolume=0 - Kept persisted restore safety for temporary audio CVars so the player's previous values still recover on exit, reload, addon load, and logout
Practical outcome:
- Silvermoon reload, teleport, and hearth arrivals no longer stack Midnight native music with old TBC replacement music
- The earlier "play on
Musicand avoid slider hijacking" model is no longer the active runtime design
Tradeoff:
- While supported replacement music is active, the user's music slider no longer directly controls the injected TBC track because playback is back on
Master
This session was the large cleanup after repeated music-overlap regressions in Deatholme, Harandar, and Silvermoon interiors.
It also included a post-refactor load recovery after the new Config.lua policy extraction briefly pushed BElfRestore.lua over WoW's chunk-local limit and introduced a few ordering/syntax regressions.
What changed:
- Tightened music ownership to Midnight Quel'Thalas only:
- added map-lineage scope gating
- added native-only exclusion tokens
- kept Harandar native
- Fixed Deatholme routing regressions:
- restored exact
Ruins of Deatholmerouting - added
deatholmetoken fallback for small subzone-name shifts - re-darkened the dedicated TBC
deatholmeday pool
- restored exact
- Reworked tracked music muting from a partial hand-maintained list into a generated-catalog model:
- added
Midnight_ID_catalog.lua - added
Midnight_ID_Index.md - added
tools/generate_midnight_catalog.ps1 - updated
bloodElfRestore.tocto load the generated catalog beforeSoundData.lua
- added
- Converted runtime Midnight muting to broad family coverage with explicit exclusions instead of hand-adding one family at a time:
- Harandar families are now excluded at the family level
- non-catalog
mus_1200_*gaps still live inBElfVR_NewMusicIDs
- Fixed Silvermoon inn overlap:
- added
BElfVR_SupplementalMusicMuteIDs - currently includes Blizzard tavern / inn / rest-area zonemusic IDs
53737-53778 - these supplemental IDs are only applied while the addon owns a supported music region
- added
- Removed global login-time music muting:
- old
ApplyMutes/RemoveMutesmusic behavior was too broad - all music muting now flows through
SetTrackedMusicMutesActive - muting is now strictly region-scoped
- old
- Reworked mute-list building:
- added helper logic to build one deduped base mute set
- base set now includes catalog-backed Midnight data plus supplemental supported-zone data
- optional region-specific extra mutes can still be layered on top
- Fixed music slider and temporary-audio-setting safety:
- replacement music now plays on
Music, notMaster - steady-state slider hijacking is disabled
- persisted restore values were added for
Sound_MusicVolume - persisted restore values were added for
Sound_EnableAmbience - persisted restore values were added for
Sound_EnableDialog - recovery runs on addon load and
PLAYER_LOGOUT - this
Music-channel model was later reverted on2026-03-08after Silvermoon load-screen arrivals still produced native+TBC overlap
- replacement music now plays on
- Expanded the real user-editable config surface:
- created
Config.lua - moved safe voice/music/UI policy tables out of hardcoded runtime blocks
- moved intro cooldown matching out of transient runtime-only state
- persisted intro cooldown history in
BElfVRDB.musicIntroHistory - intro cooldown rules can now be scoped by region, zone, subzone, area, pool, and exact FileDataID
- role heuristics, scope tokens, supported zones/subzones, region routing, built-in name profiles, trace limits, and UI art/layout settings are now config-backed
- created
- Expanded live debugging and status output:
- context lines now include
scope,scopeSource,overrideSource, andnativeOnly /belr statusnow reports catalog counts and supplemental mute counts- UI text now refers to tracked supported-zone music instead of tracked Midnight Silvermoon music
- context lines now include
Removed or superseded behavior:
- Removed the assumption that music problems were only Silvermoon / Eversong problems
- Removed the old "mute everything globally and hope it is fine" music path
- Removed the old documentation assumption that replacement music intentionally used
MasterwithSound_MusicVolume=0in steady-state- this was accurate for the 2026-03-07 runtime, but was later reversed by the 2026-03-08 Silvermoon world-entry fix
Current practical debugging rule:
- If a leak is inside supported Midnight Quel'Thalas and
Music muted IDslooks correct in/belr status, the next suspect is usually:- anonymous
mus_1200_* - non-listfile Blizzard zonemusic
- SoundKit-style playback not visible in the Midnight catalog
- anonymous
Low-risk cleanup pass applied in BElfRestore.lua after review triage:
- Removed unused
local addon = {}declaration near the top of the file. - Removed dead fallback-zone entry
["zul'aman"] = falsefromBLOOD_ELF_FALLBACK_ZONES. - Added an early
OnUpdateshort-circuit:if not IsMusicReplacementActive() then return end- This avoids periodic music evaluation work while replacement music is disabled/unmuted.
Notes:
- No behavior-changing refactors were done in this pass.
- Potential larger refactors (voice pool structural enforcement, trace-buffer internals) remain optional and were intentionally deferred.
Implemented a focused music-routing and trace tooling pass:
- Replaced active southern routing semantics from
ghostlandstoeversong_south. - Added dedicated
deatholmerouting forRuins of Deatholmewith a narrow dark pool. - Added compatibility handling so legacy
BElfVR_TBCMusicRegions.ghostlandsdata is still consumed aseversong_south. - Added
/belr music note <text>to write manual markers into the SavedVariables music trace with current zone/subzone/region context. - Added
amaniregional routing for Amani/Zeb-style subzones and mapped it to verified Zul'Aman ambient IDs (53825-53830) inSoundData.lua. - Updated docs and in-game help text for the new routing names and command.
Data note:
- No speculative Midnight mute IDs were added in this pass. Native leak spots are still expected to require additional verified IDs from future focused trace/datamine passes.