CURRENT_ACTIONBAR_PAGE = 1;
NUM_ACTIONBAR_PAGES = 6;
NUM_ACTIONBAR_BUTTONS = 12;
ATTACK_BUTTON_FLASH_TIME = 0.4;
BOTTOMLEFT_ACTIONBAR_PAGE = 6;
BOTTOMRIGHT_ACTIONBAR_PAGE = 5;
LEFT_ACTIONBAR_PAGE = 4;
RIGHT_ACTIONBAR_PAGE = 3;
RANGE_INDICATOR = "●";
-- Table of actionbar pages and whether they're viewable or not
VIEWABLE_ACTION_BAR_PAGES = {1, 1, 1, 1, 1, 1};
function ActionButtonDown(id)
local button;
if ( BonusActionBarFrame:IsShown() ) then
button = getglobal("BonusActionButton"..id);
else
button = getglobal("ActionButton"..id);
end
if ( button:GetButtonState() == "NORMAL" ) then
button:SetButtonState("PUSHED");
end
end
function ActionButtonUp(id)
local button;
if ( BonusActionBarFrame:IsShown() ) then
button = getglobal("BonusActionButton"..id);
else
button = getglobal("ActionButton"..id);
end
if ( button:GetButtonState() == "PUSHED" ) then
button:SetButtonState("NORMAL");
SecureActionButton_OnClick(button, "LeftButton");
ActionButton_UpdateState(button);
end
end
function ActionBar_PageUp()
local nextPage;
for i=GetActionBarPage() + 1, NUM_ACTIONBAR_PAGES do
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
nextPage = i;
break;
end
end
if ( not nextPage ) then
nextPage = 1;
end
ChangeActionBarPage(nextPage);
end
function ActionBar_PageDown()
local prevPage;
for i=GetActionBarPage() - 1, 1, -1 do
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
prevPage = i;
break;
end
end
if ( not prevPage ) then
for i=NUM_ACTIONBAR_PAGES, 1, -1 do
if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
prevPage = i;
break;
end
end
end
ChangeActionBarPage(prevPage);
end
function ActionButton_OnLoad (self)
self.flashing = 0;
self.flashtime = 0;
self:SetAttribute("showgrid", 0);
self:SetAttribute("type", "action");
self:SetAttribute("checkselfcast", true);
self:SetAttribute("useparent-unit", true);
self:SetAttribute("useparent-actionpage", true);
self:RegisterForDrag("LeftButton", "RightButton");
self:RegisterForClicks("AnyUp");
self:RegisterEvent("PLAYER_ENTERING_WORLD");
self:RegisterEvent("ACTIONBAR_SHOWGRID");
self:RegisterEvent("ACTIONBAR_HIDEGRID");
self:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
self:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
self:RegisterEvent("UPDATE_BINDINGS");
ActionButton_UpdateAction(self);
ActionButton_UpdateHotkeys(self, self.buttonType);
end
function ActionButton_UpdateHotkeys (self, actionButtonType)
if ( not actionButtonType ) then
actionButtonType = "ACTIONBUTTON";
end
local hotkey = getglobal(self:GetName().."HotKey");
local key = GetBindingKey(actionButtonType..self:GetID()) or
GetBindingKey("CLICK "..self:GetName()..":LeftButton");
local text = GetBindingText(key, "KEY_", 1);
if ( text == "" ) then
hotkey:SetText(RANGE_INDICATOR);
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", 1, -2);
hotkey:Hide();
else
hotkey:SetText(text);
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", -2, -2);
hotkey:Show();
end
end
function ActionButton_CalculateAction (self, button)
if ( not button ) then
button = SecureButton_GetEffectiveButton(self);
end
if ( self:GetID() > 0 ) then
local page = SecureButton_GetModifiedAttribute(self, "actionpage", button);
if ( not page ) then
page = GetActionBarPage();
if ( self.isBonus and page == 1 ) then
local offset = GetBonusBarOffset();
if ( offset == 0 and BonusActionBarFrame and BonusActionBarFrame.lastBonusBar ) then
offset = BonusActionBarFrame.lastBonusBar;
end
page = NUM_ACTIONBAR_PAGES + offset;
end
end
return (self:GetID() + ((page - 1) * NUM_ACTIONBAR_BUTTONS));
else
return SecureButton_GetModifiedAttribute(self, "action", button) or 1;
end
end
function ActionButton_UpdateAction (self)
local action = ActionButton_CalculateAction(self);
if ( action ~= self.action ) then
self.action = action;
ActionButton_Update(self);
end
end
function ActionButton_Update (self)
-- Special case code for bonus bar buttons
-- Prevents the button from updating if the bonusbar is still in an animation transition
if ( self.isBonus and self.inTransition ) then
self.needsUpdate = true;
ActionButton_UpdateUsable(self);
return;
end
local name = self:GetName();
local action = self.action;
local icon = getglobal(name.."Icon");
local buttonCooldown = getglobal(name.."Cooldown");
local texture = GetActionTexture(action);
if ( HasAction(action) ) then
if ( not self.eventsRegistered ) then
self:RegisterEvent("ACTIONBAR_UPDATE_STATE");
self:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
self:RegisterEvent("UPDATE_INVENTORY_ALERTS");
self:RegisterEvent("PLAYER_TARGET_CHANGED");
self:RegisterEvent("TRADE_SKILL_SHOW");
self:RegisterEvent("TRADE_SKILL_CLOSE");
self:RegisterEvent("PLAYER_ENTER_COMBAT");
self:RegisterEvent("PLAYER_LEAVE_COMBAT");
self:RegisterEvent("START_AUTOREPEAT_SPELL");
self:RegisterEvent("STOP_AUTOREPEAT_SPELL");
self.eventsRegistered = true;
end
if ( not self:GetAttribute("statehidden") ) then
self:Show();
end
ActionButton_UpdateState(self);
ActionButton_UpdateUsable(self);
ActionButton_UpdateCooldown(self);
ActionButton_UpdateFlash(self);
else
if ( self.eventsRegistered ) then
self:UnregisterEvent("ACTIONBAR_UPDATE_STATE");
self:UnregisterEvent("ACTIONBAR_UPDATE_USABLE");
self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
self:UnregisterEvent("UPDATE_INVENTORY_ALERTS");
self:UnregisterEvent("PLAYER_TARGET_CHANGED");
self:UnregisterEvent("TRADE_SKILL_SHOW");
self:UnregisterEvent("TRADE_SKILL_CLOSE");
self:UnregisterEvent("PLAYER_ENTER_COMBAT");
self:UnregisterEvent("PLAYER_LEAVE_COMBAT");
self:UnregisterEvent("START_AUTOREPEAT_SPELL");
self:UnregisterEvent("STOP_AUTOREPEAT_SPELL");
self.eventsRegistered = nil;
end
if ( self:GetAttribute("showgrid") == 0 ) then
self:Hide();
else
buttonCooldown:Hide();
end
end
-- Add a green border if button is an equipped item
local border = getglobal(name.."Border");
if ( IsEquippedAction(action) ) then
border:SetVertexColor(0, 1.0, 0, 0.35);
border:Show();
else
border:Hide();
end
-- Update Macro Text
local macroName = getglobal(name.."Name");
if ( not IsConsumableAction(action) and not IsStackableAction(action) ) then
macroName:SetText(GetActionText(action));
else
macroName:SetText("");
end
-- Update icon and hotkey text
if ( texture ) then
icon:SetTexture(texture);
icon:Show();
self.rangeTimer = -1;
self:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
else
icon:Hide();
buttonCooldown:Hide();
self.rangeTimer = nil;
self:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
local hotkey = getglobal(name.."HotKey");
if ( hotkey:GetText() == RANGE_INDICATOR ) then
hotkey:Hide();
else
hotkey:SetVertexColor(0.6, 0.6, 0.6);
end
end
ActionButton_UpdateCount(self);
-- Update tooltip
if ( GameTooltip:GetOwner() == self ) then
ActionButton_SetTooltip(self);
end
self.feedback_action = action;
end
function ActionButton_ShowGrid (button)
assert(button);
if ( issecure() ) then
button:SetAttribute("showgrid", button:GetAttribute("showgrid") + 1);
end
getglobal(button:GetName().."NormalTexture"):SetVertexColor(1.0, 1.0, 1.0, 0.5);
if ( button:GetAttribute("showgrid") >= 1 and not button:GetAttribute("statehidden") ) then
button:Show();
end
end
function ActionButton_HideGrid (button)
assert(button);
local showgrid = button:GetAttribute("showgrid");
if ( issecure() ) then
if ( showgrid > 0 ) then
button:SetAttribute("showgrid", showgrid - 1);
end
end
if ( button:GetAttribute("showgrid") == 0 and not HasAction(button.action) ) then
button:Hide();
end
end
function ActionButton_UpdateState (button)
assert(button);
local action = button.action;
if ( IsCurrentAction(action) or IsAutoRepeatAction(action) ) then
button:SetChecked(1);
else
button:SetChecked(0);
end
end
function ActionButton_UpdateUsable (self)
local name = self:GetName();
local icon = getglobal(name.."Icon");
local normalTexture = getglobal(name.."NormalTexture");
local isUsable, notEnoughMana = IsUsableAction(self.action);
if ( isUsable ) then
icon:SetVertexColor(1.0, 1.0, 1.0);
normalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif ( notEnoughMana ) then
icon:SetVertexColor(0.5, 0.5, 1.0);
normalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
icon:SetVertexColor(0.4, 0.4, 0.4);
normalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end
function ActionButton_UpdateCount (self)
local text = getglobal(self:GetName().."Count");
local action = self.action;
if ( IsConsumableAction(action) or IsStackableAction(action) ) then
text:SetText(GetActionCount(action));
else
text:SetText("");
end
end
function ActionButton_UpdateCooldown (self)
local cooldown = getglobal(self:GetName().."Cooldown");
local start, duration, enable = GetActionCooldown(self.action);
CooldownFrame_SetTimer(cooldown, start, duration, enable);
end
function ActionButton_OnEvent (self, event, ...)
local arg1 = ...;
if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
if ( arg1 == 0 or arg1 == self.action ) then
ActionButton_Update(self);
end
return;
end
if ( event == "PLAYER_ENTERING_WORLD" ) then
ActionButton_Update(self);
return;
end
if ( event == "ACTIONBAR_PAGE_CHANGED" or event == "UPDATE_BONUS_ACTIONBAR" ) then
ActionButton_UpdateAction(self);
return;
end
if ( event == "ACTIONBAR_SHOWGRID" ) then
ActionButton_ShowGrid(self);
return;
end
if ( event == "ACTIONBAR_HIDEGRID" ) then
ActionButton_HideGrid(self);
return;
end
if ( event == "UPDATE_BINDINGS" ) then
ActionButton_UpdateHotkeys(self, self.buttonType);
return;
end
-- All event handlers below this line are only set when the button has an action
if ( event == "PLAYER_TARGET_CHANGED" ) then
self.rangeTimer = -1;
elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
ActionButton_UpdateState(self);
elseif ( event == "ACTIONBAR_UPDATE_USABLE" ) then
ActionButton_UpdateUsable(self);
elseif ( event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
ActionButton_UpdateCooldown(self);
elseif ( event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_CLOSE" ) then
ActionButton_UpdateState(self);
elseif ( event == "PLAYER_ENTER_COMBAT" ) then
if ( IsAttackAction(self.action) ) then
ActionButton_StartFlash(self);
end
elseif ( event == "PLAYER_LEAVE_COMBAT" ) then
if ( IsAttackAction(self.action) ) then
ActionButton_StopFlash(self);
end
elseif ( event == "START_AUTOREPEAT_SPELL" ) then
if ( IsAutoRepeatAction(self.action) ) then
ActionButton_StartFlash(self);
end
elseif ( event == "STOP_AUTOREPEAT_SPELL" ) then
if ( ActionButton_IsFlashing(self) and not IsAttackAction(self.action) ) then
ActionButton_StopFlash(self);
end
end
end
function ActionButton_SetTooltip (self)
if ( GetCVar("UberTooltips") == "1" ) then
GameTooltip_SetDefaultAnchor(GameTooltip, self);
else
local parent = self:GetParent();
if ( parent == MultiBarBottomRight or parent == MultiBarRight or parent == MultiBarLeft ) then
GameTooltip:SetOwner(self, "ANCHOR_LEFT");
else
GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
end
end
if ( GameTooltip:SetAction(self.action) ) then
self.UpdateTooltip = ActionButton_SetTooltip;
else
self.UpdateTooltip = nil;
end
end
function ActionButton_OnUpdate (self, elapsed)
if ( ActionButton_IsFlashing(self) ) then
local flashtime = self.flashtime;
flashtime = flashtime - elapsed;
if ( flashtime <= 0 ) then
local overtime = -flashtime;
if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
overtime = 0;
end
flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;
local flashTexture = getglobal(self:GetName().."Flash");
if ( flashTexture:IsShown() ) then
flashTexture:Hide();
else
flashTexture:Show();
end
end
self.flashtime = flashtime;
end
-- Handle range indicator
local rangeTimer = self.rangeTimer;
if ( rangeTimer ) then
rangeTimer = rangeTimer - elapsed;
if ( rangeTimer <= 0 ) then
local count = getglobal(self:GetName().."HotKey");
local valid = IsActionInRange(self.action);
if ( count:GetText() == RANGE_INDICATOR ) then
if ( valid == 0 ) then
count:Show();
count:SetVertexColor(1.0, 0.1, 0.1);
elseif ( valid == 1 ) then
count:Show();
count:SetVertexColor(0.6, 0.6, 0.6);
else
count:Hide();
end
else
if ( valid == 0 ) then
count:SetVertexColor(1.0, 0.1, 0.1);
else
count:SetVertexColor(0.6, 0.6, 0.6);
end
end
rangeTimer = TOOLTIP_UPDATE_TIME;
end
self.rangeTimer = rangeTimer;
end
end
function ActionButton_GetPagedID (self)
return self.action;
end
function ActionButton_UpdateFlash (self)
local action = self.action;
if ( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) ) then
ActionButton_StartFlash(self);
else
ActionButton_StopFlash(self);
end
end
function ActionButton_StartFlash (self)
self.flashing = 1;
self.flashtime = 0;
ActionButton_UpdateState(self);
end
function ActionButton_StopFlash (self)
self.flashing = 0;
getglobal(self:GetName().."Flash"):Hide();
ActionButton_UpdateState (self);
end
function ActionButton_IsFlashing (self)
if ( self.flashing == 1 ) then
return 1;
end
return nil;
end