From a3f38502c2d6574aa270b22ec78d8525443ad582 Mon Sep 17 00:00:00 2001 From: Meow <30401521+me0wg4ming@users.noreply.github.com> Date: Mon, 9 Mar 2026 02:44:52 +0100 Subject: [PATCH] hunter bar auto swap fix (works for ALL levels) --- modules/hunterbar.lua | 96 ++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/modules/hunterbar.lua b/modules/hunterbar.lua index af9b99ae..b6de6e24 100644 --- a/modules/hunterbar.lua +++ b/modules/hunterbar.lua @@ -2,60 +2,72 @@ pfUI:RegisterModule("hunterbar", "vanilla", function () local _,class = UnitClass("player") if class ~= "HUNTER" or C.bars.hunterbar == "0" then return end + -- Wing Clip (any rank) and Arcane Shot (any rank) spell IDs. + -- IsSpellInRange(spellId) works with any spell ID via Nampower, + -- no actionbar slot needed. + local WINGCLIP_ID = 2974 -- melee range indicator (~5 yd) + local ARCANESHOT_ID = 3044 -- ranged range indicator (~35 yd) + + -- Hysteresis: only swap TO ranged bar when Arcane Shot is actually in range. + -- Only swap BACK to melee bar when Wing Clip is actually in range. + -- This prevents rapid bar-flipping in the transition zone. + pfUI.hunterbar = CreateFrame("Frame", "pfHunterBar", UIParent) - local scanner = libtipscan:GetScanner("hunterbar") - pfUI.hunterbar.melee = nil - pfUI.hunterbar.ranged = nil - pfUI.hunterbar.current = 1 - - pfUI.hunterbar:RegisterEvent("ACTIONBAR_SLOT_CHANGED") - pfUI.hunterbar:RegisterEvent("PLAYER_ENTERING_WORLD") - pfUI.hunterbar:SetScript("OnEvent", function() - if event == "PLAYER_ENTERING_WORLD" then - this.event = GetTime() + 3 - elseif this.event and this.event < GetTime() + .2 then - this.event = GetTime() + .1 - end - end) + -- track which page we last forced so we don't spam ChangeActionBarPage() + pfUI.hunterbar.lastPage = nil pfUI.hunterbar:SetScript("OnUpdate", function() - -- we got an event 0.1s ago, scanning for new Skills - if this.event and this.event <= GetTime() then - this.event = nil - this.melee = nil - this.ranged = nil + -- only act when there is a live, attackable target + if not UnitExists("target") or not UnitCanAttack("player", "target") then + return + end - for i=1,120 do - if this.melee and this.ranged then return end + local onMeleeBar = (_G.CURRENT_ACTIONBAR_PAGE == 1) + local onRangedBar = (_G.CURRENT_ACTIONBAR_PAGE == 9) - scanner:SetAction(i) + -- IsSpellInRange returns: 1 = in range, 0 = out of range, -1 = not applicable + -- IsSpellUsable returns: usable(0/1), outOfMana(0/1) + -- We only swap when the *destination* condition is fully confirmed. - local left = scanner:Line(1) - if left then - if left == L["hunterpaging"]["MELEE"] then - this.melee = i - elseif left == L["hunterpaging"]["RANGED"] then - this.ranged = i - end + if onMeleeBar then + -- Currently on melee bar → switch to ranged bar only when: + -- • Wing Clip is OUT of range (we are far enough away) + -- • Arcane Shot IS in range (ranged attack would actually land) + -- • Arcane Shot is usable (not dead / phase / etc.) + local wingclipInRange = IsSpellInRange(WINGCLIP_ID, "target") + local arcaneshotInRange = IsSpellInRange(ARCANESHOT_ID, "target") + local arcaneshotUsable = IsSpellUsable(ARCANESHOT_ID) + + if wingclipInRange == 0 and arcaneshotInRange == 1 and arcaneshotUsable == 1 then + if this.lastPage ~= 9 then + this.lastPage = 9 + _G.CURRENT_ACTIONBAR_PAGE = 9 + ChangeActionBarPage() end end - end - -- skip further code when no abilities were found - if not this.melee or not this.ranged then return end + elseif onRangedBar then + -- Currently on ranged bar → switch back to melee bar only when: + -- • Wing Clip IS in range (we are close enough to melee) + -- • Wing Clip is usable (not dead / phase / etc.) + -- • Arcane Shot is OUT of range (fully in melee – belt-and-suspenders) + local wingclipInRange = IsSpellInRange(WINGCLIP_ID, "target") + local wingclipUsable = IsSpellUsable(WINGCLIP_ID) + local arcaneshotInRange = IsSpellInRange(ARCANESHOT_ID, "target") - -- do the actual rangedetection and barswapping - if IsActionInRange(this.melee) == 1 and IsActionInRange(this.ranged) == 0 then - if _G.CURRENT_ACTIONBAR_PAGE == 1 then - _G.CURRENT_ACTIONBAR_PAGE = 9 - ChangeActionBarPage() + if wingclipInRange == 1 and wingclipUsable == 1 and arcaneshotInRange == 0 then + if this.lastPage ~= 1 then + this.lastPage = 1 + _G.CURRENT_ACTIONBAR_PAGE = 1 + ChangeActionBarPage() + end end + else - if _G.CURRENT_ACTIONBAR_PAGE == 9 then - _G.CURRENT_ACTIONBAR_PAGE = 1 - ChangeActionBarPage() - end + -- Player manually switched to a different page → stop tracking + -- until they return to page 1 or 9. + this.lastPage = nil end end) -end) +end) \ No newline at end of file