From 1abeafcec2f7dca9f11fad181a265094bf1a09c4 Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Mon, 2 Nov 2026 19:25:16 -0600 Subject: [PATCH] Action bars: range and usable state from ClassicAPI events, drop the range ticker Shown buttons on bars 1-10 enable C_ActionBar.EnableActionRangeCheck for their slot and take ACTION_RANGE_CHECK_UPDATE; hiding a bar or paging releases the old slot. ACTION_USABLE_CHANGED refreshes only the changed slots; ACTIONBAR_UPDATE_USABLE is left to the stance buttons. Requires ClassicAPI v1.19.1. --- API_Check.lua | 2 +- modules/actionbar.lua | 134 ++++++++++++++++++++++++------------------ 2 files changed, 79 insertions(+), 57 deletions(-) diff --git a/API_Check.lua b/API_Check.lua index 8af2c0b7..d6c4ace9 100644 --- a/API_Check.lua +++ b/API_Check.lua @@ -13,7 +13,7 @@ do -- on. There pfUI does load, and will throw wherever it reaches for something -- the installed DLL doesn't have yet -- the popup names the cause so those -- errors aren't a mystery. - local PFUI_CLASSIC_API_MIN = 11900 -- (X*10000 + Y*100 + Z) + local PFUI_CLASSIC_API_MIN = 11901 -- (X*10000 + Y*100 + Z) local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI" local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest" diff --git a/modules/actionbar.lua b/modules/actionbar.lua index 45b23a8c..2784d249 100644 --- a/modules/actionbar.lua +++ b/modules/actionbar.lua @@ -90,7 +90,9 @@ pfUI:RegisterModule("actionbar", function () -- Page changes only touch the main bar, whose pager handles them. local pass_events = { ["ACTIONBAR_UPDATE_COOLDOWN"] = "cooldown", - ["ACTIONBAR_UPDATE_USABLE"] = "usable", + -- action slots take ACTION_USABLE_CHANGED; the stance buttons still + -- need a pass on this one + ["ACTIONBAR_UPDATE_USABLE"] = "stance", ["ACTIONBAR_UPDATE_STATE"] = "state", -- the active border of attack, auto repeat and tradeskill actions ["PLAYER_ENTER_COMBAT"] = "state", @@ -530,19 +532,18 @@ pfUI:RegisterModule("actionbar", function () end end - local function ButtonRangeUpdate(self) - self = self or this + -- Keeps the range check of the slot a shown action button displays + -- enabled, so ACTION_RANGE_CHECK_UPDATE reports it. Each button holds its + -- own enable, as the client counts them per slot. An enable fires the + -- event with the current state, so a new slot starts in range until then. + local function ButtonRangeWatch(button) + local slot = C.bars.glowrange == "1" and button.bar <= 10 and button:IsVisible() and button.id or nil + if slot == button.rangeslot then return end - -- update range display - if C.bars.glowrange == "1" and self.bar ~= 11 and self.bar ~= 12 and HasAction(self.id) and ActionHasRange(self.id) and IsActionInRange(self.id) == 0 then - if not self.outofrange then - self.outofrange = true - ButtonUsableUpdate(self) - end - elseif self.outofrange then - self.outofrange = nil - ButtonUsableUpdate(self) - end + if button.rangeslot then C_ActionBar.EnableActionRangeCheck(button.rangeslot, false) end + if slot then C_ActionBar.EnableActionRangeCheck(slot, true) end + button.rangeslot = slot + button.outofrange = nil end local start, duration, enable @@ -584,7 +585,6 @@ pfUI:RegisterModule("actionbar", function () if not button then return end ButtonSlotUpdate(button) - ButtonRangeUpdate(button) ButtonUsableUpdate(button) ButtonCooldownUpdate(button) end @@ -595,16 +595,35 @@ pfUI:RegisterModule("actionbar", function () -- Updates wait for the next frame, so the events of one frame share one -- pass. Passes and full updates skip hidden bars, which catch up as they - -- show (BarShow). The shown buttons of a bar are its first `count` ones. + -- show (BarShowHide). The shown buttons of a bar are its first `count` ones. local scheduled + + -- calls func on the buttons that show a slot: its own button and the main + -- bar button paged to it + local function ForSlotButtons(slot, func, a1) + local button = buttoncache[slot] + if button then func(button, a1) end + + local page = bars[1][1].id - 1 + local paged = slot > page and slot <= page + 12 and bars[1][slot - page] + if paged and paged ~= button then func(paged, a1) end + end + + -- the range watch follows hidden buttons too, so a hidden bar lets go of + -- its slots + local function SlotButtonUpdate(button) + ButtonRangeWatch(button) + if button:IsVisible() then pfUI.bars.ButtonFullUpdate(button) end + end + local function Flush() scheduled = nil - local inventory, cooldown, usable, state = passcache.inventory, passcache.cooldown, passcache.usable, passcache.state - local bindings = passcache.bindings + local inventory, cooldown, state = passcache.inventory, passcache.cooldown, passcache.state + local stance, bindings = passcache.stance, passcache.bindings table.wipe(passcache) - if inventory or cooldown or usable or state then + if inventory or cooldown or state then for i = 1, 12 do local bar = bars[i] if bar:IsVisible() then @@ -612,13 +631,19 @@ pfUI:RegisterModule("actionbar", function () local button = bar[j] if inventory then ButtonInventoryUpdate(button) end if inventory or cooldown then ButtonCooldownUpdate(button) end - if inventory or usable then ButtonUsableUpdate(button) end + if inventory then ButtonUsableUpdate(button) end if state then ButtonIsActiveUpdate(button) end end end end end + if stance and not inventory and bars[11]:IsVisible() then + for j = 1, bars[11].count do + ButtonUsableUpdate(bars[11][j]) + end + end + -- the keybinds of hidden buttons as well, as they don't catch up on them if bindings then for _, button in pairs(buttoncache) do @@ -627,20 +652,9 @@ pfUI:RegisterModule("actionbar", function () end end - -- a slot refreshes its own button and the main bar button paged to it - local page = bars[1][1].id - 1 for slot in pairs(updatecache) do updatecache[slot] = nil - - local button = buttoncache[slot] - if button and button:IsVisible() then - pfUI.bars.ButtonFullUpdate(button) - end - - local paged = slot > page and slot <= page + 12 and bars[1][slot - page] - if paged and paged ~= button and paged:IsVisible() then - pfUI.bars.ButtonFullUpdate(paged) - end + ForSlotButtons(slot, SlotButtonUpdate) end end @@ -662,28 +676,40 @@ pfUI:RegisterModule("actionbar", function () Schedule() end - -- ClassicAPI has no range event for action slots yet, so the visible - -- buttons are polled at the rate of the stock bars - local function RangeUpdate() - for i = 1, 10 do - local bar = bars[i] - if bar:IsVisible() then - for j = 1, bar.count do - ButtonRangeUpdate(bar[j]) - end - end - end - end - - -- passes skip hidden bars, so a bar refreshes its buttons as it shows - local function BarShow() + -- passes skip hidden bars, so a bar refreshes its buttons as it shows; + -- as it hides, its buttons let go of their range checks + local function BarShowHide() local offset = (this:GetID() - 1) * 12 for j = 1, this.count do QueueSlot(offset + j) end end + local function ButtonRangeEvent(button, outofrange) + if button.rangeslot ~= arg1 or button.outofrange == outofrange then return end + button.outofrange = outofrange + ButtonUsableUpdate(button) + end + + local function ButtonUsableEvent(button) + if button:IsVisible() then ButtonUsableUpdate(button) end + end + local function BarsEvent() + -- slot, isInRange, checksRange of a slot a button watches + if event == "ACTION_RANGE_CHECK_UPDATE" then + ForSlotButtons(arg1, ButtonRangeEvent, arg3 and not arg2 or nil) + return + end + + -- the slots whose usable state changed + if event == "ACTION_USABLE_CHANGED" then + for _, change in ipairs(arg1) do + ForSlotButtons(change.slot, ButtonUsableEvent) + end + return + end + -- refresh only specific slots if event == "ACTIONBAR_SLOT_CHANGED" and arg1 and arg1 ~= 0 then QueueSlot(arg1) @@ -742,6 +768,8 @@ pfUI:RegisterModule("actionbar", function () for event in pairs(global_events) do RegisterBarEvent(event) end for event in pairs(aura_events) do RegisterBarEvent(event) end for event in pairs(pet_events) do RegisterBarEvent(event) end + bars:RegisterEvent("ACTION_RANGE_CHECK_UPDATE") + bars:RegisterEvent("ACTION_USABLE_CHANGED") -- refresh actionbar buttons on event bars:SetScript("OnEvent", BarsEvent) @@ -1175,7 +1203,10 @@ pfUI:RegisterModule("actionbar", function () bars[i] = bars[i] or CreateFrame("Frame", "pfActionBar" .. barnames[i], UIParent) bars[i]:SetID(i) bars[i].count = buttons - if init then bars[i]:SetScript("OnShow", BarShow) end + if init then + bars[i]:SetScript("OnShow", BarShowHide) + if i <= 10 then bars[i]:SetScript("OnHide", BarShowHide) end + end -- autohide if autohide == "1" then @@ -1389,19 +1420,10 @@ pfUI:RegisterModule("actionbar", function () end end - local rangeticker pfUI.bars.UpdateConfig = function(self) for i=1,12 do CreateActionBar(i) end - - -- poll range only while it is shown - if C.bars.glowrange == "1" and not rangeticker then - rangeticker = C_Timer.NewTicker(.2, RangeUpdate) - elseif C.bars.glowrange ~= "1" and rangeticker then - rangeticker:Cancel() - rangeticker = nil - end end pfUI.bars:UpdateConfig()