From 6a670ab66809afb51999f0be6cb0666414416b35 Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Fri, 30 Oct 2026 23:31:29 -0500 Subject: [PATCH] Tint swing timer bars while the target is out of range C_SwingTimer checks the range for each shown bar, and PLAYER_SWING_RANGE_UPDATE turns a bar the new Out Of Range Color (grey by default, since the main-hand bar and the hunter dead zone are red) while its swing can't reach the current target. The melee check is the server's 2D reach; the ranged one covers the hunter's minimum range too. No check (no target, nothing to attack, no weapon) keeps the normal color. --- api/config.lua | 1 + modules/gui.lua | 1 + modules/swingtimer.lua | 44 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/api/config.lua b/api/config.lua index bb9c1e8b..2c85f77d 100644 --- a/api/config.lua +++ b/api/config.lua @@ -253,6 +253,7 @@ function pfUI:LoadConfig() pfUI:UpdateConfig("unitframes", nil, "swingtimerohcolor",".3,.8,.3,1") pfUI:UpdateConfig("unitframes", nil, "swingtimerrangedcolor",".3,.6,1,1") pfUI:UpdateConfig("unitframes", nil, "swingtimerrangedwarncolor",".9,0,0,1") + pfUI:UpdateConfig("unitframes", nil, "swingtimeroutrangecolor",".5,.5,.5,1") pfUI:UpdateConfig("unitframes", nil, "swingtimerhsqueue","1") pfUI:UpdateConfig("unitframes", nil, "swingtimerattackspeed","0") pfUI:UpdateConfig("unitframes", nil, "raidmarkerwidth", "80") diff --git a/modules/gui.lua b/modules/gui.lua index ab2693ff..e3048998 100644 --- a/modules/gui.lua +++ b/modules/gui.lua @@ -2073,6 +2073,7 @@ pfUI:RegisterModule("gui", function () CreateConfig(nil, T["Offhand Bar Color"], C.unitframes, "swingtimerohcolor", "color") CreateConfig(nil, T["Ranged Bar Color"], C.unitframes, "swingtimerrangedcolor", "color") CreateConfig(nil, T["Ranged Warn Color (Hunter)"], C.unitframes, "swingtimerrangedwarncolor", "color") + CreateConfig(nil, T["Out Of Range Color"], C.unitframes, "swingtimeroutrangecolor", "color") CreateConfig(nil, T["Show On Next Attack Queue Color"], C.unitframes, "swingtimerhsqueue", "checkbox") CreateConfig(nil, T["Show Attack Speed"], C.unitframes, "swingtimerattackspeed", "checkbox") diff --git a/modules/swingtimer.lua b/modules/swingtimer.lua index afb1738e..0e7f37ed 100644 --- a/modules/swingtimer.lua +++ b/modules/swingtimer.lua @@ -23,8 +23,13 @@ pfUI:RegisterModule("swingtimer", function () useSpellQueueEvent = false, swingThrottle = 0, onSwingCache = {}, + outOfRange = {}, -- by Enum.PlayerSwingType } + local MAINHAND = Enum.PlayerSwingType.MainHand + local OFFHAND = Enum.PlayerSwingType.OffHand + local RANGED = Enum.PlayerSwingType.Ranged + -- On-next-swing spells replace the next auto-attack swing. -- Covers Raptor Strike, Maul, Mongoose Bite, Holy Strike, etc. automatically. local function IsOnSwingSpell(spellId) @@ -63,6 +68,7 @@ pfUI:RegisterModule("swingtimer", function () local ohR, ohG, ohB, ohA = ParseColor(C.unitframes.swingtimerohcolor, 0.3, 0.8, 0.3, 1) local raR, raG, raB, raA = ParseColor(C.unitframes.swingtimerrangedcolor, 0.3, 0.6, 1.0, 1) local rwR, rwG, rwB, rwA = ParseColor(C.unitframes.swingtimerrangedwarncolor, 0.9, 0.0, 0.0, 1) + local orR, orG, orB = ParseColor(C.unitframes.swingtimeroutrangecolor, 0.5, 0.5, 0.5, 1) local isHunter = UnitClassBase("player") == "HUNTER" local mhDefaultR, mhDefaultG, mhDefaultB = mhR, mhG, mhB @@ -499,6 +505,10 @@ pfUI:RegisterModule("swingtimer", function () end -- Render MH + if S.outOfRange[MAINHAND] then + curR, curG, curB = orR, orG, orB + end + if S.mhActive then local progress = 1 - (S.mhTimer / S.mhTimerMax) pfUI.swingtimer.mainhand:SetValue(progress) @@ -538,6 +548,11 @@ pfUI:RegisterModule("swingtimer", function () if sw_showoh and S.ohActive then local progress = 1 - (S.ohTimer / S.ohTimerMax) pfUI.swingtimer.offhand:SetValue(progress) + if S.outOfRange[OFFHAND] then + pfUI.swingtimer.offhand:SetStatusBarColor(orR, orG, orB, ohA) + else + pfUI.swingtimer.offhand:SetStatusBarColor(ohR, ohG, ohB, ohA) + end if S.ohTimer <= 0 then if S.lastOhMarkerX ~= -1 then S.lastOhMarkerX = -1 @@ -573,13 +588,13 @@ pfUI:RegisterModule("swingtimer", function () -- Render Ranged if sw_showranged and S.raActive then local remaining = S.raTimer + local r, g, b, a = raR, raG, raB, raA if isHunter then local DEADZONE = 0.5 if remaining > DEADZONE then - pfUI.swingtimer.ranged:SetStatusBarColor(raR, raG, raB, raA) pfUI.swingtimer.ranged:SetValue((remaining - DEADZONE) / (S.raTimerMax - DEADZONE)) else - pfUI.swingtimer.ranged:SetStatusBarColor(rwR, rwG, rwB, rwA) + r, g, b, a = rwR, rwG, rwB, rwA pfUI.swingtimer.ranged:SetValue(1 - (remaining / DEADZONE)) end if sw_showtext then @@ -595,6 +610,10 @@ pfUI:RegisterModule("swingtimer", function () pfUI.swingtimer.ranged.text:SetFormattedText("%.1f", math.floor(remaining * 10) / 10) end end + if S.outOfRange[RANGED] then + r, g, b = orR, orG, orB + end + pfUI.swingtimer.ranged:SetStatusBarColor(r, g, b, a) if sw_showspeed and S.raSpeed > 0 then pfUI.swingtimer.ranged.speed:SetFormattedText("%.2f", S.raSpeed) end @@ -633,6 +652,7 @@ pfUI:RegisterModule("swingtimer", function () local events = CreateFrame("Frame") events:RegisterEvent("PLAYER_SWING") + events:RegisterEvent("PLAYER_SWING_RANGE_UPDATE") events:RegisterEvent("PLAYER_ENTERING_WORLD") events:RegisterEvent("PLAYER_EQUIPMENT_CHANGED") -- ClassicAPI: per-slot, equipment-only events:RegisterEvent("PLAYER_REGEN_DISABLED") @@ -650,14 +670,19 @@ pfUI:RegisterModule("swingtimer", function () -- ClassicAPI tracks the server's swing clock (white hits, on-next-swing -- abilities, swing-reset casts, parry haste, extra attacks, weapon -- swaps) and hands over the seconds left until the next swing. - if arg2 == Enum.PlayerSwingType.MainHand then + if arg2 == MAINHAND then StartMH(arg1) - elseif arg2 == Enum.PlayerSwingType.OffHand then + elseif arg2 == OFFHAND then StartOH(arg1) - elseif arg2 == Enum.PlayerSwingType.Ranged then + elseif arg2 == RANGED then StartRanged(arg1) end + elseif event == "PLAYER_SWING_RANGE_UPDATE" then + -- arg1 = swingType, arg2 = isInRange, arg3 = checksRange; no check + -- (no target, nothing to attack, no weapon) is not out of range + S.outOfRange[arg1] = arg3 and not arg2 + elseif event == "UNIT_SPELLCAST_SENT" then -- arg4 = spellID: an on-next-swing ability (HS / Cleave / Maul) queued local kind = ClassifyOnSwingSpell(arg4) @@ -769,5 +794,14 @@ pfUI:RegisterModule("swingtimer", function () IsMaulQueued = function() return S.maulQueued end, } + -- the range event fires only on a change, so read the state once + local function EnableRangeCheck(swingType) + C_SwingTimer.EnableRangeCheck(swingType, true) + S.outOfRange[swingType] = C_SwingTimer.IsTargetWithinSwingRange(swingType) == false + end + EnableRangeCheck(MAINHAND) + if sw_showoh then EnableRangeCheck(OFFHAND) end + if sw_showranged then EnableRangeCheck(RANGED) end + UpdateWeaponSpeeds() end) \ No newline at end of file