-- ActionBars.lua local _; local pairs = pairs; local format = string.format; local ssub = string.sub; local GetActionInfo, GetActionTexture = GetActionInfo, GetActionTexture; local GetActionLossOfControlCooldown = GetActionLossOfControlCooldown; local GetActionCooldown, GetActionCharges = GetActionCooldown, GetActionCharges; local GetActionText, GetBindingKey = GetActionText, GetBindingKey; local IsConsumableAction, IsStackableAction = IsConsumableAction, IsStackableAction; local IsItemAction, GetActionCount = IsItemAction, GetActionCount; local IsSpellOverlayed, GetMacroSpell = IsSpellOverlayed, GetMacroSpell; local IsMounted = IsMounted; local HasAction, IsUsableAction = HasAction, IsUsableAction; local IsCurrentAction, IsAutoRepeatAction = IsCurrentAction, IsAutoRepeatAction; local CreateFrame = CreateFrame; local RegisterStateDriver = RegisterStateDriver; local CooldownFrame_Set, CooldownFrame_Clear = CooldownFrame_Set, CooldownFrame_Clear; local GameTooltip = GameTooltip; local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor; local COOLDOWN_TYPE_LOSS_OF_CONTROL = COOLDOWN_TYPE_LOSS_OF_CONTROL; local COOLDOWN_TYPE_NORMAL = COOLDOWN_TYPE_NORMAL; local CDTexture = "Interface\\Cooldown\\edge"; local locCDTexture = "Interface\\Cooldown\\edge-LoC"; local BUTTONLOCK = true; -- change to lock button dragging local settings = { ["Oma1"] = { bar = 1, start = 1, length = 12, columns = 4, size = 40, x = 580, y = 300, nomouse = true, }, ["Oma2"] = { bar = 2, start = 13, length = 12, columns = 4, size = 40, x = 580, y = 180, nomouse = true, }, ["Oma3"] = { bar = 3, start = 25, length = 12, columns = 3, x = 1824, y = 128, flyout = "LEFT", }, ["Oma4"] = { bar = 4, start = 37, length = 12, columns = 3, x = 1824, y = 256, }, ["Oma5"] = { bar = 5, start = 49, length = 12, columns = 3, x = 1000, y = 840, }, ["Oma6"] = { bar = 6, start = 61, length = 12, x = 1000, y = 600, }, -- used as bonus bars for some classes ["Oma7"] = { bar = 7, start = 73, length = 12, x = 1000, y = 760, }, ["Oma8"] = { bar = 8, start = 85, length = 12, x = 1000, y = 720, }, ["Oma9"] = { bar = 9, start = 97, length = 12, x = 1000, y = 680, }, ["Oma10"] = { bar = 10, start = 109, length = 12, x = 1000, y = 640, }, }; local usingBonusbars = { --["WARRIOR"] = {[7]=true, [8]=true, [9]=true}, -- not using stance separated actionbars ["DRUID"] = {[7]=true, [8]=true, [9]=true}, -- moonkin form page is usable anyway --["DRUID"] = {[7]=true, [8]=true, [9]=true,[10]=true}, ["ROGUE"] = {[7]=true}, --["PRIEST"] = {[7]=true}, -- shadowform doesn't change abilities }; local chars = { ["Stormreaver"] = { ["Vildan"] = {1, 2, 3, 4,}, ["Gedren"] = {1, 2, 3, 4,}, ["Gazden"] = {1, 2, 3, 4,}, }, }; local buttons = {}; local activeButtons = {}; local ActionBars = CreateFrame("Frame", "OmaActionBars", UIParent); local inheritedFrames = "SecureActionButtonTemplate,SecureHandlerDragTemplate,SecureHandlerStateTemplate"; local function showTooltip(secure) GameTooltip_SetDefaultAnchor(GameTooltip, secure); GameTooltip:SetAction(secure:GetAttribute("action")); end local function hideTooltip() GameTooltip:Hide(); end local numChargeCDs = 0; local function createChargeCD(parent) numChargeCDs = numChargeCDs + 1; local frame = CreateFrame("Cooldown", "OmaChargeCD"..numChargeCDs, parent, "CooldownFrameTemplate"); frame:SetHideCountdownNumbers(false); frame:SetDrawSwipe(false); frame:SetAllPoints(parent); frame:SetFrameStrata("TOOLTIP"); return frame; end local function clearChargeCD(parent) if parent.chargecd then CooldownFrame_Clear(parent.chargecd) end end local function startChargeCD(parent, start, duration, modrate) if start == 0 then return clearChargeCD(parent); end parent.chargecd = parent.chargecd or createChargeCD(parent); CooldownFrame_Set(parent.chargecd, start, duration, true, true, modrate); end local redoCooldown; local function updateCooldown(button, slot) -- CD update from FrameXML/ActionButton.lua local locstart, locduration = GetActionLossOfControlCooldown(slot); local start, duration, enable, modrate = GetActionCooldown(slot); local charges, maxcharges, chargestart, chargeduration, chargemodrate = GetActionCharges(slot); -- avoid as many updates as possible by checking if there's changes first if button.prev and button.prev[1] == locstart and button.prev[2] == locduration and button.prev[3] == start and button.prev[4] == duration and button.prev[5] == enable and button.prev[6] == modrate and button.prev[7] == charges and button.prev[8] == maxcharges and button.prev[9] == chargestart and button.prev[10] == chargeduration and button.prev[11] == chargemodrate then return; end button.prev = { locstart, locduration, start, duration, enable, modrate, charges, maxcharges, chargestart, chargeduration, chargemodrate }; if (locstart + locduration) > (start + duration) then if button.cd.currentCooldownType ~= COOLDOWN_TYPE_LOSS_OF_CONTROL then button.cd:SetEdgeTexture(locCDTexture); button.cd:SetSwipeColor(0.17, 0, 0); button.cd:SetHideCountdownNumbers(true); button.cd.currentCooldownType = COOLDOWN_TYPE_LOSS_OF_CONTROL; end CooldownFrame_Set(button.cd, locstart, locduration, true, true, modrate); clearChargeCD(button); else if button.cd.currentCooldownType ~= COOLDOWN_TYPE_NORMAL then button.cd:SetEdgeTexture(CDTexture); button.cd:SetSwipeColor(0, 0, 0); button.cd:SetHideCountdownNumbers(false); button.cd.currentCooldownType = COOLDOWN_TYPE_NORMAL; end if locstart > 0 then button.cd:SetScript("OnCooldownDone", redoCooldown); end if charges and maxcharges and maxcharges > 1 and charges < maxcharges then startChargeCD(button, chargestart, chargeduration, chargemodrate); else clearChargeCD(button); end CooldownFrame_Set(button.cd, start, duration, enable, false, modrate); end end local function redoCooldown(cd) local button = cd:GetParent(); cd:SetScript("OnCooldownDone", nil); updateCooldown(button, button.slot); end local function updateCount(button, slot) if IsConsumableAction(slot) or IsStackableAction(slot) or (not IsItemAction(slot) and GetActionCount(slot) > 0) then local count = GetActionCount(slot); if count > 99 then button.count:SetText("*"); else button.count:SetText(count); end button.count:Show(); else local charges, maxcharges = GetActionCharges(slot); if maxcharges > 1 then button.count:SetText(charges); button.count:Show(); else button.count:Hide(); end end end local function updateUsable(button, slot) local isUsable, noMana = IsUsableAction(slot); if isUsable then button.icon:SetVertexColor(1, 1, 1); elseif noMana then button.icon:SetVertexColor(0, 0.5, 1); else button.icon:SetVertexColor(0.4, 0.4, 0.4); end end local function updateState(button, slot) button:SetChecked(IsCurrentAction(slot) or IsAutoRepeatAction(slot)); end local function updateGlow(button, slot) local stype, id, _ = GetActionInfo(slot); if stype == "spell" and IsSpellOverlayed(id) then button.glow:Show(); elseif stype == "macro" then local _, _, macroid = GetMacroSpell(id); if macroid and IsSpellOverlayed(macroid) then button.glow:Show(); else button.glow:Hide(); end else -- TODO FlyoutHasSpell glow button.glow:Hide(); end end local function startGlow(button, slot, spell) local stype, id, _ = GetActionInfo(slot); if stype == "spell" and id == spell then button.glow:Show(); elseif stype == "macro" then local _, _, macroid = GetMacroSpell(id); if macroid and macroid == spell then button.glow:Show(); end end -- TODO FlyoutHasSpell glow end local function stopGlow(button, slot, spell) local stype, id, _ = GetActionInfo(slot); if stype == "spell" and id == spell then button.glow:Hide(); elseif stype == "macro" then local _, _, macroid = GetMacroSpell(id); if macroid and macroid == spell then button.glow:Hide(); end end -- TODO FlyoutHasSpell glow end local function updateButton(button, slot) if HasAction(slot) then activeButtons[slot] = button; button.base:Show(); button.icon:SetTexture(GetActionTexture(slot)); updateCooldown(button, slot); updateUsable(button, slot); updateState(button, slot); updateCount(button, slot); updateGlow(button, slot); if not IsConsumableAction(slot) and not IsStackableAction(slot) then button.text:SetText(ssub(GetActionText(slot) or "", 1, 4)); button.text:Show(); end if button.hotkey.shown then button.hotkey:Show() end else activeButtons[slot] = nil; if not button.grid then button.base:Hide() end button.icon:SetTexture(nil); button.cd:Hide(); button.count:Hide(); button.hotkey:Hide(); button.text:Hide(); button.glow:Hide(); button:SetChecked(false); end end local function updateHotkeys(button) local key = GetBindingKey(format("CLICK %s:LeftButton", button:GetName())); if key and key ~= "" then -- from LibKeyBound-1.0 key = key:upper(); key = key:gsub(" ", ""); key = key:gsub("ALT%-", "a"); key = key:gsub("CTRL%-", "c"); key = key:gsub("SHIFT%-", "s"); key = key:gsub("NUMPAD", "n"); button.hotkey:SetText(key); button.hotkey.shown = true; button.hotkey:Show(); else button.hotkey.shown = nil; button.hotkey:Hide(); end end local mainbartoggle = "[overridebar][possessbar][shapeshift]possess;"; mainbartoggle = mainbartoggle.."[bonusbar:1,stealth:1]bonusbar2;"; -- prowl mainbartoggle = mainbartoggle.."[bonusbar:1]bonusbar1;[bonusbar:2]bonusbar2;"; -- cat form, unused mainbartoggle = mainbartoggle.."[bonusbar:3]bonusbar3;[bonusbar:4]bonusbar4;"; -- bear form, moonkin form mainbartoggle = mainbartoggle.."normal"; local function setupSnippets(secure, slot) -- FrameXML/SecureHandlers.lua has arguments and return value -- args: self, button, kind, value, ... (kind, value, ... from GetCursorInfo()) -- returns: kind, target, detail -- or: "clear", kind, target, detail -- used for Pickup* functions -- some of these snippets based on LibActionButton-1.0 secure:SetAttribute("_ondragstart", [=[ return "action", self:GetAttribute("action"); ]=]); secure:SetAttribute("_onreceivedrag", [=[ if not kind or not value then return nil end return "action", self:GetAttribute("action"); ]=]); -- pre-wrapper can pass a message to post-wrapper secure:WrapScript(secure, "OnDragStart", [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); return "message", format("%s|%s", tostring(kind), tostring(value)); ]=], [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); if message ~= format("%s|%s", tostring(kind), tostring(value)) then self:CallMethod("ActionChanged"); end ]=]); secure:WrapScript(secure, "OnReceiveDrag", [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); return "message", format("%s|%s", tostring(kind), tostring(value)); ]=], [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); if message ~= format("%s|%s", tostring(kind), tostring(value)) then self:CallMethod("ActionChanged"); end ]=]); function secure:UpdateState() return updateState(self, self.slot); end secure:WrapScript(secure, "OnClick", [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); return nil, format("%s|%s", tostring(kind), tostring(value)); ]=], [=[ local kind, value = GetActionInfo(self:GetAttribute("action")); if message ~= format("%s|%s", tostring(kind), tostring(value)) then self:CallMethod("ActionChanged"); else self:CallMethod("UpdateState"); end ]=]); if slot < 13 then -- first action bar has possible states based on vehicle/possess etc. secure:SetAttribute("origaction", slot); secure:SetAttribute("_onstate-possess", [=[ local oldslot = self:GetAttribute("action"); if newstate == "possess" then local slot; if HasVehicleActionBar() then slot = (GetVehicleBarIndex()-1)*12+self:GetAttribute("origaction"); elseif HasOverrideActionBar() then slot = (GetOverrideBarIndex()-1)*12+self:GetAttribute("origaction"); elseif HasTempShapeshiftActionBar() then slot = (GetTempShapeshiftBarIndex()-1)*12+self:GetAttribute("origaction"); else -- something wrong, just revert to normal print("Possess bar index not found"); slot = self:GetAttribute("origaction"); end self:SetAttribute("action", slot); elseif newstate == "bonusbar1" then self:SetAttribute("action", 72+self:GetAttribute("origaction")); elseif newstate == "bonusbar2" then self:SetAttribute("action", 84+self:GetAttribute("origaction")); elseif newstate == "bonusbar3" then self:SetAttribute("action", 96+self:GetAttribute("origaction")); elseif newstate == "bonusbar4" then --self:SetAttribute("action", 108+self:GetAttribute("origaction")); -- moonkin form, don't change actionbar self:SetAttribute("action", self:GetAttribute("origaction")); else self:SetAttribute("action", self:GetAttribute("origaction")); end self:CallMethod("ActionChanged", oldslot); ]=]); RegisterStateDriver(secure, "possess", mainbartoggle); else function secure:ShowButton() if HasAction(slot) then activeButtons[slot] = self end end function secure:HideButton() activeButtons[slot] = nil end -- all other action bar are hidden if with overridebar or vehicleui (not shapeshift, possessbar) -- default Bartender4 options secure:SetAttribute("_onstate-possess", [=[ if newstate == "possess" then self:Hide(); self:CallMethod("HideButton"); else self:Show(); self:CallMethod("ShowButton"); end ]=]); RegisterStateDriver(secure, "possess", "[overridebar][vehicleui] possess; normal"); end end local function createActionBar(parent, config) local prev; local i = 0; local bar = CreateFrame("Frame", "OmaBTBar"..config.bar, parent, "SecureFrameTemplate"); bar:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y); bar:SetWidth(1); bar:SetHeight(1); if config.hidden then bar:Hide(); end for slot = config.start, config.start+config.length-1 do local secure = CreateFrame("CheckButton", "OmaBT"..slot, bar, inheritedFrames); secure.slot = slot; if slot == config.start then secure:SetPoint("TOPLEFT"); elseif config.columns and i % config.columns == 0 then secure:SetPoint("TOPLEFT", _G["OmaBT"..(slot-config.columns)], "BOTTOMLEFT"); else secure:SetPoint("TOPLEFT", prev, "TOPRIGHT"); end secure:RegisterForClicks("AnyUp"); if not BUTTONLOCK then secure:RegisterForDrag("LeftButton", "RightButton"); end if config.nomouse then secure:EnableMouse(false); else -- only show tooltips for bars with mouse interaction secure:SetScript("OnEnter", showTooltip); secure:SetScript("OnLeave", hideTooltip); end secure:SetWidth(config.size or 32); secure:SetHeight(config.size or 32); secure.base = secure:CreateTexture(nil, "BACKGROUND"); secure.base:SetAllPoints(); secure.base:SetColorTexture(0, 0, 0, 0.5); secure.iconbase = secure:CreateTexture(nil, "BORDER"); secure.iconbase:SetPoint("TOPLEFT", secure.base, "TOPLEFT", 1, -1); secure.iconbase:SetPoint("BOTTOMRIGHT", secure.base, "BOTTOMRIGHT", -1, 1); secure.iconbase:SetColorTexture(0, 0, 0, 0.5); secure.iconbase:Hide(); secure.icon = secure:CreateTexture(nil, "ARTWORK"); secure.icon:SetPoint("TOPLEFT", secure.iconbase, "TOPLEFT"); secure.icon:SetPoint("BOTTOMRIGHT", secure.iconbase, "BOTTOMRIGHT"); secure.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93); secure:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight"); secure.autocastable = secure:CreateTexture(nil, "OVERLAY"); secure.autocastable:SetPoint("CENTER"); secure.autocastable:SetWidth(58); secure.autocastable:SetHeight(58); secure.autocastable:SetTexture("Interface\\Buttons\\UI-AutoCastableOverlay"); secure.autocastable:Hide(); secure.glow = secure:CreateTexture(nil, "OVERLAY", nil, 1); secure.glow:SetPoint("CENTER"); secure.glow:SetWidth(config.size and config.size+26 or 53); secure.glow:SetHeight(config.size and config.size+26 or 53); secure.glow:SetTexture("Interface\\SpellActivationOverlay\\IconAlert"); secure.glow:SetTexCoord(0.00781250, 0.50781250, 0.27734375, 0.52634375); secure.glow:Hide(); secure.hotkey = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormalGray"); secure.hotkey:SetPoint("TOPRIGHT", secure, "TOPRIGHT", 2, -1); secure.count = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal"); secure.count:SetPoint("BOTTOMRIGHT", secure, "BOTTOMRIGHT", 2, -1); secure.text = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal"); secure.text:SetPoint("BOTTOMLEFT", secure, "BOTTOMLEFT", 2, -1); secure.text:Hide(); secure.cd = CreateFrame("Cooldown", "OmaBTCD"..slot, secure, "CooldownFrameTemplate"); secure.cd:SetAllPoints(); secure:SetAttribute("type", "action"); secure:SetAttribute("action", slot); if config.flyout then secure:SetAttribute("flyoutDirection", config.flyout); end function secure:ActionChanged(oldslot) if oldslot then activeButtons[oldslot] = nil; self.prev = nil; -- invalidate previous CD when slot changes end self.slot = self:GetAttribute("action"); return updateButton(self, self.slot); end secure:ActionChanged(); -- initial update setupSnippets(secure, slot); updateHotkeys(secure); buttons[slot] = secure; prev = secure; i = i + 1; end end local function initialize() local _, class = UnitClass("player"); local name, realm = UnitFullName("player"); ActionBars:SetFrameStrata("LOW"); ActionBars:SetPoint("BOTTOMLEFT"); ActionBars:SetWidth(1); ActionBars:SetHeight(1); for _, config in pairs(settings) do if (not usingBonusbars[class] or not usingBonusbars[class][config.bar]) and (not chars[realm] or not chars[realm][name] or chars[realm][name][config.bar]) then createActionBar(ActionBars, config); end end end local function setupBindings() _G["BINDING_HEADER_OmaAB"] = "Oma Action Bar"; for i = 1,10 do _G["BINDING_HEADER_OMAABBLANK"..i] = "Bar "..i; for j = 1,12 do _G[format("BINDING_NAME_CLICK OmaBT%d:LeftButton", (i-1)*12+j)] = format("Bar %d Button %d", i, j); end end end local mounted = false; local events = { ["ACTIONBAR_UPDATE_COOLDOWN"] = function() for _, button in pairs(activeButtons) do updateCooldown(button, button.slot); end end, ["SPELL_UPDATE_CHARGES"] = function() for _, button in pairs(activeButtons) do updateCount(button, button.slot); end end, ["ACTIONBAR_SLOT_CHANGED"] = function(slot) if buttons[slot] then buttons[slot]:ActionChanged() end end, ["ACTIONBAR_SHOWGRID"] = function() for _, button in pairs(buttons) do button.grid = true; button.iconbase:Show(); if not activeButtons[button.slot] then button.base:Show() end end end, ["ACTIONBAR_HIDEGRID"] = function() for _, button in pairs(buttons) do button.grid = nil; button.iconbase:Hide(); if not activeButtons[button.slot] then button.base:Hide() end end end, ["ACTIONBAR_UPDATE_STATE"] = function() for _, button in pairs(activeButtons) do updateState(button, button.slot); end end, ["ACTIONBAR_UPDATE_USABLE"] = function() for _, button in pairs(activeButtons) do updateUsable(button, button.slot); end end, ["UPDATE_OVERRIDE_ACTIONBAR"] = function() if buttons[1] then -- called before PLAYER_LOGIN for _, button in pairs(buttons) do updateButton(button, button.slot); end end end, ["START_AUTOREPEAT_SPELL"] = function() for _, button in pairs(activeButtons) do if IsAutoRepeatAction(button.slot) then button.autorepeating = true; button.icon:SetVertexColor(0, 1, 0.5); end end end, ["STOP_AUTOREPEAT_SPELL"] = function() for _, button in pairs(activeButtons) do if button.autorepeating then button.autorepeating = nil; updateUsable(button, button.slot); end end end, ["SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"] = function(spell) -- TODO create mapping from spellIDs to buttons for _, button in pairs(activeButtons) do startGlow(button, button.slot, spell); end end, ["SPELL_ACTIVATION_OVERLAY_GLOW_HIDE"] = function(spell) -- TODO create mapping from spellIDs to buttons for _, button in pairs(activeButtons) do stopGlow(button, button.slot, spell); end end, ["UPDATE_BINDINGS"] = function() for _, button in pairs(buttons) do updateHotkeys(button); end end, ["UNIT_AURA"] = function(unit) -- using UNIT_AURA instead of COMPANION_UPDATE to not update every time -- someone mounts, tracking player mount status with COMPANION_UPDATE is -- inconsistent if (not mounted and IsMounted()) or (mounted and not IsMounted()) then mounted = not mounted; for _, button in pairs(activeButtons) do updateState(button, button.slot); end end end, ["UPDATE_ALL_BUTTONS"] = function() for _, button in pairs(buttons) do updateButton(button, button.slot); end end, ["PLAYER_LOGIN"] = function() GameTooltip = _G["GameTooltip"]; initialize(); end, ["ADDON_LOADED"] = function(addon) if addon == "OmaAB" then setupBindings(); ActionBars:UnregisterEvent("ADDON_LOADED"); end end, }; events["LOSS_OF_CONTROL_ADDED"] = events["ACTIONBAR_UPDATE_COOLDOWN"]; events["LOSS_OF_CONTROL_UPDATE"] = events["ACTIONBAR_UPDATE_COOLDOWN"]; -- TODO might change once tooltips are in events["PLAYER_MOUNT_DISPLAY_CHANGED"] = events["ACTIONBAR_UPDATE_USABLE"]; events["TRADE_SKILL_SHOW"] = events["ACTIONBAR_UPDATE_STATE"]; events["TRADE_SKILL_CLOSE"] = events["ACTIONBAR_UPDATE_STATE"]; events["ARCHAEOLOGY_CLOSED"] = events["ACTIONBAR_UPDATE_STATE"]; events["PLAYER_ENTERING_WORLD"] = events["UPDATE_ALL_BUTTONS"]; events["UPDATE_VEHICLE_ACTIONBAR"] = events["UPDATE_ALL_BUTTONS"]; events["UPDATE_SHAPESHIFT_FORM"] = events["UPDATE_ALL_BUTTONS"]; events["SPELL_UPDATE_ICON"] = events["UPDATE_ALL_BUTTONS"]; events["PET_STABLE_UPDATE"] = events["UPDATE_ALL_BUTTONS"]; events["PET_STABLE_SHOW"] = events["UPDATE_ALL_BUTTONS"]; events["PLAYER_SPECIALIZATION_CHANGED"] = events["UPDATE_ALL_BUTTONS"]; events["UNIT_ENTERED_VEHICLE"] = function(unit) if unit == "player" then events["ACTIONBAR_UPDATE_STATE"]() end end events["UNIT_EXITED_VEHICLE"] = events["UNIT_ENTERED_VEHICLE"]; ActionBars:RegisterEvent("ADDON_LOADED"); ActionBars:RegisterEvent("PLAYER_LOGIN"); ActionBars:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN"); ActionBars:RegisterEvent("ACTIONBAR_UPDATE_USABLE"); ActionBars:RegisterEvent("ACTIONBAR_UPDATE_STATE"); ActionBars:RegisterEvent("ACTIONBAR_SLOT_CHANGED"); ActionBars:RegisterEvent("ACTIONBAR_SHOWGRID"); ActionBars:RegisterEvent("ACTIONBAR_HIDEGRID"); ActionBars:RegisterEvent("SPELL_UPDATE_ICON"); ActionBars:RegisterEvent("SPELL_UPDATE_CHARGES"); ActionBars:RegisterEvent("SPELL_ACTIVATION_OVERLAY_GLOW_SHOW"); ActionBars:RegisterEvent("SPELL_ACTIVATION_OVERLAY_GLOW_HIDE"); ActionBars:RegisterEvent("UPDATE_VEHICLE_ACTIONBAR"); ActionBars:RegisterEvent("UPDATE_OVERRIDE_ACTIONBAR"); ActionBars:RegisterEvent("PLAYER_MOUNT_DISPLAY_CHANGED"); ActionBars:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED"); ActionBars:RegisterEvent("UNIT_ENTERED_VEHICLE"); ActionBars:RegisterEvent("UNIT_EXITED_VEHICLE"); ActionBars:RegisterEvent("PET_STABLE_UPDATE"); ActionBars:RegisterEvent("PET_STABLE_SHOW"); ActionBars:RegisterEvent("UPDATE_BINDINGS"); ActionBars:RegisterUnitEvent("UNIT_AURA", "player"); ActionBars:SetScript("OnEvent", function(self, event, arg1) events[event](arg1); end);