28 Commits
Author SHA1 Message Date
Brues a506dcf7d2 Parse combat events only from the ClassicAPI combat log
The combat log detection flags started false and only flipped when the
first matching combat log event arrived, so the first buff, hit, heal,
DoT or kill of a session was shown twice: once from the CHAT_MSG text,
once from the combat log. ClassicAPI is required, so drop the flags and
every CHAT_MSG parser they gated, keeping chat parsing only for power
losses, item buffs, honor, reputation, skill and XP.

Keep every CHAT_MSG event registered for search pattern triggers, which
re-registers CHAT_MSG_SPELL_AURA_GONE_SELF so buff fade triggers fire
again. Delete the now-dead parsers, ParseForPartialActions and the
stray global MikCEL_ParseForOutgoingHits.
2026-10-28 17:57:44 -05:00
Brues 6f50252d8e Make MikCEH private and clear tables with table.wipe
Share MikCEH through the addon table instead of a global; the options
addon now reads the search pattern trigger type from
MikSBT.TRIGGERTYPE_SEARCH_PATTERN. ClassicAPI's table.wipe also resets
the Lua 5.0 length, so replace MikCEH.EraseTable and the hand-written
clear-then-setn loops with it.
2026-10-28 17:37:25 -05:00
Brues b50ce60ec6 Create the combat event helper frame in Lua and drop its XML
Replace the global MCEHEventFrame from MikCombatEventHelper.xml with a
local frame, set its scripts with SetScript and run OnLoad when the file
loads.
2026-10-28 17:32:32 -05:00
Brues 0fbff6f767 Build MSBT frames in Lua and drop MikScrollingBattleText.xml
The XML hand-copied 60 font strings whose anchors were overwritten before
every message. Create the event frame and the three scroll area frames
with CreateFrame/CreateFontString instead, keep the frame object on each
scroll area rather than its global name, and read the scroll area from
the frame in OnUpdate.
2026-10-28 17:28:46 -05:00
Brues 3c6420b22b Simplify spell icon lookup
Resolve icons from the trigger texture, then the event's SpellId via
C_Spell.GetSpellTexture, then the effect name. Drop the hand-written
French ICON_CACHE table, the never-read NO_ICON_CACHE and the SpellId
cache. The name lookup no longer overrides an exact SpellId icon, the
item fallback is reachable again, and misses are cached so each name is
searched once.
2026-10-28 17:23:54 -05:00
Brues 86b71cec9f Filter UNIT_HEALTH/UNIT_MANA with RegisterUnitEvent and drop the throttle
Register UNIT_HEALTH for player, target and pet and UNIT_MANA for player
only, so raid members' updates never reach Lua. The shared 150ms throttle
was compensating for that traffic and let any unit's event consume the
window, delaying or dropping the player's own threshold crossings.
2026-10-28 17:17:12 -05:00
Brues c187c92106 Replace profile migrations with a fill-missing-defaults pass
Profiles are deep copies of DEFAULT_CONFIG, so settings added later never
reached existing saves; the versioned migration chain patched that by
hand. Fill every missing key from the defaults on load instead, skipping
the entries of the user-editable Triggers and Suppressions lists.

Drop CreationVersion and VERSION_NUMBER, take VERSION_STRING from the
.toc Version ("dev" for unpackaged checkouts), and retitle the window
to ClassicAPI Edition.
2026-10-28 17:12:10 -05:00
Brues 9bf7e51f76 Drop player GUID retry logic
ClassicAPI's UnitGUID is valid from ADDON_LOADED on, so set playerGUID
once in Init and remove the PLAYER_ENTERING_WORLD retry, the per-event
EnsurePlayerGUID check and the pcall guards.
2026-10-28 16:56:09 -05:00
Brues a36912af47 Replace MikTRO with a ClassicAPI object pool
Animation event tables now come from CreateUnsecuredObjectPool and are
wiped on release, keeping garbage down under 1.12's stop-the-world GC.
Release the tables that were previously dropped for the GC (hidden
events, the power-gain early return), and make /msbt stats report the
number of tables in use as a leak check.
2026-10-28 16:53:18 -05:00
Brues 4b09ebc3f7 Draw spell icons inline and make scroll speed framerate-independent
Prefix the icon as a ClassicAPI |T escape instead of a separate texture
region, so it fades and scales with its text and counts toward alignment.
Scale the scroll step by elapsed time so text moves at the same speed at
any framerate.
2026-10-28 16:45:23 -05:00
Brues 862ac4c56a Replace Nampower events with ClassicAPI combat log
- Register COMBAT_LOG_EVENT_UNFILTERED and map 20 subevents to MSBT damage/heal/notification data with GUID-based direction

- Remove Nampower event layer, NP_* CVars, version check and install prompt

- Resolve spell icons through ClassicAPI GetSpellInfo

- Keep CHAT_MSG parsing for honor/rep/skill/XP/item/power lines and as fallback until each log event fires

- Update README integration docs
2026-10-24 22:36:20 -05:00
Brues ea79f083f3 defeats the purpose of the addon and confuses users 2026-07-20 15:38:27 -05:00
Brues 0229b07122 removed Babble 2026-06-23 14:28:20 -05:00
Brues 615c074a3f add ClassicAPI dep 2026-06-23 02:25:27 -05:00
Brues dc88b69103 Add BigWigs packager config to bundle both addons in one zip
Add .pkgmeta (package-as MikScrollingBattleText, move-folders pulling both addon folders to top-level siblings) and a tag-triggered GitHub Actions workflow using BigWigsMods/packager that attaches the single zip to an auto-created GitHub release. Switch both TOCs' Version to the @project-version@ substitution token so the packager stamps the git tag version.
2026-06-23 02:19:35 -05:00
Brues 9f88f0bf32 Replace FindBuff tooltip scanning with C_UnitAuras/C_Item
GetAuraIcon resolves buff/debuff icons via C_UnitAuras.GetAuraDataBySpellName (returns the icon directly, no UnitBuff/UnitDebuff follow-up) and temporary weapon-enchant icons via C_Item.GetWeaponEnchantInfo + C_Item.GetEnchantInfo + C_Spell.GetSpellTexture. This drops ~48 tooltip create/scan/hide ops per uncached effect and, unlike the old FindBuff, actually yields an icon for weapon-enchant-named effects. The dead tracking-spell branch is removed, the AddAnimation call site no longer dead-ends on non-matches (falls through to the spellId/Babble/item resolvers), and the now-unused MSBT_Tooltip frame is removed from the XML.
2026-06-23 02:10:07 -05:00
Brues 9d0f945c59 Make FindItemIcon return the icon consistently from both paths
The equipped-slot path returned (slot, nil, icon, count) while the bag path returned just the icon. The sole caller (AddAnimation) uses only the first return value as the texture, so equipped items produced a slot number instead of an icon path. Both paths now return the icon as the first value. Also call FindItemIcon once in the caller instead of three times, folding the no-icon case into the same branch.
2026-06-22 19:15:30 -05:00
Brues 8c35b8b6ad Fix equipped-item match in FindItemIcon and drop the link loop
The equipped-slot check compared itemName to its own lowercase (always matching the first named slot) instead of the searched item; now it compares against item. The separate GetInventoryItemLink/ItemLinkToName loop for slots past INVSLOT_LAST_EQUIPPED is folded into the ItemLocation loop by extending its range by 4.
2026-06-22 19:09:27 -05:00
Brues 6418359865 use IsPlayerGuid from classicapi 2026-06-22 19:00:58 -05:00
Brues f42c2cf6ca Drop spellNameCache; C_Spell.GetSpellName is a cheap DBC read
The cache originally wrapped the SuperWoW/Nampower pcall fallback chain, where it mattered. Now that GetSpellNameFromId is a single C_Spell.GetSpellName call (a single-field DBC + locale read), the cache only saved a boundary crossing and a string-intern hash per repeated lookup -- and Lua 5.0 interns strings, so it never saved allocations. Not worth the extra table and branch.
2026-06-22 18:49:32 -05:00
Brues c095b76d10 Drop hasNampower gate on UnitGUID calls (provided by ClassicAPI)
UnitGUID is supplied by ClassicAPI, so player/pet GUID resolution no longer needs to be conditional on Nampower. Simplifies the player GUID caching (Init + PLAYER_ENTERING_WORLD retry), IsPetGUID, and EnsurePlayerGUID. GetNameFromGUID stays on Nampower's GetUnitField since it resolves NPC names too, which ClassicAPI's player-only UnitNameFromGUID does not cover.
2026-06-22 18:16:22 -05:00
Brues e8b3b81241 Remove SuperWoW and UnitXP SP3 integration
Drops the SuperWoW and UnitXP SP3 detection flags and all their code paths. GUID/unit-name resolution (GetNameFromGUID, IsPetGUID, EnsurePlayerGUID, player GUID caching) now relies solely on Nampower APIs; the spellId icon fast path keeps only its Nampower branch; and GetUnitIDFromName falls back to the raw-combat-logging path and name cache. UnitXP was detection-only and never read. README updated to reflect the removal.
2026-06-22 18:12:51 -05:00
Brues d13a4102b8 Document ClassicAPI requirement; deprecate SuperWoW/UnitXP
Add a Requirements section noting MSBT now depends on the ClassicAPI client DLL for C_Spell/C_Item/ItemLocation/CreateColor. Retitle the integration section to focus on Nampower and mark the SuperWoW and UnitXP SP3 paths as deprecated and slated for removal.
2026-06-22 18:07:57 -05:00
Brues dce8df9e12 Normalize indentation in GetUnorderedCaptureDataTable
Convert the function body from 2-space to single-space (tab-style) indentation to match the surrounding file. No behavior change.
2026-06-22 18:02:34 -05:00
Brues 7502df37cf Change nampower school table to sequential index keys
nampowerSchoolToType now uses sequential keys (0=Physical, then implicit 1-6 for Holy/Fire/Nature/Frost/Shadow/Arcane) instead of the previous power-of-two bitmask keys (0,1,2,4,8,16,32).
2026-06-22 18:02:34 -05:00
Brues bf5be40e78 Use C_Spell/C_Item APIs for spell name and item icon lookups
GetSpellNameFromId now calls C_Spell.GetSpellName instead of the SuperWoW/Nampower pcall chain. FindItemIcon iterates equipped slots and bags via ItemLocation and C_Item.GetItemName/GetItemIcon. AddAnimation hoists strlower(name) into a local lowerName to avoid repeated calls and feeds the lowercased name to FindItemIcon.
2026-06-22 18:00:24 -05:00
Brues 6a9dd18ce0 Use CreateColor for damage type text coloring
Replace the manual {r,g,b} table and hex color-prefix strings with CreateColor-based color objects. GetDamageTypeFontColor now builds each school color via a CreateSpellColor helper that also caches a colorStr markup string, adds a Holy color, and retunes the existing school colors. FormatEventText and AddAnimation consume the new objects (color.colorStr and dtColor:GetRGB()), and the dead GetDamageTypeColor lookup is removed.
2026-06-22 18:00:04 -05:00
Brues 3f08a237de add Numen font 2026-06-22 17:52:29 -05:00
14 changed files with 696 additions and 15058 deletions
+23
View File
@@ -0,0 +1,23 @@
name: Package and release
on:
push:
tags:
- '**'
permissions:
contents: write
jobs:
package:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Package and create GitHub release
uses: BigWigsMods/packager@v2
env:
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
+10
View File
@@ -0,0 +1,10 @@
package-as: MikScrollingBattleText
enable-nolib-creation: no
move-folders:
MikScrollingBattleText/MikScrollingBattleText: MikScrollingBattleText
MikScrollingBattleText/MikScrollingBattleTextOptions: MikScrollingBattleTextOptions
ignore:
- README.md
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,13 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
<!-- Frame that handles core events -->
<Frame name="MCEHEventFrame">
<Scripts>
<OnEvent>MikCEH.OnEvent();</OnEvent>
<OnLoad>MikCEH.OnLoad();</OnLoad>
<OnUpdate>MikCEH.OnUpdate();</OnUpdate>
</Scripts>
</Frame>
</Ui>
File diff suppressed because it is too large Load Diff
@@ -1,14 +1,14 @@
## Interface: 11200 ## Interface: 11200
## Version: 4.43 ## Version: @project-version@
## Title: Mik's Scrolling Battle Text ## Title: Mik's Scrolling Battle Text
## Notes: Scrolls battle information around the character model. ## Notes: Scrolls battle information around the character model.
## Notes-ruRU: Прокрутка информации боя вокруг модели персонажа. ## Notes-ruRU: Прокрутка информации боя вокруг модели персонажа.
## Dependencies: !!!ClassicAPI
## OptionalDeps: SW_FixLogStrings ## OptionalDeps: SW_FixLogStrings
## SavedVariables: MikSBT_Save ## SavedVariables: MikSBT_Save
Libs\AceLibrary\AceLibrary.lua Libs\AceLibrary\AceLibrary.lua
Libs\AceLocale-2.2\AceLocale-2.2.lua Libs\AceLocale-2.2\AceLocale-2.2.lua
Libs\BabbleSpell-2.2\Babble-Spell-2.2.lua
MikScrollingBattleText-enUS.lua MikScrollingBattleText-enUS.lua
MikScrollingBattleText-frFR.lua MikScrollingBattleText-frFR.lua
@@ -16,8 +16,5 @@ MikScrollingBattleText-deDE.lua
MikScrollingBattleText-ruRU.lua MikScrollingBattleText-ruRU.lua
localization.lua localization.lua
MikTableRecyclerObject.lua
MikCombatEventHelper.lua MikCombatEventHelper.lua
MikScrollingBattleText.lua MikScrollingBattleText.lua
MikCombatEventHelper.xml
MikScrollingBattleText.xml
@@ -1,385 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
<!-- Frame that handles core events -->
<Frame name="MSBTEventFrame">
<Scripts>
<OnEvent>MikSBT.OnEvent();</OnEvent>
<OnLoad>MikSBT.OnLoad();</OnLoad>
<OnUpdate>MikSBT.OnUpdate();</OnUpdate>
</Scripts>
</Frame>
<!-- Tooltip -->
<GameTooltip name="MSBT_Tooltip" frameStrata="TOOLTIP" hidden="true" parent="UIParent" inherits="GameTooltipTemplate">
<Scripts>
<OnLoad>
this:SetOwner(WorldFrame, "ANCHOR_NONE");
</OnLoad>
</Scripts>
</GameTooltip>
<!-- Incoming Scroll Area -->
<Frame name="MSBTFrameIncoming" toplevel="true" enableMouse="false" parent="UIParent" frameStrata="HIGH" hidden="true">
<Size>
<AbsDimension x="24" y="24" />
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="CENTER" relativeTo="UIParent">
<Offset>
<AbsDimension x="-60" y="-160" />
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentText1" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText2" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText3" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText4" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText5" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText6" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText7" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText8" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText9" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText10" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText11" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText12" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText13" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText14" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText15" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText16" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText17" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText18" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText19" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
<FontString name="$parentText20" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMRIGHT" />
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnUpdate>MikSBT.OnUpdateAnimationFrame(this);</OnUpdate>
</Scripts>
</Frame>
<!-- Notification Scroll Area -->
<Frame name="MSBTFrameNotification" toplevel="true" enableMouse="false" parent="UIParent" frameStrata="HIGH" hidden="true">
<Size>
<AbsDimension x="24" y="25" />
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="CENTER" relativeTo="UIParent">
<Offset>
<AbsDimension x="0" y="100" />
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentText1" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText2" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText3" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText4" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText5" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText6" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText7" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText8" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText9" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText10" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText11" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText12" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText13" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText14" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText15" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText16" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText17" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText18" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText19" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText20" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnUpdate>MikSBT.OnUpdateAnimationFrame(this);</OnUpdate>
</Scripts>
</Frame>
<!-- Outgoing Scroll Area -->
<Frame name="MSBTFrameOutgoing" toplevel="true" enableMouse="false" parent="UIParent" frameStrata="HIGH" hidden="true">
<Size>
<AbsDimension x="24" y="24" />
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="CENTER" relativeTo="UIParent">
<Offset>
<AbsDimension x="60" y="-160" />
</Offset>
</Anchor>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="$parentText1" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText2" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText3" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText4" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText5" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText6" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText7" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText8" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText9" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText10" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText11" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOM" />
</Anchors>
</FontString>
<FontString name="$parentText12" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText13" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText14" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText15" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText16" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText17" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText18" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText19" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
<FontString name="$parentText20" inherits="MasterFont">
<Anchors>
<Anchor point="BOTTOMLEFT" />
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnUpdate>MikSBT.OnUpdateAnimationFrame(this);</OnUpdate>
</Scripts>
</Frame>
</Ui>
@@ -1,168 +0,0 @@
-------------------------------------------------------------------------------------
-- Title: Mik's Table Recyler Object
-- Author: Mik
-- Maintainer: Athene
-- Credits:
-- Thanks to tekkub, the author of compostLib. I adapted much of his code for
-- this object.
-------------------------------------------------------------------------------------
-- Create "namespace."
MikTRO = {};
-- Set the __index property to the recycler object namespace so
-- when a new recycler object sets it metatable to the namespace
-- the recycler object inherits the functions in the namespace.
MikTRO.__index = MikTRO;
-- **********************************************************************************
-- Creates a recycler object.
-- **********************************************************************************
function MikTRO:NewRecyclerObject(maxEntries)
-- Create a table to use.
recyclerObject = {};
-- Create a table to hold the cache entries and set its max permanent size.
recyclerObject.PrimaryCache = {};
recyclerObject.PrimaryCacheSize = 0;
recyclerObject.MaxEntries = maxEntries;
-- Create some variables to hold stats.
recyclerObject.NumNew = 0;
recyclerObject.NumRecycled = 0;
recyclerObject.NumErased = 0;
recyclerObject.NumReclaimed = 0;
recyclerObject.AmountMemFreed = 0;
-- Create a table to hold overflow entries. If more tables are reclaimed
-- than the size of the max primary cache can hold, they will be reclaimed
-- into the overflow cache which is a weak table. This allows for spikes
-- in cache usage to still be optimized while not preventing garbage
-- collection on the extra data once there are no other references to them.
recyclerObject.OverflowCache = {};
setmetatable(recyclerObject.OverflowCache, {__mode = "v"});
-- Set the meta table for the cache object to the table recycler
-- obect's namespace so the cache object inherits the functions of
-- table recycler object.
setmetatable(recyclerObject, self);
-- Return the recycler object.
return recyclerObject;
end
-- **********************************************************************************
-- Removes a table from the cache and returns it. If there are no tables available
-- in the cache a new one is returned.
-- **********************************************************************************
function MikTRO:AcquireTable()
-- Check if there are any tables available in the primary cache and if so
-- return one.
if (self.PrimaryCacheSize > 0) then
-- Increment the number of recycled tables.
self.NumRecycled = self.NumRecycled + 1;
self.PrimaryCacheSize = self.PrimaryCacheSize - 1;
return table.remove(self.PrimaryCache);
-- Check if there are any tables available in the overflow cache and if so
-- return one.
elseif self:TablesInOverflow() then
-- Increment the number of recycled tables.
self.NumRecycled = self.NumRecycled + 1;
-- Loop through the tables in the overflow and return one.
for i in pairs(self.OverflowCache) do
return table.remove(self.OverflowCache, i);
end
-- No tables available so return a new one.
else
-- Increment the number of new tables created.
self.NumNew = self.NumNew + 1;
return {};
end
end
-- **********************************************************************************
-- Reclaims a table into the cache.
-- **********************************************************************************
function MikTRO:ReclaimTable(t)
-- Check if the passed value isn't valid.
if (type(t) ~= "table") then
return;
end
-- Erase the passed table.
self:EraseTable(t);
-- Check if the primary cache is already full.
if (self.PrimaryCacheSize >= self.MaxEntries) then
-- Insert the table into the overflow cache.
table.insert(self.OverflowCache, t);
else
-- Insert the table into the primary cache.
table.insert(self.PrimaryCache, t);
self.PrimaryCacheSize = self.PrimaryCacheSize + 1;
end
-- Increment the number of reclaimed tables.
self.NumReclaimed = self.NumReclaimed + 1;
end
-- **********************************************************************************
-- Erases the passed table. Subtables are NOT erased.
-- **********************************************************************************
function MikTRO:EraseTable(t)
-- Check if the passed value isn't valid.
if (type(t) ~= "table") then
return;
end
-- Loop through all the keys in the table and clear it.
for key in pairs(t) do
t[key] = nil;
end
-- Set the length of the table to 0.
table.setn(t, 0);
-- Increment the number of tables erased.
self.NumErased = self.NumErased + 1;
end
-- **********************************************************************************
-- Prints stats.
-- **********************************************************************************
function MikTRO:PrintStats()
local overflowSize = 0;
for i in pairs(self.OverflowCache) do
overflowSize = overflowSize + 1;
end
DEFAULT_CHAT_FRAME:AddMessage(string.format(
"|cff00ff00New Tables: %d|r |cffffff00Recycled Tables: %d|r |cff00ffffCached Tables: %d|r |cffff0000Overflow Tables: %d|r |cff888888Erased Tables: %d|r |cffff00ffMemory Saved: %d KiB|r |cffff0088Tables Lost to GC: %d",
self.NumNew,
self.NumRecycled,
self.PrimaryCacheSize,
overflowSize,
self.NumErased,
self.AmountMemFreed + ((32/1024) * self.NumRecycled),
self.NumReclaimed - self.NumRecycled - self.PrimaryCacheSize));
end
-- **********************************************************************************
-- Checks if there are any tables in the overflow cache.
-- **********************************************************************************
function MikTRO:TablesInOverflow()
return next(self.OverflowCache) ~= nil;
end
+26 -20
View File
@@ -6,21 +6,27 @@
-- Create "namespace." -- Create "namespace."
MikSBT = {}; MikSBT = {};
local addonName, addonTable = ...
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Mod Constants -- Mod Constants
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
MikSBT.MOD_NAME = "MikScrollingBattleText" MikSBT.MOD_NAME = addonName
MikSBT.VERSION_NUMBER = 4.43;
MikSBT.VERSION_STRING = "v4.43 beta"; -- The packager fills in the .toc version ("v4.45"); an unpackaged checkout still has the
MikSBT.WINDOW_TITLE = "Mik's Scrolling Battle Text " .. MikSBT.VERSION_STRING .. " - \124cffF58CBA\124hAthene Edit\124h\124r"; -- "@project-version@" placeholder.
local version = GetAddOnMetadata(addonName, "Version");
MikSBT.VERSION_STRING = string.find(version, "^@") and "dev" or version;
MikSBT.WINDOW_TITLE = "Mik's Scrolling Battle Text " .. MikSBT.VERSION_STRING .. " - \124cffF58CBA\124hClassicAPI Edition\124h\124r";
MikSBT.COMMAND = "/msbt"; MikSBT.COMMAND = "/msbt";
local BS = AceLibrary("Babble-Spell-2.2")
local L = AceLibrary("AceLocale-2.2"):new(MikSBT.MOD_NAME) local L = AceLibrary("AceLocale-2.2"):new(MikSBT.MOD_NAME)
-- Resolves a spell's localized name from its ID via ClassicAPI (C_Spell), replacing
-- the old Babble-Spell localization library. Any rank's spell ID yields the same name.
local function SpellName(id) return C_Spell.GetSpellName(id) or "" end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- English (Default) -- English (Default)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -45,7 +51,7 @@ MikSBT.COMMAND_USAGE = {
" " .. MikSBT.COMMAND_DISABLE .. " - Disables the mod.", " " .. MikSBT.COMMAND_DISABLE .. " - Disables the mod.",
" " .. MikSBT.COMMAND_ENABLE .. " - Enables the mod.", " " .. MikSBT.COMMAND_ENABLE .. " - Enables the mod.",
" " .. MikSBT.COMMAND_SHOWVER .. " - Shows the current version.", " " .. MikSBT.COMMAND_SHOWVER .. " - Shows the current version.",
" " .. MikSBT.COMMAND_STATS .. " - Reports stats about table recycling.", " " .. MikSBT.COMMAND_STATS .. " - Reports how many pooled event tables are in use.",
" " .. MikSBT.COMMAND_SEARCH .. " filter - Sets a filter for searching event types.", " " .. MikSBT.COMMAND_SEARCH .. " filter - Sets a filter for searching event types.",
" " .. MikSBT.COMMAND_DEBUG .. " - Toggles debug mode.", " " .. MikSBT.COMMAND_DEBUG .. " - Toggles debug mode.",
" " .. MikSBT.COMMAND_HELP .. " - Show the command usage.", " " .. MikSBT.COMMAND_HELP .. " - Show the command usage.",
@@ -126,6 +132,7 @@ MikSBT.AVAILABLE_FONTS = {
[30] = {Name="PT-Sans-Narrow-Regular", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\PT-Sans-Narrow-Regular.ttf"}, [30] = {Name="PT-Sans-Narrow-Regular", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\PT-Sans-Narrow-Regular.ttf"},
[31] = {Name="Simhei", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\simhei.ttf"}, [31] = {Name="Simhei", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\simhei.ttf"},
[32] = {Name="Archangelsk", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\archangelsk.ttf"}, [32] = {Name="Archangelsk", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\archangelsk.ttf"},
[32] = {Name="Numen", Path="Interface\\Addons\\MikScrollingBattleText\\Fonts\\Numen.ttf"},
}; };
end end
@@ -202,10 +209,9 @@ MikSBT.DEFAULT_PROFILE_NAME = "Default";
-- %s = name of the spell, ability, buff, debuff, power type, etc. -- %s = name of the spell, ability, buff, debuff, power type, etc.
-- %t = damage type -- %t = damage type
MikSBT.DEFAULT_CONFIG = { MikSBT.DEFAULT_CONFIG = {
CreationVersion = MikSBT.VERSION_NUMBER,
ShowPartialEffects = true, ShowPartialEffects = true,
ShowOverheals = true, ShowOverheals = true,
ShowGameDamage = true, ShowGameDamage = false,
UseStickyCrits = true, UseStickyCrits = true,
ShowAllManaGains = false, ShowAllManaGains = false,
LowHealthSound = true, LowHealthSound = true,
@@ -1134,7 +1140,7 @@ MikSBT.DEFAULT_CONFIG = {
MSBT_TRIGGER_EXECUTE = { MSBT_TRIGGER_EXECUTE = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Execute"].."!", Message = SpellName(5308).."!", -- Execute
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1151,7 +1157,7 @@ MikSBT.DEFAULT_CONFIG = {
MSBT_TRIGGER_HAMMER_OF_WRATH = { MSBT_TRIGGER_HAMMER_OF_WRATH = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Hammer of Wrath"].."!", Message = SpellName(24275).."!", -- Hammer of Wrath
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1168,7 +1174,7 @@ MikSBT.DEFAULT_CONFIG = {
MSBT_TRIGGER_COUNTER_ATTACK = { MSBT_TRIGGER_COUNTER_ATTACK = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Counterattack"].."!", Message = SpellName(19306).."!", -- Counterattack
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1187,7 +1193,7 @@ MikSBT.DEFAULT_CONFIG = {
MSBT_TRIGGER_MONGOOSE_BITE = { MSBT_TRIGGER_MONGOOSE_BITE = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Mongoose Bite"].."!", Message = SpellName(1495).."!", -- Mongoose Bite
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1206,7 +1212,7 @@ MikSBT.DEFAULT_CONFIG = {
MSBT_TRIGGER_CLEARCAST = { MSBT_TRIGGER_CLEARCAST = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Clearcasting"].."!", Message = SpellName(16246).."!", -- Clearcasting
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1217,14 +1223,14 @@ MikSBT.DEFAULT_CONFIG = {
Classes = {MAGE=true,SHAMAN=true}, Classes = {MAGE=true,SHAMAN=true},
TriggerType = 6, TriggerType = 6,
TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},
SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, BS["Clearcasting"])}, SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, SpellName(16246))}, -- Clearcasting (ID verified vs Spell.dbc)
}, },
Texture = "Interface\\Icons\\spell_shadow_manaburn" Texture = "Interface\\Icons\\spell_shadow_manaburn"
}, },
MSBT_TRIGGER_RIPOSTE = { MSBT_TRIGGER_RIPOSTE = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Riposte"].."!", Message = SpellName(14251).."!", -- Riposte
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -1253,14 +1259,14 @@ MikSBT.DEFAULT_CONFIG = {
TriggerSettings = { TriggerSettings = {
TriggerType = 6, TriggerType = 6,
TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},
SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, string.gsub(BS["Windfury Totem"], "-", "%%-"))}, --"Vous gagnez Totem Furie-des-vents" -- escape char ! SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, string.gsub(SpellName(8512), "-", "%%-"))}, -- Windfury Totem (ID verified vs Spell.dbc). "Vous gagnez Totem Furie-des-vents" -- escape char !
}, },
Texture = "Interface\\Icons\\spell_nature_cyclone" Texture = "Interface\\Icons\\spell_nature_cyclone"
}, },
MSBT_TRIGGER_NIGHTFALL = { MSBT_TRIGGER_NIGHTFALL = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Nightfall"].."!", Message = SpellName(18094).."!", -- Nightfall (talent)
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=0.709, g=0, b=0.709}, Color = {r=0.709, g=0, b=0.709},
@@ -1271,14 +1277,14 @@ MikSBT.DEFAULT_CONFIG = {
Classes = {WARLOCK=true}, Classes = {WARLOCK=true},
TriggerType = 6, TriggerType = 6,
TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, TriggerEvents = {"CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},
SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, BS["Shadow Trance"])}, SearchPatterns = {string.format(AURAADDEDSELFHELPFUL, SpellName(17941))}, -- Shadow Trance (ID verified vs Spell.dbc)
}, },
Texture = "Interface\\Icons\\spell_shadow_twilight" Texture = "Interface\\Icons\\spell_shadow_twilight"
}, },
MSBT_TRIGGER_OVERPOWER = { MSBT_TRIGGER_OVERPOWER = {
EventSettings = { EventSettings = {
Show = true, Show = true,
Message = BS["Overpower"].."!", Message = SpellName(7384).."!", -- Overpower
IsSticky = true, IsSticky = true,
FontSettings = { FontSettings = {
Color = {r=1, g=1, b=0}, Color = {r=1, g=1, b=0},
@@ -554,7 +554,7 @@ function MikSBTOpt.TriggerTypeDropdownOnClick(frameName)
UIDropDownMenu_SetSelectedValue(getglobal(frameName), this.value); UIDropDownMenu_SetSelectedValue(getglobal(frameName), this.value);
-- Setup the trigger controls appropriately depending on the trigger type. -- Setup the trigger controls appropriately depending on the trigger type.
MikSBTOpt.SetupVariableTriggerControls(getglobal(frameName):GetParent().TriggerKey, this.value == MikCEH.TRIGGERTYPE_SEARCH_PATTERN); MikSBTOpt.SetupVariableTriggerControls(getglobal(frameName):GetParent().TriggerKey, this.value == MikSBT.TRIGGERTYPE_SEARCH_PATTERN);
end end
@@ -3345,7 +3345,7 @@ function MikSBTOpt.ShowTriggerConfig(triggerKey)
MikSBTOpt.PopulateEditbox(TRIGGER_CONFIGURATION_FRAME_NAME .. "IconNameEditbox", texture); MikSBTOpt.PopulateEditbox(TRIGGER_CONFIGURATION_FRAME_NAME .. "IconNameEditbox", texture);
-- Setup the trigger controls appropriately depending on the trigger type. -- Setup the trigger controls appropriately depending on the trigger type.
MikSBTOpt.SetupVariableTriggerControls(triggerKey, triggerData.TriggerSettings.TriggerType == MikCEH.TRIGGERTYPE_SEARCH_PATTERN); MikSBTOpt.SetupVariableTriggerControls(triggerKey, triggerData.TriggerSettings.TriggerType == MikSBT.TRIGGERTYPE_SEARCH_PATTERN);
-- Show the trigger settings. -- Show the trigger settings.
triggerFrame:Show(); triggerFrame:Show();
@@ -3389,7 +3389,7 @@ function MikSBTOpt.SetupVariableTriggerControls(triggerKey, showSearch)
if (not triggerFrame.SelectedTriggerEvents) then if (not triggerFrame.SelectedTriggerEvents) then
triggerFrame.SelectedTriggerEvents = {}; triggerFrame.SelectedTriggerEvents = {};
else else
MikCEH.EraseTable(triggerFrame.SelectedTriggerEvents); table.wipe(triggerFrame.SelectedTriggerEvents);
end end
-- Loop through all of the trigger events for the trigger. -- Loop through all of the trigger events for the trigger.
@@ -3525,7 +3525,7 @@ function MikSBTOpt.SaveTriggerConfig()
end end
-- Check if the trigger type is search pattern. -- Check if the trigger type is search pattern.
if (triggerData.TriggerSettings.TriggerType == MikCEH.TRIGGERTYPE_SEARCH_PATTERN) then if (triggerData.TriggerSettings.TriggerType == MikSBT.TRIGGERTYPE_SEARCH_PATTERN) then
-- Clear the threshold field. -- Clear the threshold field.
triggerData.TriggerSettings.Threshold = nil; triggerData.TriggerSettings.Threshold = nil;
@@ -1,5 +1,5 @@
## Interface: 11200 ## Interface: 11200
## Version: 4.43 ## Version: @project-version@
## Title: Mik's Scrolling Battle Text Options ## Title: Mik's Scrolling Battle Text Options
## Notes: Load on demand options for Mik's Scrolling Battle Text ## Notes: Load on demand options for Mik's Scrolling Battle Text
## Notes-ruRU: Настройки для Mik's Scrolling Battle Text ## Notes-ruRU: Настройки для Mik's Scrolling Battle Text
+23 -26
View File
@@ -4,6 +4,10 @@ A World of Warcraft 1.12 (Vanilla) addon that displays scrolling combat text aro
**Interface:** 11200 | **Version:** 4.43 **Interface:** 11200 | **Version:** 4.43
## Requirements
- **ClassicAPI** — a client-side DLL that backports modern WoW API calls to the 1.12 client (no companion addon required). MSBT relies on it for `C_Spell.GetSpellName`, `C_Item.GetItemName`/`GetItemIcon`, `ItemLocation`, and `CreateColor`/`GetRGB` — used for spell-name lookups, item-icon resolution, and damage-type text coloring. These are not optional fast paths; the addon expects them to be present.
## Features ## Features
- Scrolling combat text across three display areas: **Incoming** (right), **Outgoing** (left), and **Notification** (center) - Scrolling combat text across three display areas: **Incoming** (right), **Outgoing** (left), and **Notification** (center)
@@ -55,56 +59,50 @@ Interface/
| `/msbt disable` | Disable the addon | | `/msbt disable` | Disable the addon |
| `/msbt enable` | Enable the addon | | `/msbt enable` | Enable the addon |
| `/msbt version` | Show the current version | | `/msbt version` | Show the current version |
| `/msbt stats` | Report table recycling statistics | | `/msbt stats` | Report how many pooled event tables are in use |
| `/msbt search <filter>` | Set a filter for searching event types | | `/msbt search <filter>` | Set a filter for searching event types |
| `/msbt debug` | Toggle debug mode | | `/msbt debug` | Toggle debug mode |
| `/msbt help` | Show command usage | | `/msbt help` | Show command usage |
## Nampower / SuperWoW / UnitXP SP3 Integration ## ClassicAPI Combat Log Integration
When these enhanced client mods are detected, MSBT automatically switches from string-based combat log parsing to structured event handling for significantly better performance in heavy combat scenarios (raids, AoE, battlegrounds). MSBT reads structured combat data from ClassicAPI's `COMBAT_LOG_EVENT_UNFILTERED` instead of relying on string-based combat log parsing alone, for significantly better performance in heavy combat scenarios (raids, AoE, battlegrounds).
### What Changes ### What Changes
- **Nampower**: Registers for structured events (`SPELL_DAMAGE_EVENT_SELF`, `AUTO_ATTACK_SELF`, `SPELL_HEAL_ON_SELF`, etc.) that provide pre-parsed combat data. Redundant `CHAT_MSG_*` events are unregistered to avoid duplicates. Enables `NP_EnableAutoAttackEvents`, `NP_EnableSpellHealEvents`, and `NP_EnableSpellEnergizeEvents` CVars. - **ClassicAPI combat log**: Registers for the unfiltered combat log (`SPELL_DAMAGE`, `SWING_DAMAGE`, `SPELL_HEAL`, `SPELL_ENERGIZE`, `SPELL_MISSED`, `SPELL_AURA_APPLIED`, `ENVIRONMENTAL_DAMAGE`, `PARTY_KILL`, etc.) which carries pre-parsed amounts, GUIDs, crit flags, miss types and spell info. It is the only source for combat events. No opt-in CVars are needed.
- **SuperWoW**: Provides O(1) unit lookups by name via `UnitExists(name)` (replacing O(n) raid/party iteration) and `SpellInfo(spellId)` for spell icon resolution. - **Spell icons**: combat log events resolve icons from their SpellId with ClassicAPI's `C_Spell.GetSpellTexture`. Events with only a name fall back to the player's auras, spellbook and items; each name is looked up once.
- **UnitXP SP3**: Detected for compatibility; used for GUID-based unit resolution.
### Removed: SuperWoW / UnitXP SP3 / Nampower
SuperWoW, UnitXP SP3 and Nampower integration has been removed in favor of ClassicAPI (for spell/item lookups, GUIDs and structured combat events). ClassicAPI is a hard dependency (see the `.toc`).
### Fallback ### Fallback
When none of these mods are present, the addon falls back to the original string-parsing pipeline with no changes in behavior. `CHAT_MSG_*` messages are parsed only for what the combat log lacks (honor, reputation, skill, XP, item enchantments, power losses). All of them stay registered because search pattern triggers can match any of them.
### Verification
```lua
-- Check detection status in-game:
/run MikSBT.Print("NP="..tostring(MikCEH.hasNampower).." SW="..tostring(MikCEH.hasSuperWoW).." UXP="..tostring(MikCEH.hasUnitXP))
```
## Performance Optimizations ## Performance Optimizations
- **Upvalue caching**: Frequently called standard library functions (`string.find`, `string.gsub`, `table.insert`, `table.getn`, `GetTime`, etc.) are cached as local variables - **Upvalue caching**: Frequently called standard library functions (`string.find`, `string.gsub`, `table.insert`, `table.getn`, `GetTime`, etc.) are cached as local variables
- **Dispatch table**: Combat event routing uses O(1) table lookup instead of an if/elseif chain - **Dispatch table**: Combat event routing uses O(1) table lookup instead of an if/elseif chain
- **SpellId icon cache**: When spellIds are available (via Nampower/SuperWoW), icons are resolved directly and cached, bypassing Babble-Spell dictionary lookups and tooltip scanning - **Unit event filtering**: `UNIT_HEALTH` (player, target, pet) and `UNIT_MANA` (player) use ClassicAPI's `RegisterUnitEvent`, so other units' updates never reach Lua
- **Event throttling**: UNIT_HEALTH and UNIT_MANA trigger checks are throttled to 150ms intervals - **Table pooling**: Animation event tables come from a ClassicAPI object pool (`CreateUnsecuredObjectPool`) and are reused, so 1.12's stop-the-world GC runs less often
- **Table recycling**: `MikTRO` (Table Recycler Object) pools and reuses table allocations to reduce garbage collection pressure
## Architecture ## Architecture
### Global Namespaces ### Namespaces
| Namespace | Purpose | | Namespace | Purpose |
|---|---| |---|---|
| `MikSBT` | Main addon: display, animation, profiles, event routing, slash commands | | `MikSBT` | Global. Main addon: display, animation, profiles, event routing, slash commands, and the API the options addon and other addons use |
| `MikCEH` | Combat Event Helper: parses combat events into structured data | | `MikCEH` | Private, shared through the addon table. Combat Event Helper: parses combat events into structured data |
| `MikTRO` | Table Recycler Object: memory pool for table reuse |
### Event Processing Pipeline ### Event Processing Pipeline
``` ```
WoW CHAT_MSG_* events (or Nampower structured events) ClassicAPI COMBAT_LOG_EVENT_UNFILTERED (plus CHAT_MSG_* for triggers and non-combat notifications)
-> MikCEH.OnEvent() / MikCEH.OnNampowerEvent() -> MikCEH.OnEvent() / MikCEH.OnCombatLogEvent()
-> ParseCombatEvents() dispatch table (or Nampower handler) -> ParseCombatEvents() dispatch table (or combat log handler)
-> Creates CombatEventData tables -> Creates CombatEventData tables
-> MikSBT.CombatEventsHandler() -> MikSBT.CombatEventsHandler()
-> Formats text with templates (%a=amount, %n=name, %s=spell, %t=type) -> Formats text with templates (%a=amount, %n=name, %s=spell, %t=type)
@@ -116,11 +114,10 @@ WoW CHAT_MSG_* events (or Nampower structured events)
- **AceLibrary** — Addon framework skeleton - **AceLibrary** — Addon framework skeleton
- **AceLocale-2.2** — Localization management - **AceLocale-2.2** — Localization management
- **Babble-Spell-2.2** — Spell name database for icon lookups (~10K lines)
### Saved Variables ### Saved Variables
`MikSBT_Save` — Stores named profiles containing event settings, triggers, suppressions, display positions, and font settings. Profiles support versioning and migration between addon versions. `MikSBT_Save` — Stores named profiles containing event settings, triggers, suppressions, display positions, and font settings. On load, settings added in newer versions are filled into existing profiles from the defaults.
## Development ## Development