SuperSwingTimer v0.2.7
What's new
v0.2.7 - 2026-10-25
Added
- Enterprise Diagnostics (
SuperSwingTimer_Diag.lua,/stt diag//sst diag):- New early-loaded diagnostics module. It is the first file in the TOC, so
/stt diag//sst diagremains reachable even if a library or later SuperSwingTimer module fails to load. /sst diagprints a compact health report: client/build/project, addon version, DB version, class, bar/hook counts, aura API path, precise-clock status, event registration, render-loop state, FPS, addon memory, addon CPU, library status, SoD module status, slash registration, and captured errors./sst diag fullprints every check, including informational rows that are hidden from the compact report./sst diag errorsprints captured signatures with stacks and counts./sst diag exportopens a copyable report window./sst diag clearresets the ring buffer./sst diag testruns live API probes (clock, spell info, aura path, metadata, glow) and reports pass/fail.- Error capture chains the existing
seterrorhandlerinstead of replacing it, so Blizzard's normal error display and logging still run. Capture also listens forLUA_WARNING,ADDON_ACTION_BLOCKED, andADDON_ACTION_FORBIDDEN. - Deduplicated ring buffer (40 signatures) with repeat counts, first/last timestamps, source tags (
lua,warning,taint,init,slash,diag,glow), and stack excerpts. Identical failures cannot flood the report or the SavedVariables. /sst diag profile [seconds]adds an opt-in per-hook profiler usingdebugprofilestart/debugprofilestop; it reports total time, per-frame average, share, and max for the top hooks. Profiling is completely inactive until requested.- Diagnostics never write to files. Export is an in-game EditBox with the report pre-selected for
Ctrl+A/Ctrl+C.
- New early-loaded diagnostics module. It is the first file in the TOC, so
- LibCustomGlow-1.0 Integration (
Lib/LibStub,Lib/LibCustomGlow-1.0,SuperSwingTimer_Glow.lua):- Added LibStub and LibCustomGlow-1.0 to the TOC in dependency order (
LibStubbeforeLibCustomGlow). - Added
ns.Glow, a lifecycle-safe adapter withSetBar/SetIcon/StopAll/Refresh. Call sites may invoke it every frame; only active↔inactive transitions touch the library.SetBarsupportsautocast(default, best for thin bars) andproc;SetIconuses ButtonGlow. - Every library call is
pcall-guarded with failure latches, so a library/client mismatch cannot break swing rendering. Errors are recorded for/sst diag. - No-op fallback when LibCustomGlow is absent; the addon continues to render all bars and existing border pulses.
- Bar effects:
- Paladin Judgement of the Crusader bar: Autocast shine while the debuff is in its final 4-second window.
- Rogue Slice and Dice bar: Autocast shine while the buff is in its final 4 seconds.
- Warrior Overpower: Autocast shine on the main-hand bar for the full Overpower proc window.
- Hunter Rapid Fire bar: Autocast shine while the buff is active and in its final 4 seconds.
- Shaman weave: Autocast shine on the main-hand bar while a weave cast is in flight, using the existing safe/clip color (class color when safe, red when clipping).
- Icon effect:
- All six classes' buff/cooldown icon groups: ButtonGlow only in the urgent final 2 seconds, complementing (not duplicating) the existing 4-second border pulse.
Glow.SetIconinstalls a one-timeOnHidehook per icon, so an icon that expires, is hidden by its class toggle, or is hidden by Minimal Mode stops its glow immediately without per-class cleanup bookkeeping.
- Deliberately avoids PixelGlow: its
AM_29mask asset is not referenced by either Classic Era 1.15.9 or TBC Anniversary 2.5.6 FrameXML, and registering a global replacement mask would affect other addons sharing LibStub. AutocastGlow (UI-ItemSockets), ProcGlow (proc flipbook atlases), and ButtonGlow (IconAlert) use assets verified on both clients. - Added
/sst glowand/sst glow on|offto toggle the effects. AddedDB_DEFAULTS.showGlowEffects = true; existing SavedVariables without the key are treated as enabled (no migration required). - Added
/sttas a fifth alias for the existing command table, so/stt diagworks exactly like/sst diag.
- Added LibStub and LibCustomGlow-1.0 to the TOC in dependency order (
Changed
- Initialization hardening (
SuperSwingTimer.lua):OnAddonLoadednow runs underxpcallwith a traceback handler instead ofpcall, so initialization failures keep a usable stack for/sst diag.- On init failure the addon records the error, routes it through the client error handler, prints a short
/sst diaghint, and skips event registration instead of leaving a half-initialized addon receiving combat events. - Exposed
ns.eventFrameso diagnostics can verify event registration and the render-loop state without duplicating frame bookkeeping.
- OnUpdate hook labels (
SuperSwingTimer_Hooks.lua,SuperSwingTimer_UI.lua,SuperSwingTimer_ClassMods.lua):- Added
ns.RegisterNamedOnUpdateHook(name, hook, index)and a weakns.OnUpdateHookNamesmap. ExistingRegisterOnUpdateHookbehavior is unchanged. - Named the core hook and all class hooks (
paladin-seal,paladin-judgement,paladin-power,warrior,shaman,druid-form,druid-dots,hunter,rogue,power-fallback) so profiler output is readable.
- Added
- TOC load order (
SuperSwingTimer.toc):SuperSwingTimer_Diag.lua→LibStub→LibCustomGlow→SuperSwingTimer_Constants.lua→Media\Media.xml→SuperSwingTimer_Glow.lua→ engine/UI/class modules →SuperSwingTimer_SoD.lua(unchanged last position).- Diagnostics is first so it can capture and report a LibStub or LibCustomGlow load failure, not just failures in later SuperSwingTimer modules.
- Documentation (
README.md,SuperSwingTimer.toc):- Updated the current version to v0.2.7, added the diagnostics/glow command reference and compact-report example, added the LibCustomGlow texture-source row, and corrected the class-support debuff heights to the shipped 8px standard.
- Added a 12,000+ downloads note (as of October 2026).
Performance
- Idle bar reset guard (
SuperSwingTimer_UI.lua):ResetBarDisplaynow marks the bar with_sstResetDone;UpdateMeleeBarandUpdateRangedBarskip the full reset while the bar is already idle. The flag is cleared on the first swinging frame and set by every reset path (HideBars,ShowBars,ApplyVisibility, channel rendering, expiry), so labels/values cannot go stale. This removes repeatedSetMinMaxValues,SetValue, label text/style, cast-overlay, cast-threshold, and spark-position work for inactive MH/OH/enemy/ranged bars while the render loop stays alive for power bars. - Library calls are transition-driven.
ns.Glow.SetBar/SetIconare safe to call from existing throttled/frame update paths: they compare against weak state maps and only start/stop LibCustomGlow when the desired state changes. Icon and bar glows also stop through one-timeOnHidehooks, so hidden frames never leave an animation running and the throttled icon scans never need a per-class "dropped out of the active set" pass. - Profiling is opt-in and makes no timing calls when off:
ns.OnUpdatechecks a singlens.Diag.profile.activeflag and otherwise runs the original loop unchanged. - No per-frame
xpcall: error capture uses the client'sseterrorhandlerchain, so normal rendering keeps its original call shape.xpcallis used only for one-time initialization; slash/config failures usepcalland are recorded in the diag buffer. - No new per-frame color allocations: shared
GLOW_GOLDand a per-bar cached Rogue glow color table replace per-call literals.
Fixed
- Init failure could leave the addon half-initialized:
RegisterEvents()previously ran even whenOnAddonLoadedthrew. It now runs only after a successful initialization. - Init error stacks were lost: the old
pcall+tostring(initErr)path discarded the traceback. The newxpcallpath preserves it and records it for diagnostics. - Diagnostics reachability: the diagnostics module and a minimal
/sst+/sttfallback are registered at file load, so/stt diag//sst diagis available even if a later addon file errors before the full command table is built. The main dispatcher replaces the fallback once it loads. - Hunter Auto Shot could be missed on Classic Era / TBC Anniversary, flashing the MH bar after a ranged swing:
ns.AUTO_SHOT_NAME = ns.GetSpellInfo(75) or "Auto Shot" or "Shoot"made the"Shoot"fallback unreachable ("Auto Shot" or ...always yields the first string), and the only matcher accepted spell ID 75,"75", or the single client-resolved name. The supported clients disagree on whether CLEU andUNIT_SPELLCAST_*payloads carry the numeric ID or the localized name, and spell 75 resolves under different names across builds, so an unrecognised token fell through. A miss is not cosmetic:HandleSpellcastSucceededskips the MH/OH restart only for a recognised Auto Shot (skipMeleeReset), so the miss restarted melee and showed the MH bar right after each ranged swing.ns.IsAutoShotSpellnow accepts the numeric ID, its numeric string, the client-resolved localized name, and an explicitns.AUTO_SHOT_NAMESalias set ("Auto Shot","Shoot"). - Auto Shot could disappear or fail to display when a hunter cast ended before the red zone:
ShouldKeepHunterRangedTimerActiveanchored its hold to the moment the cast ended (a fixed 1.0s window) instead of the ranged cycle end, so a Steady Shot / Arcane Shot / Multi-Shot finishing more than a second ahead of cycle end tore the ranged timer down before the shot fired. The hold is now anchored tolastSwing + durationplus latency/grace, so Auto Shot is preserved wherever in the cycle the cast finished, including a cast landing at the very end. The anchor re-targets automatically when a new cycle starts and cannot hold an idle/reset timer. - Interrupted or failed casts left stale cast identity behind:
HandleSpellcastInterruptedOrFailedstopped clearingcurrentCastSpellId,currentCastStartTime,lastResolvedHunterCastToken, andlastResolvedHunterCastAt(and only ran for hunters), so a stale token survived intoHandleSpellcastSucceeded, which re-attributed it to the next successful cast and fabricated a red-zone Steady Shot that never landed. Cleanup is restored for every class.
Internal
- Headless tests (
SuperSwingTimer_Tests.lua,run_tests.lua):- Expanded the suite from 123 to 146 tests with a new
SST-Diaggroup covering: API presence, live error-handler capture,LUA_WARNINGevent capture, error dedupe and count semantics, SST-vs-external attribution, ring-buffer cap, slash consumption, compact/full/error report construction, error text inclusion, clear semantics, glow fallback, glow start/stop transition counting, icon and bar hide-stop via theOnHidehooks, the reset-guard flag, the Glow DB default,/sst glowtoggling, the/sttalias, LibStub/LCG library reporting, idempotent error-handler installation, profiler stats, self-test probes, and export construction. - Added harness mocks for
seterrorhandler,debugstack,debugprofilestart/debugprofilestop,GetBuildInfo,GetFramerate, addon memory/CPU APIs,C_AddOns.GetAddOnMetadata, project constants,UnitAura, event registration/IsEventRegistered,SetMultiLine,SetToplevel, andRaise. - Added
SuperSwingTimer_Diag.luaandSuperSwingTimer_Glow.luato the headless load order and to the TOC load-order assertions (LibStub before LCG, Diag before Constants, Glow before ClassMods). - Expanded the suite from 146 to 150 tests with Hunter regression coverage for Auto Shot alias matching (
"Auto Shot","Shoot", numeric ID and numeric string), cast-identity cleanup on interrupt/fail, and the cycle-anchored ranged hold (including that an idle/reset timer is never held).
- Expanded the suite from 123 to 146 tests with a new
- CI (
.github/workflows/luac.yml):- Added the new files plus
SuperSwingTimer_SoD.lua,SuperSwingTimer_Tests.lua, andMedia/SuperSwingTimer_Media.luato the syntax check. - Added a headless test step (
lua5.1 run_tests.lua, falling back tolua run_tests.lua) so the suite runs on every push/PR, not just locally.
- Added the new files plus
Notes
- No DB schema migration:
showGlowEffectsis a new optional key;nilis treated as enabled. ExistingSuperSwingTimerDBversions remain valid. - Pending in-game verification: this build has not yet been tested on live
classic_era,classic_anniversary, orclassic_titanclients. The Hunter Auto Shot and cast-window changes are covered by headless tests only; bars, glow, and CLEU-driven behaviour still need an in-game pass. - SoD load order is unchanged (
SuperSwingTimer_SoD.luaremains last): class merges run fromns.InitClassMods()onADDON_LOADED, after every file has loaded. - LibCustomGlow asset verification:
AnimateTexCoords(UIParent.lua:593),Interface\SpellActivationOverlay\IconAlert,Interface\SpellActivationOverlay\IconAlertAnts,Interface\ItemSocketingFrame\UI-ItemSockets,UI-HUD-ActionBar-Proc-Start-Flipbook,UI-HUD-ActionBar-Proc-Loop-Flipbook,CreateTexturePool,CreateFramePool,CreateMaskTexture, and the flipbook animation setters were confirmed againstclassic_era(1.15.9.70003),classic_anniversary(2.5.6.70006), andclassic_titan(3.80.2.69815) UI source.
This mod has no additional files

