local band = bit.band; local CreateFrame = CreateFrame; local GetActionInfo = GetActionInfo; local lshift = bit.lshift; local next = next; local OVERLAY_GLOW_SPELL_MAP = CHEESE_OVERLAY_GLOW_SPELL_MAP; local OVERLAY_GLOW_SPELL_TABLE = CHEESE_OVERLAY_GLOW_SPELL_TABLE; local OVERLAY_MAP = CHEESE_OVERLAY_MAP; local OVERLAY_TABLE = CHEESE_OVERLAY_TABLE; local OVERLAYS_UPPER_BOUND = CHEESE_OVERLAYS_UPPER_BOUND; local pairs = pairs; local PlayerFrame = PlayerFrame; local rshift = bit.rshift; local UnitBuff = UnitBuff; local NUM_ACTION_BUTTONS = 12 * 12; local actionButtons = { nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil, }; local buffGlowSpells = {}; local buffs = {}; local spellsOverlayed = {}; local eventOverlayShowListeners = {}; local eventOverlayHideListeners = {}; local eventOverlayGlowShowListeners = {}; local eventOverlayGlowHideListeners = {}; local eventListeners = { ["CHEESE_SPELL_ACTIVATION_OVERLAY_SHOW"] = eventOverlayShowListeners, ["CHEESE_SPELL_ACTIVATION_OVERLAY_HIDE"] = eventOverlayHideListeners, ["CHEESE_SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"] = eventOverlayGlowShowListeners, ["CHEESE_SPELL_ACTIVATION_OVERLAY_GLOW_HIDE"] = eventOverlayGlowHideListeners, }; local eventFrame1 = CreateFrame("Frame"); local eventFrame2 = CreateFrame("Frame"); local function AddOverlayGlow(globalID) local overlayedCount = spellsOverlayed[globalID]; if ( not overlayedCount ) then spellsOverlayed[globalID] = 1; for frame, func in pairs(eventOverlayGlowShowListeners) do func(frame, globalID); end else spellsOverlayed[globalID] = overlayedCount + 1; end end local function RemoveOverlayGlow(globalID) local overlayedCount = spellsOverlayed[globalID]; if ( overlayedCount == 1 ) then spellsOverlayed[globalID] = nil; for frame, func in pairs(eventOverlayGlowHideListeners) do func(frame, globalID); end else spellsOverlayed[globalID] = overlayedCount - 1; end end local function SetAction(action, globalID) actionButtons[action] = globalID; if ( globalID ) then local glowSpellK = OVERLAY_GLOW_SPELL_MAP()[globalID]; if ( glowSpellK ) then local overlayGlowSpellTable = OVERLAY_GLOW_SPELL_TABLE(); local spellID = overlayGlowSpellTable[glowSpellK]; repeat local glowSpells = buffGlowSpells[spellID]; if ( not glowSpells ) then buffGlowSpells[spellID] = { [globalID] = 1; }; if ( buffs[spellID] ) then AddOverlayGlow(globalID); end else local refCount = glowSpells[globalID]; if ( not refCount ) then glowSpells[globalID] = 1; if ( buffs[spellID] ) then AddOverlayGlow(globalID); end else glowSpells[globalID] = refCount + 1; end end glowSpellK = glowSpellK + 1; spellID = overlayGlowSpellTable[glowSpellK]; until not spellID end end end local function ChangeAction(action, newGlobalID) local globalID = actionButtons[action]; if ( globalID ) then local glowSpellK = OVERLAY_GLOW_SPELL_MAP()[globalID]; if ( glowSpellK ) then local overlayGlowSpellTable = OVERLAY_GLOW_SPELL_TABLE(); local spellID = overlayGlowSpellTable[glowSpellK]; repeat local glowSpells = buffGlowSpells[spellID]; local refCount = glowSpells[globalID]; if ( refCount == 1 ) then glowSpells[globalID] = nil; if ( next(glowSpells) == nil ) then glowSpells = nil; buffGlowSpells[spellID] = nil; end if ( buffs[spellID] ) then RemoveOverlayGlow(globalID); end else glowSpells[globalID] = refCount - 1; end glowSpellK = glowSpellK + 1; spellID = overlayGlowSpellTable[glowSpellK]; until not spellID end end SetAction(action, newGlobalID); end local function BuffGained(spellID, k, overlayTable) if ( k < OVERLAYS_UPPER_BOUND ) then local texture = "INTERFACE\\ADDONS\\CHEESE\\TEXTURES\\SPELLACTIVATIONOVERLAYS\\"..overlayTable[k + 1]; local positions = overlayTable[k + 2]; local scale = overlayTable[k + 3]; local vertexColor = overlayTable[k + 4]; local r = rshift(lshift(vertexColor, 8), 24); local g = rshift(lshift(vertexColor, 16), 24); local b = band(vertexColor, 0xff); for frame, func in pairs(eventOverlayShowListeners) do func(frame, spellID, texture, positions, scale, r, g, b); end end local glowSpells = buffGlowSpells[spellID]; if ( glowSpells ) then for globalID in pairs(glowSpells) do AddOverlayGlow(globalID); end end end local function BuffLost(spellID) for frame, func in pairs(eventOverlayHideListeners) do func(frame, spellID); end local glowSpells = buffGlowSpells[spellID]; if ( glowSpells ) then for globalID in pairs(glowSpells) do RemoveOverlayGlow(globalID); end end end local function eventFrame1_OnEventActionbarSlotChanged(self, event, action) if ( action ~= 0 ) then local actionType, id, subType, globalID = GetActionInfo(action); if ( actionType == "spell" ) then if ( actionButtons[action] ~= globalID ) then ChangeAction(action, globalID); end else if ( actionButtons[action] ) then ChangeAction(action, nil); end end else for action=1, NUM_ACTION_BUTTONS do local actionType, id, subType, globalID = GetActionInfo(action); if ( actionType == "spell" ) then if ( actionButtons[action] ~= globalID ) then ChangeAction(action, globalID); end else if ( actionButtons[action] ) then ChangeAction(action, nil); end end end end end local function eventFrame2_OnEventUnitAura(self, event, unitID) local unit = PlayerFrame.unit; if ( unitID == unit ) then do local name, _, _, count, _, _, _, _, _, _, spellID = UnitBuff(unit, 1); if ( name ) then local overlayMap = OVERLAY_MAP(); local overlayTable; local j = 1; repeat local k = overlayMap[spellID]; if ( k ) then if ( not overlayTable ) then overlayTable = OVERLAY_TABLE(); end if ( not (count < overlayTable[k]) ) then local hasBuff = buffs[spellID]; buffs[spellID] = false; if ( hasBuff == nil ) then BuffGained(spellID, k, overlayTable); end end end j=j+1; name, _, _, count, _, _, _, _, _, _, spellID = UnitBuff(unit, j); until not name end end for spellID, hasBuff in pairs(buffs) do if ( not hasBuff ) then buffs[spellID] = true; else buffs[spellID] = nil; BuffLost(spellID); end end end end local function eventFrame1_OnEventPlayerLogin(self) eventFrame1:UnregisterEvent("PLAYER_LOGIN"); do for action=1, NUM_ACTION_BUTTONS do local actionType, id, subType, globalID = GetActionInfo(action); if ( actionType == "spell" ) then SetAction(action, globalID); end end end eventFrame1:SetScript("OnEvent", eventFrame1_OnEventActionbarSlotChanged); eventFrame1:RegisterEvent("ACTIONBAR_SLOT_CHANGED"); do local unit = PlayerFrame.unit; local name, _, _, count, _, _, _, _, _, _, spellID = UnitBuff(unit, 1); if ( name ) then local overlayMap = OVERLAY_MAP(); local overlayTable; local j = 1; repeat local k = overlayMap[spellID]; if ( k ) then if ( not overlayTable ) then overlayTable = OVERLAY_TABLE(); end if ( not (count < overlayTable[k]) ) then buffs[spellID] = true; BuffGained(spellID, k, overlayTable); end end j=j+1; name, _, _, count, _, _, _, _, _, _, spellID = UnitBuff(unit, j); until not name end end eventFrame2:SetScript("OnEvent", eventFrame2_OnEventUnitAura); eventFrame2:RegisterEvent("UNIT_AURA"); end eventFrame1:SetScript("OnEvent", eventFrame1_OnEventPlayerLogin); eventFrame1:RegisterEvent("PLAYER_LOGIN"); function Cheese_IsSpellOverlayed(spellID) return spellsOverlayed[spellID] and true or false; end function Cheese_RegisterEvent(event, frame, func) local listeners = eventListeners[event]; if ( listeners ) then listeners[frame] = func; end end function Cheese_UnregisterEvent(event, frame) local listeners = eventListeners[event]; if ( listeners ) then listeners[frame] = nil; end end if ( GetCVarBool("scriptProfile") ) then function Cheese_GetAPISpellActivationOverlayFuncs() return eventFrame1_OnEventPlayerLogin, eventFrame1_OnEventActionbarSlotChanged, eventFrame2_OnEventUnitAura, BuffGained, BuffLost, SetAction, ChangeAction, AddOverlayGlow, RemoveOverlayGlow; end end