Files
coa-bartender/ActionButton.lua
T
florian.berthold 57a5cdabdf ascension: 4.4.2 → vendored 4.4.2-2-g3b02ee4 (in-game AddOns dir)
Imported from /srv/add01/wow-ascension/Interface/AddOns/Bartender4 — the
build Ascension's WotLK 3.3.5 client ships.

Single vendored drop: Ascension's build process bundles their custom
patches with the standard CurseForge packager output (embedded libs),
and the individual patches aren't published separately.

Net delta vs Nevcairiel 4.4.2, excluding bundled libs and CRLF
normalization: 21 files, 2213+/52- — the Ascension-specific
adaptations for WotLK 3.3.5 hero classes / custom action systems.

License: All rights reserved (per .toc).
2026-05-08 03:45:58 +02:00

516 lines
14 KiB
Lua

--[[
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
All rights reserved.
]]
--[[
Action Button Template
Note:
Some IDs produce a special behaviour!
- Button ID 132 (Last Button in Possess Bar) Creates a Leave Vehicle Button
]]
local specialButtons = {
[132] = { icon = "Interface\\Icons\\Spell_Shadow_SacrificialShield", tooltip = LEAVE_VEHICLE}, -- Vehicle Leave Button
}
local Button = CreateFrame("CheckButton")
local Button_MT = {__index = Button}
local onEnter, onLeave, onUpdate, onDragUpdate
-- upvalues
local _G = _G
local format = string.format
local IsUsableAction, IsActionInRange, GetActionTexture, ActionHasRange = IsUsableAction, IsActionInRange, GetActionTexture, ActionHasRange
local ATTACK_BUTTON_FLASH_TIME, RANGE_INDICATOR, TOOLTIP_UPDATE_TIME = ATTACK_BUTTON_FLASH_TIME, RANGE_INDICATOR, TOOLTIP_UPDATE_TIME
local Bartender4 = Bartender4
local LBF = LibStub("LibButtonFacade", true)
local KeyBound = LibStub("LibKeyBound-1.0")
Bartender4.Button = {}
Bartender4.Button.prototype = Button
Button.BT4init = true
function Bartender4.Button:Create(id, parent)
local absid = (parent.id - 1) * 12 + id
local name = ("BT4Button%d"):format(absid)
local button = setmetatable(CreateFrame("CheckButton", name, parent, "ActionBarButtonTemplate"), Button_MT)
-- work around for "blocked" message when using /click macros
GetClickFrame(name)
-- Backwards Compat to pre-4.2.0 button names/layout
_G[name .. "Secure"] = button
button.Secure = button
button.rid = id
button.id = absid
button.parent = parent
button.stateactions = {}
button:SetRealNormalTexture("")
local oldNT = _G[("%sNormalTexture"):format(name)]
oldNT:Hide()
button.normalTexture = button:CreateTexture(("%sBTNT"):format(name))
button.normalTexture:SetWidth(66)
button.normalTexture:SetHeight(66)
button.normalTexture:ClearAllPoints()
button.normalTexture:SetPoint("CENTER", 0, -1)
button.normalTexture:Show()
--button:SetFrameStrata("MEDIUM")
-- overwrite some scripts with out customized versions
button:SetScript("OnEnter", onEnter)
button:SetScript("OnUpdate", onUpdate)
button:SetScript("OnDragStart", onDragUpdate)
--button:SetScript("OnReceiveDrag", nil)
button.icon = _G[("%sIcon"):format(name)]
button.border = _G[("%sBorder"):format(name)]
button.cooldown = _G[("%sCooldown"):format(name)]
button.macroName = _G[("%sName"):format(name)]
button.hotkey = _G[("%sHotKey"):format(name)]
button.count = _G[("%sCount"):format(name)]
button.flash = _G[("%sFlash"):format(name)]
button.flash:Hide()
button:SetAttribute("type", "action")
button:SetAttribute("action", absid)
button:SetAttribute("useparent-unit", nil);
button:SetAttribute("useparent-actionpage", nil);
button:SetAttribute("buttonlock", Bartender4.db.profile.buttonlock)
button:UpdateSelfCast()
parent:WrapScript(button, "OnDragStart", [[
local action = self:GetAttribute("action")
if action and (not self:GetAttribute("buttonlock") or IsModifiedClick("PICKUPACTION")) then
return "action", action
end
]], [[
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
]])
parent:WrapScript(button, "OnReceiveDrag", [[]], [[
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
]])
button:SetAttribute("UpdateAutoAssist", [[
self:SetAttribute("assisttype", nil)
self:SetAttribute("unit", nil)
if self:GetAttribute("autoassist") then
local action = self:GetAttribute("action")
local type, id, subtype = GetActionInfo(action)
if type == "spell" and id > 0 then
if IsHelpfulSpell(id, subtype) then
self:SetAttribute("assisttype", 1)
self:SetAttribute("unit", G_assist_help)
elseif IsHarmfulSpell(id, subtype) then
self:SetAttribute("assisttype", 2)
self:SetAttribute("unit", G_assist_harm)
end
end
end
]])
button:SetAttribute('_childupdate-init', [[
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
]])
button:SetAttribute('_childupdate-state', [[
self:SetAttribute("state", message)
local action = self:GetAttribute("action-" .. message)
if not action then return end
if action == 132 then
self:SetAttribute("type", "click")
if not self:GetAttribute("isSpecial") then
self:SetAttribute("showgrid", self:GetAttribute("showgrid") + 1)
self:SetAttribute("isSpecial", true)
end
else
if action > 120 and action <= 126 then
self:SetAttribute("type", "click")
else
self:SetAttribute("type", "action")
end
if self:GetAttribute("isSpecial") then
self:SetAttribute("isSpecial", nil)
self:SetAttribute("showgrid", max(0, self:GetAttribute("showgrid") - 1))
end
end
self:SetAttribute("action", action)
-- fix unit on state change
if action <= 120 and self:GetAttribute("autoassist") then
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
else
self:SetAttribute("unit", nil)
end
G_state = message
]])
button:SetAttribute('_childupdate-assist-help', [[
G_assist_help = message
if self:GetAttribute("assisttype") == 1 then
self:SetAttribute("unit", message)
end
]])
button:SetAttribute('_childupdate-assist-harm', [[
G_assist_harm = message
if self:GetAttribute("assisttype") == 2 then
self:SetAttribute("unit", message)
end
]])
button.SecureInit = true
if LBF and parent.LBFGroup then
local group = parent.LBFGroup
group:AddButton(button)
end
if button.parent.config.showgrid then
button:ShowGrid()
end
--self:UpdateAction(true)
button:UpdateHotkeys()
button:UpdateUsable()
button:UpdateGrid()
button:ToggleButtonElements()
for page = 0,11,1 do
local action = (page == 0) and button.id or (button.rid + (page - 1) * 12)
button:SetStateAction(page, action)
end
return button
end
function onDragUpdate(self)
ActionButton_UpdateState(self)
ActionButton_UpdateFlash(self)
end
function onEnter(self)
if not (Bartender4.db.profile.tooltip == "nocombat" and InCombatLockdown()) and Bartender4.db.profile.tooltip ~= "disabled" then
self:SetTooltip(self)
end
KeyBound:Set(self)
end
function onUpdate(self, elapsed)
if self.flashing == 1 then
self.flashtime = self.flashtime - elapsed
if self.flashtime <= 0 then
local overtime = -self.flashtime
if overtime >= ATTACK_BUTTON_FLASH_TIME then
overtime = 0
end
self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
local flashTexture = self.flash
if flashTexture:IsShown() then
flashTexture:Hide()
else
flashTexture:Show()
end
end
end
if self.rangeTimer then
self.rangeTimer = self.rangeTimer - elapsed
if self.rangeTimer <= 0 then
local valid = IsActionInRange(self.action)
self.outOfRange = (valid == 0)
local oor = Bartender4.db.profile.outofrange
if oor == "hotkey" then
local hotkey = self.hotkey
local hkshown = hotkey:GetText() == RANGE_INDICATOR
if valid and hkshown then
hotkey:Show()
elseif hkshown then
hotkey:Hide()
end
if self.outOfRange then
local oorc = Bartender4.db.profile.colors.range
hotkey:SetVertexColor(oorc.r, oorc.g, oorc.b)
else
hotkey:SetVertexColor(1.0, 1.0, 1.0)
end
elseif oor == "button" then
self:UpdateUsable()
end
self.rangeTimer = TOOLTIP_UPDATE_TIME
end
end
end
Bartender4.Button.onUpdate = onUpdate
local function updateIcon(self)
if self.action then
if specialButtons[self.action] then
if not LBF then
self.normalTexture:SetTexCoord(0, 0, 0, 0)
end
self.icon:SetTexture(specialButtons[self.action].icon)
self.icon:Show()
self:UpdateUsable()
elseif not LBF then
if GetActionTexture(self.action) then
self.normalTexture:SetTexCoord(0, 0, 0, 0)
else
self.normalTexture:SetTexCoord(-0.15, 1.15, -0.15, 1.17)
end
end
end
end
local function updateFunc(self)
local parent = self:GetParent()
if not self.BT4init or not parent.BT4BarType then return end
self:UpdateRange()
updateIcon(self)
if self.SecureInit and not InCombatLockdown() then
local parent = self:GetParent()
parent:SetFrameRef("upd", self)
parent:Execute([[
local frame = self:GetFrameRef("upd")
control:RunFor(frame, frame:GetAttribute("UpdateAutoAssist"))
]])
end
end
hooksecurefunc("ActionButton_Update", updateFunc)
Button.SetRealNormalTexture = Button.SetNormalTexture
function Button:SetNormalTexture(...)
self.normalTexture:SetTexture(...)
end
Button.GetRealNormalTexture = Button.GetNormalTexture
function Button:GetNormalTexture()
return self.normalTexture
end
function Button:UpdateStates()
self:SetAttribute("autoassist", self.parent.config.autoassist)
end
function Button:SetStateAction(state, action)
self.stateactions[state] = action
self:RefreshStateAction(state)
end
function Button:RefreshStateAction(state)
local state = tonumber(state or self:GetAttribute("state")) or 0
local action = self.stateactions[state]
assert(action, ("No valid action for state %d on button %d of Bar %d"):format(state, self.rid, self.parent.id))
self:SetAttribute("action-"..state, action)
if action > 120 and action <= 126 then
self:SetAttribute("clickbutton", _G["VehicleMenuBarActionButton"..tostring(action-120)])
elseif action == 132 then
self:SetAttribute("clickbutton", PossessButton2)
end
end
function Button:UpdateSelfCast()
self:SetAttribute("checkmouseovercast", true)
self:SetAttribute("checkselfcast", Bartender4.db.profile.selfcastmodifier and true or nil)
self:SetAttribute("checkfocuscast", Bartender4.db.profile.focuscastmodifier and true or nil)
self:SetAttribute("unit2", Bartender4.db.profile.selfcastrightclick and "player" or nil)
end
function Button:GetActionID()
return self.action
end
function Button:Update()
self:UpdateAction(true)
self:UpdateHotkeys()
self:ToggleButtonElements()
self:UpdateRange()
end
function Button:UpdateAction(force)
ActionButton_UpdateAction(self)
end
function Button:ToggleButtonElements()
if self.parent.config.hidemacrotext then
self.macroName:Hide()
else
self.macroName:Show()
end
end
hooksecurefunc("ActionButton_UpdateHotkeys", function(self, ...)
local parent = self:GetParent()
if not self.BT4init or not parent.BT4BarType then return end
self:UpdateHotkeys()
end)
function Button:UpdateHotkeys()
local key = self:GetHotkey() or ""
local hotkey = self.hotkey
if key == "" or self.parent.config.hidehotkey then
hotkey:SetText(RANGE_INDICATOR)
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", 1, -2)
hotkey:Hide()
else
hotkey:SetText(key)
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", -2, -2)
hotkey:Show()
end
end
function Button:GetHotkey()
local key = ((self.id <= 12) and GetBindingKey(format("ACTIONBUTTON%d", self.id))) or GetBindingKey("CLICK "..self:GetName()..":LeftButton")
return key and KeyBound:ToShortKey(key)
end
function Button:GetBindings()
local keys, binding = ""
if self.id <= 12 then
binding = format("ACTIONBUTTON%d", self.id)
for i = 1, select('#', GetBindingKey(binding)) do
local hotKey = select(i, GetBindingKey(binding))
if keys ~= "" then
keys = keys .. ', '
end
keys = keys .. GetBindingText(hotKey,'KEY_')
end
end
binding = "CLICK "..self:GetName()..":LeftButton"
for i = 1, select('#', GetBindingKey(binding)) do
local hotKey = select(i, GetBindingKey(binding))
if keys ~= "" then
keys = keys .. ', '
end
keys = keys .. GetBindingText(hotKey,'KEY_')
end
return keys
end
function Button:SetKey(key)
if self.id <= 12 then
SetBinding(key, format("ACTIONBUTTON%d", self.id))
else
SetBindingClick(key, self:GetName(), 'LeftButton')
end
end
function Button:ClearBindings()
if self.id <= 12 then
local binding = format("ACTIONBUTTON%d", self.id)
while GetBindingKey(binding) do
SetBinding(GetBindingKey(binding), nil)
end
end
local binding = "CLICK "..self:GetName()..":LeftButton"
while GetBindingKey(binding) do
SetBinding(GetBindingKey(binding), nil)
end
end
local actionTmpl = "BT4 Bar %d Button %d"
function Button:GetActionName()
return format(actionTmpl, self.parent.id, self.rid)
end
hooksecurefunc("ActionButton_UpdateUsable", function(self)
if self.BT4init then
self:UpdateUsable()
end
end)
function Button:UpdateUsable()
local isUsable, notEnoughMana = IsUsableAction(self.action)
local icon = self.icon
if Bartender4.db.profile.outofrange == "button" and self.outOfRange then
local oorc = Bartender4.db.profile.colors.range
icon:SetVertexColor(oorc.r, oorc.g, oorc.b)
else
if isUsable or specialButtons[self.action] then
icon:SetVertexColor(1.0, 1.0, 1.0)
elseif notEnoughMana then
local oomc = Bartender4.db.profile.colors.mana
icon:SetVertexColor(oomc.r, oomc.g, oomc.b)
else
icon:SetVertexColor(0.4, 0.4, 0.4)
end
end
end
function Button:UpdateRange()
if Bartender4.db.profile.outofrange == "none" or not ActionHasRange(self.action) then
self.rangeTimer = nil
self.outOfRange = nil
end
self.hotkey:SetVertexColor(1.0, 1.0, 1.0)
self:UpdateUsable()
onUpdate(self, 10)
end
function Button:SetTooltip()
if ( GetCVar("UberTooltips") == "1" ) then
GameTooltip_SetDefaultAnchor(GameTooltip, self)
else
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
end
if specialButtons[self.action] then
GameTooltip:SetText(specialButtons[self.action].tooltip)
self.UpdateTooltip = self.SetTooltip
else
if ( GameTooltip:SetAction(self.action) ) then
self.UpdateTooltip = self.SetTooltip
else
self.UpdateTooltip = nil
end
end
end
function Button:UpdateGrid()
if self:GetAttribute("showgrid") > 0 then
ActionButton_ShowGrid(self)
else
ActionButton_HideGrid(self)
end
end
function Button:ShowGrid()
if not self.gridShown then
self.gridShown = true
self:SetAttribute("showgrid", self:GetAttribute("showgrid") + 1)
self:UpdateGrid()
end
end
function Button:HideGrid()
if self.gridShown then
self.gridShown = nil
self:SetAttribute("showgrid", max(0, self:GetAttribute("showgrid") - 1))
self:UpdateGrid()
end
end
function Button:ClearSetPoint(...)
self:ClearAllPoints()
self:SetPoint(...)
end