promotional bannermobile promotional banner

Resonance

Mute or replace spell sounds, character and creature vocalizations, and weapon impacts. Works with any class. Important for players with sensory hypersensitivity.

File Details

v1.9.1

  • R
  • Jun 16, 2026
  • 3.82 MB
  • 356
  • 12.0.7+4
  • Classic + 2

File Name

Resonance-v1.9.1.zip

Supported Versions

  • 12.0.7
  • 12.0.5
  • 12.0.1
  • 2.5.5
  • 1.15.8

Changelog

v1.9.1

Compatibility

  • Updated for WoW 12.0.7 (Midnight). Bumped the retail TOC interface (Resonance and Resonance_Data) to 120007 so the addon loads without the out-of-date flag on patch 12.0.7. No code changes were needed — none of the patch's API changes touch Resonance's code paths.

v1.9.0

New Features

  • Ranged sound override (Hunter). New "Auto Shot sound source" dropdown decouples the classicAutoShot engine from the equipped weapon: choose Auto, Always bow, or Always gun. Resolves Noshei's CurseForge request for cross-type substitution (e.g., gunfire → bow on TBC). An advanced toggle exposes Always crossbow for users who want to split crossbow out of the bow pool. Existing classicAutoShot=true users get "auto" injected on first load — behavior unchanged unless explicitly overridden.
  • Sheathe sound replacement. Mute Blizzard's per-material sheathe / draw sounds and play user-chosen replacements on sheath state transitions. Resolves Arcane_Duskwhisper's CurseForge request for replaceable melee sheathe sounds. Mute and replace are independent toggles; either can be on without the other. Four simple-mode slots (melee draw, melee sheathe, ranged draw, ranged sheathe), each opt-in — fill only the transitions you want to replace, leave the rest blank to keep Blizzard's default; Advanced... button opens a popup with per-material overrides (5 materials × 2 states). Per-material data vendored from LibSoundIndex (MIT, credited in LICENSES.md).
  • Sheath module flavor guard. If GetSheathState or ToggleSheath is missing on a flavor, the sheathe module fails closed (no event registration, no Lua errors) and logs once; ranged override remains functional. Ships on retail, TBC, and Vanilla.

Implementation Notes

  • ToggleSheath secure hook is installed exactly once at addon load and persists for the session — disabling the feature makes the hook callback inert rather than uninstalling (secure hooks cannot be removed).
  • C_Timer.After(0) deferred state checks are guarded by an explicit sheatheCheckPending flag (Lua's C_Timer does not auto-coalesce) and a generation token that invalidates in-flight callbacks on disable / profile switch.
  • GetSheathState() mapping is 1=none/sheathed, 2=melee drawn, 3=ranged drawn (verified via Blizzard_SharedXMLBase/ModelSceneUtil.lua). Initial-state seeding on PLAYER_ENTERING_WORLD prevents the first sheathe action after login from being eaten by the no-dispatch-on-nil rule.
  • Per-material routing is best-effort from item subclass; may not exactly match Blizzard's per-model classification. Falls back to simple-mode slots on unknown materials.

v1.8.0

New Features

  • Data-driven flavor capability table (Resonance.Flavor). Replaces scattered IS_TBC / IS_VANILLA / IS_CLASSIC runtime checks with a single capability profile per flavor: muteMode, supportsPrecastMute, supportsClassPresets, supportsNPCBrowser, registersCLEUForImpacts, registersSpellCastSent, unavailableProfessions, etc. Adding a new WoW flavor (e.g. Wrath Anniversary) is now a single profile entry in FLAVOR_PROFILES instead of auditing dozens of branches. Legacy IS_* aliases retained for now; new code should query Resonance.Flavor.X.
  • Aggressive cast-start mute (opt-in, Classic). General-tab toggle persistently mutes the cast-initiation FIDs (cast_start / channel_start / precast events) for every configured spell, eliminating the first-cast leak that the transient mute path can't catch — WoW plays cast-start audio synchronously inside the engine's cast-initiation C call, before any Lua hook (including UNIT_SPELLCAST_SENT) runs. New Resonance_SpellEarlyFIDs table emitted by tools/spell_sounds.py (filtered to SpellVisualEvent.StartEvent in {1,3,5}) drives this; the toggle's tooltip warns that cast-start FIDs are shared across same-school spells (enabling for Fireball also silences other fire spells' cast-start audio). Off by default — existing users see no change unless they opt in.
  • TBC Anniversary + Vanilla Anniversary support. Resonance now ships three flavors: retail, TBC (Interface 20505, build wow_anniversary 2.5.5.66765), and Vanilla (Interface 11508, build wow_classic_era 1.15.8.66129). Each flavor has its own TOC + data set: SpellMuteData, SpellSounds, MountSoundData, AmbientSoundData. Mute-on-cast, character vox, ambient, mount, profession, weapon-impact, and FileDataID muting all work on Classic. Mount Sounds tab is available on both Classic flavors via cross-flavor extraction (vanilla uses its own AURA_MOUNTED DisplayID chain plus retail fallback for max coverage — 92 mounts on Vanilla, more on TBC).
  • Transient cast-window mute on Classic. Classic spell visuals reuse generic sound FIDs across thousands of spells (one "magic cast" FID is shared by ~2,800 spells), so persistent global muting silences too much. Classic now mutes the spell's default FIDs only during the cast window via UNIT_SPELLCAST_SENT, then unmutes after 5s. Collateral mute is scoped to the cast window instead of forever. The over-shared filter is dropped on Classic — TBC SpellMuteData grew from 5,767 → 17,422 entries, Vanilla generates 18,350. Stale transient mutes from /reload mid-cast are drained at OnEnable via db._lastTransientFIDs. Refreshed at UNIT_SPELLCAST_CHANNEL_START so long channels (Drain Soul, Tranquility, Mind Flay) keep their default sounds muted across the full channel duration.
  • First-cast warm-up on Classic. WoW's audio system silently defers MuteSoundFile for FIDs it hasn't yet seen, so the very first cast of a configured spell in a session would leak through. warmUpTransientFIDs() cycles MuteSoundFile / UnmuteSoundFile for each configured spell's FIDs at OnEnable to register them with the engine, so the next mute (at cast time) applies immediately.

Fixes

  • Refcount inflation across /reload (transient + precast mutes). Both layers now gate MuteSoundFile on a saved-variable snapshot (db._lastTransientFIDs / db._lastPrecastFIDs) instead of the in-memory ticker. WoW's MuteSoundFile calls survive /reload but the in-memory tables don't, so without the snapshot gate every /reload mid-cast (or every opt-in cycle) added +1 to the engine refcount with no matching unmute — eventually FIDs would get permanently stuck muted. Snapshots are drained at OnEnable and on toggle-off.
  • /res off no longer destroys saved muting config. The disable path used to wipe mutedNPCs, mutedMounts, muteCreatureVox, muteAmbientSounds, muteProfessionSounds and reset muteWeaponImpacts/muteVocalizations/classicAutoShot — so a user toggling off to A/B compare audio lost their entire curated muting config. Disable now only flips the master db.enabled flag and unmutes live FIDs; saved preferences persist. The General-tab master toggle, /res off, and the LDB minimap right-click all share a single canonical Resonance.disableEverything() / enableEverything() pair (previously each had its own drifted copy with different bugs — the LDB version was missing applyMountMutes, clearPrecastMutes, clearMountMutes, and clearAmbientMutes).
  • /res checkfid output is now fully localized (was a mix of localized and hardcoded English) and references to a non-existent /res testfid are removed.
  • Per-cast string-parse hot path for getSpellMuteFIDs is now cached per spell ID. Resonance.SpellMuteData[sid] is parsed once via gmatch and the result is reused on subsequent casts; previously a Mage spamming Fireball would re-parse the same comma-separated FID string several times per second.
  • playOneSoundWithUnmute respects transientMutedFIDs and precastMutedFIDs in both the muted-detection check and the post-playback re-mute restoration. Without this, playing a sound that overlapped a muted FID would over-unmute and leave the FID audible.
  • Classic stale snapshot cleanup: with a stale _lastAutoMutedFIDs snapshot from a prior retail-style session, OnEnable no longer re-applies persistent mutes via reapplyAutoMutesFromSnapshot — it falls through to loadDataAddon so rebuildAutoMutes can drain the stale snapshot cleanly.

UX

  • "Aggressive cast-start mute (opt-in)" toggle (was "Mute precast sounds (Classic)") leads the description with the symptom rather than the developer-facing rationale, and color-codes the trade-off paragraph. Toggling now prints a confirmation message unconditionally.
  • Tab reorder: General → Spell Sounds → Sound Browser → Custom Sounds → Muting → Mount Sounds → Ambient → Alerts → Presets → Profiles. Sound Browser is no longer 8th; Custom Sounds groups with file-management.
  • Class Presets and Clear Presets buttons hidden on Classic flavors — class templates target retail spells/specs and Clear Presets is a no-op without templates. Add Spell anchors directly to Clear All on Classic, keeping the row uncluttered.
  • Spell input placeholder ("e.g. 6343 or Mortal Strike") is now localized, plus the handleCheckfidCommand debug strings.
  • tools/spell_sounds.py --build {tbc,classic}: build aliases for wow_anniversary and wow_classic_era. Emits flavor-suffixed SpellMuteData_TBC.lua / SpellMuteData_Vanilla.lua. New --max-fid-sharing CLI flag (default 100; pass a large value to disable the over-shared filter for transient-mute Classic builds). Vox-data and weapon-data extraction are wrapped in try/except so missing or differently-shaped DB2 tables on Classic flavors don't fail the whole pipeline. CSV downloader passes &product= alongside ?build= for unambiguous routing on wago.tools. New tools/generate_vanilla_data.py builds vanilla-specific Mount/Ambient/SpellSounds files.
  • Runtime flavor detection (Resonance.IS_RETAIL / IS_TBC / IS_VANILLA / IS_WRATH / IS_CATA / IS_MISTS / IS_CLASSIC) in Core.lua. Used to gate Mount-related UI, profession exclusions (Jewelcrafting hidden on Vanilla, Inscription hidden on TBC + Vanilla), COMBAT_LOG_EVENT_UNFILTERED registration for impact sounds on Classic, and the transient mute path.

v1.7.0

New Features

  • Impact sounds — layered delayed playback for travel-time spells: New Impact tab in the spell editor. Configure a list of {delay, sound} entries that fire after cast-complete, staggered by delay. Intended for travel-time spells like Wrath, Frostbolt, Starsurge where the modern sound plays at cast rather than at target arrival. Per-entry delay is editable inline in each row. Since 12.0.x removed addon access to SPELL_DAMAGE/CombatLogGetCurrentEventInfo, real impact detection isn't possible — impact delays are user-tuned fixed offsets.
  • Precast auto-stops at cast end: The precast sound now stops exactly when the cast bar ends, regardless of the sound's natural length, via UNIT_SPELLCAST_STOP. Covers successful completion, player cancel, enemy interrupt, and spell-fail (e.g. moving during cast). No more manual cfg.precastDuration tuning — and no more sound bleeding past the cast. cfg.precastDuration still works as a shorter ceiling if set.
  • "Add Class Presets" / "Refresh Class Presets" button: One-click preset for the player's current class, in the Spell Sounds tab next to Clear Presets. Label and tooltip flip based on whether the class's preset is already applied:
    • Add: loads the built-in preset with recommended per-spell sound replacements
    • Refresh: re-applies to pick up new spells and updated auto-mute data from the latest template, without wiping user-customised sounds
  • Complete slash-command palette (/res reorganisation): Every per-spell field the GUI edits is now reachable via chat commands with a consistent subject → verb → args structure. Each phase command accepts an optional horde/alliance trailing argument to write to a faction-specific override bundle.
    /res cast    add|list|remove|clear|mode|loop|duration <spellID> [...] [horde|alliance]
    /res precast add|list|remove|clear|mode|loop|duration <spellID> [...] [horde|alliance]
    /res impact  add|list|remove|clear                     <spellID> [...] [horde|alliance]
    /res trigger  <spellID> cast|precast|both
    /res channel  <spellID> Master|SFX|Dialog|Music|Ambience|off
    /res multihit <spellID> <seconds|off>
    /res unmute   add|list|remove|clear <spellID> [<fileDataID>]
    /res spell    show|remove           <spellID>
    
  • Faction GUI expansion — horde/alliance cast + precast: The Advanced Options → Faction-specific sounds section now has four inputs (Horde cast, Horde precast, Alliance cast, Alliance precast) instead of two. Editor writes to the nested cfg.horde / cfg.alliance bundle (new data model); legacy cfg.hordeSound / cfg.allianceSound are lifted into the bundle on first load. Faction impact lists are still slash-only (/res impact add <spellID> <delay> <sound> horde|alliance); they survive GUI save round-trips intact.
  • Search-by-name input on the Impact tab: Matching Cast/Precast tabs, the Impact tab has the same Browse (name autocomplete) and File Path / FID input modes, plus a persistent Delay field shared between both modes.
  • Patch 12.0.5 support: TOC declares compatibility with both live (12.0.1) and 12.0.5 (## Interface: 120001, 120005). Spell mute data, mount/NPC/creature-vox/profession data regenerated from build wowt 12.0.5.67088 — covers Midnight 12.0.5 spells (Battle Visage, Explosive Shot, Sanguine Vial, Tigereye Brew redesign, Voidforge / Void Assault content, etc.).
  • /res spell show <spellID>: New diagnostic dump — prints the full spell_config entry including faction overrides, impact list, exclusions, and trigger.
  • Editor tab order now follows cast lifecycle: Precast → Cast Complete → Impact → Muted (was Cast → Precast → Impact → Muted).

Bug Fixes

  • Precast sound dropdown button was mislabelled (reported on CurseForge): The "+ Mute" button with pass-skip icon in the precast Browse autocomplete was actually calling the add action — it always added the sound when clicked, the label just hid that. Fixed to + Add with a plus icon.
  • Battle Shout / Rallying Cry / Intimidating Shout / Demoralizing Shout weren't auto-muting their modern roar. The Revamp BattleRoar FIDs are shared across ~240 buff/rage spells (Bloodlust, Frenzied Regeneration, Ancient Hysteria, NPC variants, etc.) so --max-fid-sharing=100 stripped them from SpellMuteData. Added explicit muteFIDs in the Warrior template so applying the preset mutes those FIDs regardless of the sharing filter. Matches the existing fix pattern for Shield Slam / Pummel / Rend / Colossus Smash from earlier versions.
  • Starfire / Starsurge Lunar precast loop wasn't muted. Same root cause — spell_dr_revamp_lunar_precast_loop_01 (FID 1597782) is used by 114 Balance spells, filtered from SpellMuteData. Added muteFIDs = {1597782} to both Starfire (194153) and Starsurge (197626 + 78674) templates.
  • Spam-cast Wrath: second impact sound didn't fire. The multi-hit-window debounce (default 1.5s) was returning early in UNIT_SPELLCAST_SUCCEEDED before impact scheduling, so a rapid recast under heavy haste dropped its impact. Impact scheduling is now extracted into scheduleImpactsForCast and runs before the debounce — debounce only affects the main cast sound, as intended.
  • Precast sound list: first-added sound didn't appear in the list. WoW 12.x added a stricter SetPoint check that exposed a latent bug where the empty-state row (with only a text FontString) was reused as the first data row (which needs playBtn/removeBtn too). Fixed by detecting the empty-state row and upgrading it with the missing widgets.
  • GUI save was dropping cfg.muteFIDs. Pre-existing bug: opening and saving a spell in the editor wiped cfg.muteFIDs (populated by class templates — e.g. Warrior Battle Shout's forced-mute FIDs). Would be re-filled on next login by refreshPresetsFromTemplates, but mutes wouldn't apply in the interim. Now preserved verbatim across GUI save.
  • Template refresh now propagates new shape fields to existing preset entries. Previously refreshPresetsFromTemplates only updated muteExclusions / muteFIDs / multiHitWindow on existing preset-sourced spells. New template fields like precastSound, trigger, impacts never reached users who already had the spell configured — the Precast/Impact tabs would show empty even after "Refresh Class Presets". Now fills in any missing (nil) shape field from the template while preserving user-customised values (nil-check, not truthy-check, so explicit cfg.sound = false survives).
  • Addon could fail to register silently ("/res does nothing") after growing enough slash-command helpers. Lua's 60-upvalue-per-function cap was being approached by Resonance:ChatCommand. Extracted the command handlers (handleImpactCommand, handleTriggerCommand, handleChannelCommand, handleOnCommand, handleOffCommand, handleDiagCommand, etc.) into file-scope functions. Also added tools/check_upvalues.sh + make check-upvalues target so CI catches approach-to-cap at lint time — WARN at 45, FAIL at the 60 cap.
  • Options.lua stays under Lua's 200-local-per-function cap. The faction + impact GUI expansion pushed the enclosing buildTab2_SpellSounds over 200; bundled editor state into editorFaction + factionRows tables so adding more fields doesn't multiply local count.
  • Snapshot invalidation on template updates: when the template introduces new muteFIDs and a user is mid-session without having opened Options (i.e., Resonance_Data not loaded), the auto-mute snapshot would be reapplied on login without the new FIDs. refreshPresetsFromTemplates now invalidates the snapshot when changes are detected, forcing loadDataAddon → rebuildAutoMutes so template-added mutes take effect that session.
  • cfg.hordeSound edge case in migration: migrateFaction previously could drop cfg.hordeSound if a cfg happened to have both the legacy flat field and a faction bundle without .sound set. Now merges the legacy value into the bundle when bundle lacks .sound.

Data updates

  • Regenerated SpellMuteData.lua, MountSoundData.lua, NPCSoundData.lua, CreatureVoxData.lua, ProfessionSoundData.lua from 12.0.5 build — 137K+ spells touched, covers 12.0.5 content (new spells, Void Assault zones, Ritual Sites).
  • Removed dead orphan data/MountSoundData.lua (was duplicated between repo-root and Resonance_Data/data/; only the latter is loaded by the TOC).
  • Druid Wrath / Starsurge / Starfire / Starfall template updates:
    • Wrath (5176): three-phase classic restoration — precast lifedrainloop, cast naturecast, impact (+1.0s) lightningboltimpact.
    • Starsurge (197626 + 78674 variant): precast lifedrainloop, cast druid_starfallmissile1 (unchanged), impact (+0.5s) starfireimpact, muteFIDs = {1597782}.
    • Starfire (194153): precast lifedrainloop, cast starfireimpact (unchanged), muteFIDs = {1597782}.
    • Starfall (191034): sound changed from StarFireImpact.ogg (wrong — that's Starfire's) to a random pool of the dedicated druid_starfallmissile1/2/3 FIDs.
  • Army of the Dead (42650) removed from the Death Knight template — modern spell is a single quick cast, and the shadowprecasthigh replacement was noticeably too long.

Localisation

  • 141 new user-facing strings wrapped in L[...] and declared in the enUS/enGB block for strict validator compliance.
  • 18 GUI-visible strings translated into all 9 non-English locales (ptBR, deDE, frFR, esES/esMX, itIT, ruRU, koKR, zhCN, zhTW). Spell-name references cross-checked against wago.tools SpellName DB2 for build 12.0.5.67088 (Wrath → Zorn / Colère / Ira / Ira Silvana / Cólera / Гнев / 천벌 / 愤怒 / 憤怒).
  • Remaining ~123 slash-command usage/diagnostic strings get enUS entries and fall back to English via the metatable in other locales — consistent with existing behaviour for command-line output.

Breaking changes

  • /res duration <spellID> <seconds|off> is removed. Use /res cast duration <spellID> <seconds|off> (and /res precast duration ... for the precast phase).
  • Legacy cfg.hordeSound / cfg.allianceSound / cfg.impactSound / cfg.impactDelay / cfg.impactDuration fields are no longer written on save — they migrate into cfg.horde / cfg.alliance bundles and cfg.impacts[] list respectively. Old saved-vars format still reads correctly via one-shot migration (migrateFaction, migrateImpacts), and the playback path has a legacy-field fallback for defence in depth.

v1.6.1

New Features

  • Addon-manager-safe vanilla sound folder: Extracted vanilla/TBC/Wrath sound files can now live in Interface/AddOns/Resonance_Sounds/vanilla/ instead of Interface/AddOns/Resonance/sounds/vanilla/. Files in the sibling Resonance_Sounds/ addon survive updates from WoWUp, CurseForge, and other addon managers, which wipe and replace the Resonance/ folder on every update. The legacy in-addon path still works as a fallback.
  • LibSharedMedia-3.0 integration: Resonance now ships LibSharedMedia-3.0. Custom sounds you register in the Custom Sounds tab are automatically exported to LSM under MediaType "sound", so other LSM-aware addons (WeakAuras, BigWigs, etc.) can see them. In the other direction, sound search boxes throughout Resonance now surface sounds registered with LSM by any other addon — pick one and it works exactly like a regular sound reference.

v1.6.0

New Features

  • Tabbed spell editor: The spell editor now uses a clean tabbed layout with three tabs — Cast Complete, Precast, and Muted. Each sound tab has identical controls (sound list, browse/search, duration, loop). The Muted tab shows auto-muted FileDataIDs with checkboxes.
  • Precast multi-sound support: The Precast tab now supports multiple sounds, sound lists, and loop — matching the Cast Complete tab's capabilities. Old single-sound precast configs load and play correctly.
  • Unified spell input: The spell ID field now accepts both numeric IDs and spell names with autocomplete search. No more separate search box for new spells vs editing.
  • Collapsible Advanced Options: Sound mode (standard/sequence), channel override, multi-hit window, and faction-specific sounds are grouped under a collapsible "Advanced Options" toggle. Auto-expands when editing a spell that has these configured.
  • Faction-specific sounds: Configure different replacement sounds for Horde and Alliance characters on the same spell.

Bug Fixes

  • Fix spell editor UI elements overlapping (duration box on top of sound mode, precast section colliding with other controls). The tabbed layout eliminates all anchor chain conflicts.
  • Fix export/import/preset functions silently dropping hordeSound, allianceSound, precastLoop, and multiHitWindow fields. All spell config fields are now preserved across export, import, preset save, and preset apply operations.
  • Fix mount sound CSD-derived folder discovery for mounts whose sounds live in numeric or cross-referenced folders (e.g. Headless Horseman's Hallowed Charger).

v1.5.2

Bug Fixes

  • Fix mounts whose sounds live in numeric or cross-referenced sound folders (e.g. Headless Horseman's Hallowed Charger). The generator now discovers sound folders by tracing CSD FileDataIDs back to their listfile folder, catching M2-embedded animation sounds that don't match the model folder name.

v1.5.1

New Features

  • Faction-specific sounds: Configure different replacement sounds for Horde and Alliance characters on the same spell. In the spell editor, check "Faction-specific sounds" to reveal Horde and Alliance sound fields. Useful for spells like Time Warp that you want to sound different per faction.

v1.5.0

New Features

  • Mount sound muting: New "Mount Sounds" tab to mute individual mount sounds. Browse your collected mounts in a paginated, searchable list and check the box to mute any mount's locomotion and ambient sounds (walk, run, jump, fly, wing flap, idle fidgets, summoning).
  • Skyriding sound muting: Dedicated toggle to mute all skyriding wind effects — dive wind, speed rush, ability sounds (Surge Forward, Skyward Ascent, Whirling Surge), and ground skimming.
  • Model-embedded sound discovery: Mount sounds are now discovered from three sources: DB2 CreatureSoundData tables, M2 model animation sounds (via community listfile), and spell visual chains. This catches sounds from older mounts (e.g. Mimiron's Head) whose audio is baked into the 3D model rather than DB2 tables.
  • Mount data generator: New --generate-mount-data flag for tools/spell_sounds.py walks Mount → MountXDisplay → CreatureDisplayInfo → CreatureSoundData → SoundKitEntry and scans model sound folders to produce MountSoundData.lua (1,580 mounts, 537 CSD profiles, 17K+ sound files).
  • Mount search mode added to the Sound Browser tab for searching across all mounts (not just collected).

v1.4.0

New Features

  • Sequence sound mode: Configure a list of sounds that play one per hit for multi-hit spells like Rampage. Each successive hit advances through the sound list, creating a combo-style strike sequence. Works with any number of sounds and wraps around when the list is exhausted. Select "Sequence (1 per hit)" in the spell editor's sound mode radio to enable.
  • For single-hit spells, sequence mode cycles through sounds across casts (each cast plays the next sound in the list).

Bug Fixes

  • Fix refreshPresetsFromTemplates overwriting user-customized sounds on every login/reload. Template refresh now only updates mute data (muteExclusions, muteFIDs) and preserves user sound and multiHitWindow settings.

v1.3.5

New Features

  • Multi-hit sound window: Configurable time window that prevents multi-hit spells (e.g. Rampage, Raging Blow) from playing their replacement sound on every hit. Defaults to 1.5 seconds globally, adjustable per spell in the spell editor or globally in the General tab. Resolves the behavior change from v1.2.0 where name-based config fallback caused all sub-hits to trigger sounds.

Bug Fixes

  • Fix Whirlwind not muting its modern cast sounds. The 5 caster-side FIDs (whoosh sounds) were in ExcludedFIDs as over-shared; added explicit muteFIDs to both Whirlwind templates (1680, 190411).
  • Set Bladestorm template to a 5-second multi-hit window (non-channeled spell that fires repeated hits over ~4s).

v1.3.4

Bug Fixes

  • Fix channeled spells (e.g. Tranquility) playing replacement sounds on every tick. Channeled spells now play on UNIT_SPELLCAST_CHANNEL_START and suppress all subsequent UNIT_SPELLCAST_SUCCEEDED tick events — including sub-spells with different IDs that resolve to the same config via name matching.
  • Fix Mark of the Wild echo caused by unmuted original retail sounds playing alongside the replacement. Added muteFIDs for the two excluded FIDs (568735, 568917).
  • Fix auto-mutes silently inactive on first install or after the Resonance_Data folder restructure — eagerly load Resonance_Data during OnEnable when no auto-mute snapshot exists, instead of waiting for Options to be opened.
  • Fix multiple template spells across 6 classes whose original sounds were never muted because their FIDs were in ExcludedFIDs (over-shared) with no explicit muteFIDs. Affected spells: Shield Slam, Pummel, Rend, Shield Block, Colossus Smash (Warrior), Rapid Fire (Hunter), Greater Invisibility, Shimmer (Mage), Chain Lightning, Ascendance (Shaman), Breath of Fire (Monk), Ravager (Warrior).
  • Fix empty auto-mute snapshot ({}) incorrectly treated as valid — now checks next() ~= nil instead of truthiness.
  • Update Bladestorm template to WotLK-era sounds (heroicthrowmissile + FX_Lightning_Impact_Heavy03).

v1.3.2

New Features

  • Alerts tab: Configure alert sounds for combat events with a dropdown + table UI. Select an event type, pick a sound (with autocomplete search), and manage alerts with enable/disable toggles.
    • Interrupt alert: Play a sound when your cast is interrupted by an enemy kick or counterspell. Uses LOSS_OF_CONTROL_ADDED + UNIT_SPELLCAST_INTERRUPTED dual-direction correlation — fully compatible with Midnight 12.0.1 instanced content.
    • Loss of Control alert: Play a sound when you are stunned, feared, silenced, or otherwise lose control of your character.
    • Death alert: Play a sound when you die.
  • Custom Sounds tab: Register your own .ogg/.mp3 sound files and use them throughout the addon. Place files in Interface/AddOns/Resonance_Sounds/, register them with a display name, and they appear in all sound search autocomplete dropdowns (highlighted in green).
  • Per-spell sound channel: Override the sound channel for individual spells in the spell editor. Route specific replacement sounds to Master, SFX, Music, Ambience, or Dialog — useful for adjusting relative volume of replacements vs. game sounds.
  • Cast phase triggers: Choose when spell replacement sounds play — on cast complete, cast bar start (precast), or both with separate sounds for each phase.
  • Sound duration cutoff: Limit how long a replacement sound plays (in seconds).
  • Sound looping: Loop a replacement sound continuously or a set number of times.
  • Ambient sound muting: Mute ambient sounds by zone with per-zone toggles in a new Ambient tab. Includes a search feature to find and mute individual ambient sounds, with expansion/zone info in results.
  • Per-NPC sound muting: Mute sounds from specific NPCs.
  • Sound autocomplete: Autocomplete dropdown when selecting replacement sounds, with a redesigned two-line layout showing expansion/zone and FID info.
  • Rogue Shadowstrike added to class sound templates.

UI/UX Improvements

  • Options panel reorganized into Settings subcategories with dedicated panels and tab headings.
  • Redesigned dropdown rows with per-row variable height and inline mute icon button with visual feedback.
  • Improved WCAG contrast and color consistency across the UI.
  • Sound channel dropdown now uses Blizzard's localized global strings — labels match the game's Sound settings in every language.
  • Preset spells deleted by the user no longer auto-repopulate on login. Excluded spells are tracked and skipped during template refresh. Re-applying a class template clears the exclusion list.

Performance

  • LoadOnDemand data split: Addon split into Resonance (core) + Resonance_Data, deferring large data tables until options are first opened.
  • Memory optimizations: table reuse, deferred snapshots, prefix pools, eliminated string concatenation during search.

Bug Fixes

  • Fix crash when copying AceDB profiles — nil-guard tables that may not exist after profile copy (mute_file_data_ids, spell_config, etc.).
  • Fix custom panels (Spell Sounds, Presets, Ambient) showing empty on first visit — add deferred refresh after initial build to allow WoW's layout pass to complete.
  • Fix Resonance_Data not found after addon update — moved to its own folder with BigWigs packager move-folders directive.
  • Fix CI lint failures — extract only read_globals from the WoW API globals file instead of loading the full config.
  • Fix UNIT_MODEL_CHANGED spam: cache race/gender key so vocalization mute refreshes only trigger on actual changes (barbershop, Orb of Deception), not on every model update.
  • Auto-migrate stale creature vox snapshots on addon upgrade.
  • Exclude profession sound FIDs from creature vocalization muting.
  • Clear stale mute snapshots on startup.
  • Use MAX_MUTE_DEPTH unmutes in all clear functions to properly drain refcount.
  • Fixed various UI layout issues (editor overlap, duration anchoring, ambient tab positioning, preview button placement).
  • Fixed mojibake caused by UTF-8 arrow character in disabled message.

Tooling

  • Added luacheck and StyLua linting/formatting with CI workflow.
  • Cross-platform dev setup docs in README (macOS, Linux apt/pacman, Windows).
  • /res checkfid <id> diagnostic command to inspect which muting systems affect a given FileDataID.
  • tools/generate_ambient_data.lua for generating ambient sound data.

Localization

  • All new keys translated across 9 languages (ptBR, deDE, frFR, esES, itIT, ruRU, koKR, zhCN, zhTW).

v1.2.0

New Features

  • Mute-only mode: Mute all sounds from a spell without selecting a replacement. Enable "Mute only" in the spell editor to silence original sounds with nothing playing in their place.
  • Profession sound muting: Per-profession checkboxes (Alchemy, Blacksmithing, Cooking, etc.) to mute crafting, gathering, and other profession-related sounds. 13 professions, 168 unique sound files.
  • Shared-sounds disclaimer: General tab now shows a note explaining that some sounds are shared across multiple spells/effects, so muting for one feature may silence them elsewhere.

Tooling

  • tools/spell_sounds.py --generate-profession-data generates data/ProfessionSoundData.lua from DB2 SkillLine/SkillLineAbility data.

v1.1.0

New Features

  • Classic auto-shot sounds (Hunter): Replace modern bow and gun auto-shot sounds with classic ones. Automatically detects equipped weapon type (bow/crossbow or gun). Toggle in General options (Hunter only).
  • Disable state: When "Enable Resonance" is unchecked, all General tab controls are now visually disabled and muting options revert to defaults, making it clear the addon is inactive.
  • Version display: Minimap tooltip now shows the addon version.

Bug Fixes

  • Revenge sound mapping corrected — was playing DecisiveStrike.ogg instead of dedicated warrior_revenge sounds.
  • Bladestorm sound mapping corrected — was playing WhirlwindShort.ogg instead of dedicated warrior_bladestorm sound.
  • Heart Strike sound mapping corrected — was playing Blood Strike sounds instead of dedicated deathknight_heartstrike sounds.
  • Addon icon in the AddOns menu now matches the minimap button icon.

Creature Vocalization Improvements

  • Added fidget (idle roars/growls), alert (pre-aggro), and jump sounds to creature vox muting — previously only combat sounds were covered.
  • Narrowed spell FID exclusion to player spells only — NPC abilities no longer incorrectly protect their creature's own vox sounds from being muted.
  • Total creature vox coverage increased from ~40K to ~61K sound files (+54%).

v1.0.0

  • Initial release.