File Details
Recount-v1.18.1
- R
- May 5, 2026
- 319.28 KB
- 2.9K
- 12.0.1+6
- Retail + 2
File Name
Recount-Recount-v1.18.1.zip
Supported Versions
- 12.0.1
- 12.0.0
- 11.2.7
- 4.4.0
- 3.4.3
- 2.5.5
- 1.15.8
Recount Changelog
[v1.18.1] (2026-05-05) - Retail Midnight (12.0) support via C_DamageMeter
Bug Fixes
Window color picker fixed on Classic Era and other Classic flavors. Reported by a user: "any chance of fixing the feature to change window colours?". Two bugs in one — both fixed:
The picker code in
colors.luabranched onWOW_RETAILto choose between the new (Dragonflight-era)ColorPickerFrame.Content.ColorPickerAPI and the oldOpacitySliderFrame/ColorPickerFrame.funcAPI. But the new picker has since rolled out to every Classic flavor too — Vanilla Classic 11507/11508, Cata Classic, Wrath Classic, MoP Classic — leaving Classic clients in a half-migrated state whereswatchFuncwas set on Vanilla but the alpha read still went through the long-removedOpacitySliderFrame(which isnil). Replaced everyWOW_RETAIL/WOW_VANILLA_CLASSIC/WOW_PANDA_CLASSICflag check inside the picker with a runtime test forColorPickerFrame.Content and ColorPickerFrame.Content.ColorPicker.Per-field assignment of
swatchFunc/opacityFunc/cancelFunconColorPickerFramefollowed by:Show()is silently dropped on the new picker — the OkayButton's OnClick reads from the info table the picker captured during setup, not from the frame's fields. Confirmed in-game: pressing OK on the new picker threwattempt to call field 'swatchFunc' (a nil value)from Blizzard'sColorPickerFrame.xml:79_OnClick. RefactoredColors:EditColorto useColorPickerFrame:SetupColorPickerAndShow({r=, g=, b=, opacity=, hasOpacity=, swatchFunc=, opacityFunc=, cancelFunc=})on the new picker (the documented Dragonflight+ pattern); the old per-field-then-Show path is preserved verbatim for any pre-Dragonflight client that still uses it. Position-relative-to-Attach moved to after Setup since the new picker re-anchors during its own setup.The first new-picker detector tested for
ColorPickerFrame.Content.ColorPicker, but that field returned nil on at least Classic Era 11507/11508 even though the new-style OkayButton (which readsswatchFunc) was active —SetupColorPickerAndShowwas never called and the second OK click reproduced the same error. Switched the detector to test forColorPickerFrame.SetupColorPickerAndShowdirectly (the canonical 10.2.5+ method); if that method exists, the info-table contract is in force.Alpha reads in
Color_ChangeandOpacity_Changepreviously reached intoColorPickerFrame.Content.ColorPicker:GetColorAlpha(). Switched to the documented top-levelColorPickerFrame:GetColorAlpha()so the same code works regardless of inner widget naming differences across Classic flavors.Color_Cancelno longer manually rewinds the picker's internal opacity slider —Colors:SetColor(Cur_Branch, Cur_Name, PreviousColor)already re-paints the registered visual elements viaUpdateColor, and the picker frame is closing anyway. Removes the lastColorPickerFrame.Content.ColorPickerreference from the file.
Also removed three now-unused project-flag locals from
colors.lua(WOW_RETAIL,WOW_VANILLA_CLASSIC,WOW_PANDA_CLASSIC) and the dangling MoP-onlyswatchFunc = funcpost-Show fallback.No more
ADDON_ACTION_FORBIDDENLua error at login on retail Midnight (12.0). A user reported25x [ADDON_ACTION_FORBIDDEN] AddOn 'Recount' tried to call the protected function 'Frame:RegisterEvent()'traced toRecount.lua:1868(theRecount.events:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")call insideOnEnable). Root cause: in patch 12.0, Blizzard removed addon access toCOMBAT_LOG_EVENT_UNFILTEREDunconditionally. The call now firesADDON_ACTION_FORBIDDENin every context, including at login outside any combat / encounter / instance. Two prior research dead-ends ruled out before landing the real fix: (1)C_RestrictedActions.IsAddOnRestrictionActive(0..3)is not a useful gate — it reports "no restrictions" at login while the underlying call is still blocked. (2)pcalldoes not help —ADDON_ACTION_FORBIDDENis dispatched asynchronously by Blizzard, not raised at the call site.
Retail Midnight scaffolding (data path NOT yet functional — tracked for v1.18.2)
- New file
Tracker_Midnight.lua(loaded only on Mainline TOC, never on Classic flavors) is the intended CLEU-free data path. Subscribes toDAMAGE_METER_CURRENT_SESSION_UPDATED,DAMAGE_METER_COMBAT_SESSION_UPDATED, andDAMAGE_METER_RESET. On each session update, pollsC_DamageMeter.GetCombatSessionSourceFromType(Current, metric, GUID)for every group member and would compute per-(player, datatype) deltas against a snapshot table, feeding them through the existingRecount:AddAmount(combatant, datatype, amount)so the rest of Recount (modes, fight history, bars, reports, etc.) works unchanged. - In-game test outcome on retail Midnight (12.0.5.67314):
source.totalAmountreads always come back as secret number values — not just during combat as the wiki'sSecretWhenInCombatannotation suggested, but also after combat. Tainted addon code can hold a secret value but cannot do arithmetic on it ("attempt to perform arithmetic on local 'total' (a secret number value, while execution tainted by 'Recount')"). The first iteration ofTracker_Midnight.luathrew this Lua error every combat. The current iteration usesissecretvalue(total)to skip the metric and does NOT update the snapshot when the value is secret — eliminates the Lua error, but post-combat reads also come back secret in practice, so no deltas are ever applied and the Recount bars stay empty on retail Midnight. - Net v1.18.1 effect on retail Midnight: addon loads cleanly, no Lua errors, settings / minimap / Titan Panel all work, but combat data does not populate. v1.18.2 will pursue the workaround — likely involving Skada's
SecretValueHelper.luapattern or finding a non-tainted code path the wiki documents elsewhere. - Self-help warning kept in place: if
C_DamageMeter.IsDamageMeterAvailable()returns false (in-game damage meter setting is OFF), Recount emits a yellow chat message at login telling the user to enable it underOptions > Gameplay Enhancements > Damage Meter. (Won't matter until the secret-value problem is solved, but the warning is harmless and the setting is needed regardless.)
Implementation
Recount.luatop-of-file — addedlocal WOW_RETAIL = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE(matching the convention incolors.lua) andlocal WOW_RETAIL_MIDNIGHT = WOW_RETAIL and ((select(4, GetBuildInfo()) or 0) >= 120000).GetBuildInfoandselectcached as locals per project convention.Recount.luanew dispatcherRecount:RegisterCombatLogEvent— on Midnight, callsRecount:RegisterCombatLogEvent_Midnight()(defined inTracker_Midnight.lua). On every other client, callsRecount.events:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")exactly as before.Recount.luaOnEnable— line 1868 changed fromRecount.events:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")toRecount:RegisterCombatLogEvent(). TheINSTANCE_ENCOUNTER_ENGAGE_UNITregistration on the next line is unchanged — that event is not subject to the CLEU restriction.Tracker_Midnight.lua(new file) — implementsRecount:RegisterCombatLogEvent_Midnight(), theRecount:DAMAGE_METER_*event handlers, and the snapshot/diff polling. Uses synthesizedCOMBATLOG_OBJECT_*flags (Self/Party/Raid + Player + Friendly + ControlPlayer) when callingRecount:AddCombatantsince real CLEU flags aren't available on this code path. EveryC_DamageMetercall is wrapped inpcall, including the field access on the returned struct (theDamageMeterCombatSessionSourceis markedSecretWhenInCombat).Secret-value handling — confirmed in-game on retail Midnight that
source.totalAmountreads return secret number values during combat. Reading them does not throw, but arithmetic on them does ("attempt to perform arithmetic on local 'total' (a secret number value, while execution tainted by 'Recount')"). Worked around by checkingissecretvalue(total)before any arithmetic and skipping the update when true. The snapshot is left alone in the secret case so the next non-secret read produces the correct delta against the last public total. Belt-and-suspenderspcallwraps the subtraction itself in caseissecretvalueisn't reliable on a given build. Practical effect: bars don't tick up live during combat, but populate fully once the next post-combat session update fires.Recount_Mainline.toc— addedTracker_Midnight.luaimmediately afterTracker.lua. The other four TOCs (Recount.tocfor Classic Era,Recount_BCC.toc,Recount_Wrath.toc,Recount_Cata.toc) do NOT reference the new file, so Classic-flavor clients literally never load it. Zero risk of accidental cross-version interference..luarc.json— addedGetBuildInfoandC_DamageMetertodiagnostics.globals.
Behavior
- Pre-12.0 retail and all Classic flavors — no behavior change. CLEU registers immediately at
OnEnableexactly as before.Tracker_Midnight.luais not loaded. - Midnight retail (12.0+) — login Lua error fixed; addon loads cleanly.
Tracker_Midnight.luaregisters theDAMAGE_METER_*events but in practice every poll returns secret values that we cannot operate on, so the Recount bars stay empty until v1.18.2 lands an actual workaround for secret values. - No more login Lua error in any scenario, including on retail Midnight.
What's deferred to v1.18.2
- Get retail Midnight bars actually populating. The
Tracker_Midnight.luascaffolding is in place; the missing piece is a way to either (a) extract numeric values from secret-value returns, (b) callC_DamageMeterfrom a non-tainted execution path, or (c) display secret values directly via FontString widgets without the addon ever doing arithmetic. Likely path: study Skada'sSecretValueHelper.lua(visible inzarnivoop/skadaon GitHub) which is the only public reference for a working Midnight damage meter. - Tracker modules on Midnight retail. Dispels, Interrupts, CC Breakers, Power Gains, Resurrections write to per-spell table-data structures (
AddTableDataStats,AddTableDataSum) that don't have a 1:1 mapping toC_DamageMeter'scombatSpellsarray. Will need module-specific shims once the basic data path works. - Fight rotation alignment. Recount's fight boundaries come from
PLAYER_REGEN_*(still works on Midnight), but Blizzard's session reset cadence may not match exactly. If the snapshots and Recount'sCurrentFightDataget out of sync at fight boundaries, follow-up tuning is required.
Files Changed
Recount.lua— added Midnight version guard and theRegisterCombatLogEventdispatcher; replaced the unconditional CLEURegisterEventcall inOnEnableTracker_Midnight.lua— new file, Midnight-only data collection viaC_DamageMeterRecount_Mainline.toc— addedTracker_Midnight.luato the load ordercolors.lua— replacedWOW_RETAIL/WOW_VANILLA_CLASSIC/WOW_PANDA_CLASSICflag checks inside the color picker with a runtime test for the newColorPickerFrame.Content.ColorPickerAPI; removed the three now-unused project-flag locals and the post-ShowswatchFunc = funcfallback.luarc.json— addedGetBuildInfo,C_DamageMeter, andissecretvaluetodiagnostics.globals
[v1.17.5] (2026-04-29) - Fix Bars Not Appearing on First Launch
Bug Fixes
- Main window bars now render on first launch without needing a manual mode pick. Three users reported installing Recount, entering combat, and seeing the window appear with no bars or numbers — the workaround was to right-click the title bar and pick a display mode from the dropdown. Root cause:
Recount.MainWindow.GetDatais the function pointer the 1-second refresh timer inGUI_Main.lua:RefreshMainWindowuses to read combat data, and it is only ever assigned insideRecount:SetMainWindowMode. That assignment normally happens duringOnInitializevia the chainSetupMainWindow → LoadMainWindowData → SetMainWindowMode(MainWindowMode or 1). If any earlier call in theOnInitializeCreate chain (CreateMainWindow → CreateDetailWindow → CreateGraphWindow → CreateFilterWeights → InitOrder → SetupMainWindow) threw a Lua error,SetupMainWindownever ran,GetDatastayed nil, and the timer-driven refresh silently early-returned forever. The right-click trick worked because picking a mode from the dropdown invokesSetMainWindowModedirectly, bypassing the broken init path.
Implementation
Two complementary additive fixes in OnInitialize and RefreshMainWindow:
Recount.luaOnInitialize— the six-call init chain (CreateMainWindow,CreateDetailWindow,CreateGraphWindow,CreateFilterWeights,InitOrder,SetupMainWindow) is now individually wrapped inpcallvia a localsafeInithelper. A failure in any one step no longer prevents the others from running, soSetupMainWindowalways gets a chance to bindGetData. Failures emit a yellow|cffff8800Recount init warning:|r <step> failed: <error>line toDEFAULT_CHAT_FRAMEso users can screenshot and report the actual failing call instead of just "no numbers."GUI_Main.luaRefreshMainWindow— the function-entry gateif not MainWindow.GetData or not MainWindow:IsShown() then return endwas split. The visibility check still early-returns. TheGetDatacheck now self-heals: ifGetDatais nil butRecount.MainWindowDatahas been populated,RefreshMainWindowcallsRecount:SetMainWindowMode(Recount.db.profile.MainWindowMode or 1)to bind it before continuing. Worst case for the regression scenario: bars appear ~1 second later than they would on a healthy init (next timer tick instead of immediately). Healthy installs see no behaviour change.
Files Changed
Recount.lua—OnInitializeCreate chain wrapped inpcallvia localsafeInithelperGUI_Main.lua—RefreshMainWindownow self-heals whenGetDatais nil butMainWindowDatais loaded
[v1.17.2] (2026-04-15) - Compare Graph Window
New Features
Compare Graph window — A new multi-series time-series graph window accessible from the main toolbar. Add any number of player + metric combinations as overlaid lines and compare them side by side. Supports all 14 tracked metrics: Damage Done, DPS, Friendly Fire, Damage Taken, Healing Done, Absorbs, Healing Taken, Overhealing, Deaths, DOT Uptime, HOT Uptime, Activity, Threat (TPS), and Threat (Total).
Fight Filter dropdown — Restrict the compare graph to a single recorded combat encounter using the Fight dropdown. Selecting a fight clamps the X axis to that window; "All Fights" shows the full session timeline.
Per Fight mode — A "Per Fight" checkbox renders each recorded fight as a continuous sawtooth line on a shared session timeline. Each fight rises from 0 as the metric accumulates then snaps back to 0 at fight end, with flat-zero gaps between pulls. Useful for comparing output across an entire raid session.
Crosshair cursor with live tooltip — Hovering over the compare graph draws a vertical hairline at the cursor and shows a
ANCHOR_CURSORtooltip with the interpolated value of every active series at that X position. Values are linearly interpolated between 1-second samples and formatted as raw,k, ormdepending on magnitude. The X header shows elapsed seconds since the fight/session start.Normalize checkbox — Scales each series independently to 0–100% so metrics with vastly different magnitudes (e.g. 640k threat vs 11k damage) can be visually compared on the same axis.
Integrate checkbox — Converts per-second rate data (DPS, TPS) into cumulative totals over time. Metrics that are inherently cumulative (Damage Done, Healing Done, Threat Total, etc.) integrate automatically regardless of this checkbox.
Improvements
Threat time-series units corrected —
TimeData["Threat"]now stores raw threat/s (matchingTimeData["Damage"]units) instead of k-threat/s. After integration, Threat (Total) now correctly reaches the same magnitude shown on the bar chart (e.g. 614,000). Requires one fresh fight after updating; existing saved data will be on the old scale.Compare graph dropdown fix —
UIDropDownMenu_Initializewas being called inside the Fight and Metric dropdownOnEnterhandlers, causing dropdown lists to close as soon as the cursor moved toward them. Removed the re-initialize call fromOnEnter; init functions already read live data on every open.Compare graph tooltip anchor — All three Compare window dropdowns (Player, Metric, Fight) changed from
ANCHOR_LEFTtoANCHOR_TOPRIGHTso the hover tooltip no longer overlaps the dropdown list that opens to the left.
Files Changed
GUI_CompareGraph.lua— New file; full Compare Graph window implementationTrackerModules/TrackerModule_Threat.lua— TPS units corrected to raw threat/sGUI_Main.lua— Compare button added to main window toolbar
[v1.17.1] (2026-03-31) - Minimap Button Toggle Option
New Features
- Minimap button toggle in settings — A checkbox has been added to the Recount settings panel (Options > Addons > Recount) to show or hide the minimap button. The checkbox calls
Recount:ToggleMinimapButton(v)and the state is persisted indb.profile.minimapButton.hideso it survives reloads and is character-agnostic.
Files Changed
Recount.lua—toggleentry added toconsoleOptions.argsfor the minimap button visibility checkbox
[v1.17.0] (2026-03-30) - Minimap Button & Titan Panel Integration
New Features
Minimap button (LibDBIcon-1.0) — A persistent minimap button is now registered via LibDataBroker-1.1 and LibDBIcon-1.0. Left-click toggles the main Recount window; Shift+Left-click toggles the configuration window; Right-click opens the WoW addon settings panel. Cross-version compatible: uses
Settings.OpenToCategoryon Interface 11508+ and falls back toInterfaceOptionsFrame_OpenToCategoryon older clients. Button position and visibility are persisted per-profile in AceDB.Titan Panel integration (LibDataBroker data source) — A
data sourceLDB object is registered under the nameRecount_Stats. Any LDB display addon (Titan Panel, Bazooka, DockingStation, etc.) picks this up automatically. The plugin shows a live per-player stat (DPS: 842) updated every 1 second viaC_Timer.NewTicker. Right-clicking opens a nativeUIDropDownMenuto switch between six display stats (DPS, Damage Done, HPS, Healing Done, Damage Taken, Deaths) and three datasets (Overall, Last Fight, Current Fight). Hovering shows a full tooltip with all six stats at once. The selected stat is persisted inRecount.db.profile.titanPanel.stat.
Files Changed
GUI_Minimap.lua— New file; LibDataBroker launcher + LibDBIcon-1.0 minimap buttonGUI_TitanPanel.lua— New file; LibDataBroker data source for Titan Panel / LDB displayslibs/LibDataBroker-1.1/LibDataBroker-1.1.lua— New bundled librarylibs/LibDBIcon-1.0/LibDBIcon-1.0.lua— New bundled libraryRecount.toc(and all 4 flavor TOCs) — Added new lib scripts and GUI filesRecount.lua—InitMinimapButton()andInitTitanPanel()called fromOnInitialize()
[v1.16.0] (2026-03-30) - CurseForge Publishing, Multi-Flavor TOCs & Code Quality
New Features
CurseForge project integration — Added
## X-Curse-Project-ID: 1499579to all TOC files andcurseforge-project-id: 1499579to.pkgmeta. Version field now uses theRecount-v1.18.1packager token so releases are automatically versioned on CurseForge upload. Interface version updated to11508(Season of Discovery / Classic Era).Multi-flavor TOC support — Added separate TOC files for each WoW client flavor following the standard BigWigs Packager / CurseForge naming convention:
Recount_BCC.toc— Burning Crusade Classic (Interface 20505)Recount_Wrath.toc— Wrath of the Lich King Classic (Interface 30403)Recount_Cata.toc— Cataclysm Classic (Interface 40400)Recount_Mainline.toc— Retail / The War Within (Interface 110207, 120001, 120000)
CurseForge addon description — Created
docs/Curseforge_Description.htmlwith a full formatted addon description for the CurseForge project page, covering all display modes, tracker modules, features, slash commands, and credits.
Improvements
Ace3 externalized — Removed bundled Ace3 library source files from the repository. Libraries are now declared as externals in
.pkgmetaand fetched by the CurseForge packager at release time, keeping the repository lean and libraries up to date.VersionCheck-1.0 integrated — Added VersionCheck-1.0 as a dependency in Classic Era / BCC / Wrath / Cata TOC files for out-of-date addon notification. Omitted from the Mainline TOC where it is not applicable.
Bug Fixes
table.getn()andtable.maxn()deprecated calls removed — Replaced all occurrences with the#length operator acrossGUI_Config.lua,GUI_Detail.lua,GUI_Graph.lua, andGUI_Main.lua. These calls produce errors in modern Lua 5.1 environments and generate lint warnings.GUI_Graph.luanil guard — AddedFiltered and Filtered[1] andguard before#Filtered[1]access to prevent nil indexing whenFilterDataByTimeorDataCopyreturns nil. Also appliedor 0fallback toFiltered[1][#Filtered[1]]andFiltered[1][1]arithmetic to prevent nil subtraction errors.GUI_Detail.luarow type mismatch — ChangedRow = ... or 0toRow = ... or {}so the LSP correctly infersRowas a table, preventing false type errors when fields likeRow.Dataare accessed.zonefilters.luascenario type handling — RefactoredC_Scenario.IsInScenario()assignment to use a separatescenarioTypevariable withor "none"fallback before assigning toinstanceType, resolving a type-mismatch lint error. Added---@diagnostic disable-next-line: deprecatedsuppression for theGetZonePVPInfocall which has no non-deprecated replacement in Classic Era.Tracker.luaduplicate table keys — Commented out duplicate spell ID entries[1463],[6229], and[31000]in the shield absorb duration table. Duplicate keys silently overwrite earlier values in Lua and generate lint warnings.TrackerModules/TrackerModule_CCBreakers.luaargument count mismatch — AddedextraSpellIdparameter to theAddCCBreakerfunction signature to match the 8-argument call site (previously declared with only 7 parameters).
Internal
Lua Language Server configuration (
.luarc.json) — Added 40+ WoW API globals to suppress false "undefined global" warnings, including allCOMBATLOG_OBJECT_*filter constants,CombatLogGetCurrentEventInfo,GetSpellInfo,BNGetFriendInfo,BNSendWhisper,LE_PARTY_CATEGORY_INSTANCE,InterfaceOptionsFrame,ColorPickerFrame,C_Scenario,RecountDeathTrack,RecountTempTooltip, and WoW project version constants. Added"duplicate-set-field"todiagnostics.disable.markdownlint
.pkgmetasuppression — Added**/.pkgmetato both.markdownlintignoreand.vscode/settings.jsonmarkdownlint.ignoreto prevent YAML comment lines (# comment) from triggering false markdown heading warnings.

