diff --git a/api/api.lua b/api/api.lua index 44539a98..26c9092d 100644 --- a/api/api.lua +++ b/api/api.lua @@ -143,6 +143,11 @@ function pfUI.api.UnitInRange(unit) return 1 end + -- master switch: with the 40y check off, a visible unit beyond interact + -- range counts as in range (nothing fades). Invisible units already + -- returned nil above, matching the pre-collapse behavior. + if C.unitframes.rangecheck == "0" then return 1 end + -- UnitXP precise mode: skip librange entirely, use direct distance check if C.unitframes.rangecheck_mode == "unitxp" and _G.UnitXP then local threshold = tonumber(C.unitframes.rangecheck_distance) or 40 diff --git a/api/config.lua b/api/config.lua index 09bd22b5..7987b824 100644 --- a/api/config.lua +++ b/api/config.lua @@ -232,7 +232,6 @@ function pfUI:LoadConfig() pfUI:UpdateConfig("unitframes", nil, "druidmanaspace", "-3") pfUI:UpdateConfig("unitframes", nil, "druidmanatexture", "Interface\\AddOns\\pfUI\\img\\bar") - pfUI:UpdateConfig("unitframes", nil, "rangechecki", "4") pfUI:UpdateConfig("unitframes", nil, "combowidth", "6") pfUI:UpdateConfig("unitframes", nil, "comboheight", "6") pfUI:UpdateConfig("unitframes", nil, "swingtimerwidth", "200") @@ -1110,13 +1109,6 @@ function pfUI:MigrateConfig() end end - -- migrating rangecheck interval (> 3.2.2) - if checkversion(3, 2, 2) then - if tonumber(pfUI_config.unitframes.rangechecki) <= 1 then - pfUI_config.unitframes.rangechecki = "2" - end - end - -- migrating legacy buff/debuff naming (> 3.5.0) if checkversion(3, 5, 0) then local unitframes = { "player", "target", "focus", "group", "grouptarget", "grouppet", "raid", "ttarget", "pet", "ptarget", "fallback" } diff --git a/libs/librange.lua b/libs/librange.lua index 71f11fe4..3692470a 100644 --- a/libs/librange.lua +++ b/libs/librange.lua @@ -2,194 +2,28 @@ setfenv(1, pfUI:GetEnvironment()) --[[ librange ]]-- --- A pfUI library that detects and caches distance to units. +-- A thin wrapper over ClassicAPI's UnitInRange: a fixed 40y healing-range +-- check computed C-side from unit positions, valid for any unit. There is +-- no cache or scan loop -- the check is cheap enough to run per query, +-- which also sidesteps the staleness a cached scan hit on zone changes and +-- roster re-indexing. -- -- librange:UnitInSpellRange(unit) -- Returns `1` if the unit is within range, `nil` otherwise. --- --- Requires SuperWoW's UnitPosition for the friendly scan path. Target --- range still works via IsActionInRange (vanilla-native) for any class --- with a known 40y healing spell on the action bar. if pfUI.api.librange then return end -local _, class = UnitClass("player") -local librange = CreateFrame("Frame", "pfRangecheck", UIParent) - --- 40y spells per class. Only consulted to find an action-bar slot for the --- IsActionInRange target-range path; the party/raid scan uses UnitPosition. -local spells = { - ["PALADIN"] = { - "Interface\\Icons\\Spell_Holy_FlashHeal", - "Interface\\Icons\\Spell_Holy_HolyBolt", - }, - ["PRIEST"] = { - "Interface\\Icons\\Spell_Holy_FlashHeal", - "Interface\\Icons\\Spell_Holy_LesserHeal", - "Interface\\Icons\\Spell_Holy_Heal", - "Interface\\Icons\\Spell_Holy_GreaterHeal", - "Interface\\Icons\\Spell_Holy_Renew", - }, - ["DRUID"] = { - "Interface\\Icons\\Spell_Nature_HealingTouch", - "Interface\\Icons\\Spell_Nature_ResistNature", - "Interface\\Icons\\Spell_Nature_Rejuvenation", - }, - ["SHAMAN"] = { - "Interface\\Icons\\Spell_Nature_MagicImmunity", - "Interface\\Icons\\Spell_Nature_HealingWaveLesser", - "Interface\\Icons\\Spell_Nature_HealingWaveGreater", - }, -} - --- friendly units the scan loop iterates -local units = {} -table.insert(units, "pet") -for i=1,4 do table.insert(units, "party" .. i) end -for i=1,4 do table.insert(units, "partypet" .. i) end -for i=1,40 do table.insert(units, "raid" .. i) end -for i=1,40 do table.insert(units, "raidpet" .. i) end -local numunits = table.getn(units) - -local unitcache = {} -local unitdata = {} -local librange_isLoggingOut = false -librange.id = 1 - -librange:Hide() -librange:RegisterEvent("ACTIONBAR_SLOT_CHANGED") -librange:RegisterEvent("PLAYER_ENTERING_WORLD") -librange:RegisterEvent("PLAYER_LOGOUT") -librange:RegisterEvent("PLAYER_LEAVING_WORLD") -librange:RegisterEvent("RAID_ROSTER_UPDATE") -librange:RegisterEvent("PARTY_MEMBERS_CHANGED") -librange:SetScript("OnEvent", function() - if event == "PLAYER_LOGOUT" then - librange_isLoggingOut = true - this:Hide() - return - end - - if event == "PLAYER_LEAVING_WORLD" then - this:Hide() - return - end - - if event == "RAID_ROSTER_UPDATE" or event == "PARTY_MEMBERS_CHANGED" then - -- Roster re-index: unitN tokens now map to different players, so the - -- token->realunit cache is stale. Clear it and restart the sweep from - -- the top so shifted/joined slots are re-evaluated within one pass - -- instead of inheriting the previous occupant's cached range. - for k in pairs(unitcache) do unitcache[k] = nil end - this.id = 1 - return - end - - if pfUI_config.unitframes.rangecheck == "0" then - this:Hide() - return - end - - this.interval = tonumber(C.unitframes.rangechecki)/numunits - - if event == "ACTIONBAR_SLOT_CHANGED" or event == "PLAYER_ENTERING_WORLD" then - librange.slot = this:GetRangeSlot() - if UnitPosition then this:Show() end - end -end) - -librange:SetScript("OnUpdate", function() - if librange_isLoggingOut then return end - - if (this.tick or 1) > GetTime() then return end - this.tick = GetTime() + this.interval - - while not this:NeedRangeScan(units[this.id]) and this.id <= numunits do - this.id = this.id + 1 - end - - if this.id <= numunits then - local unit = units[this.id] - if not UnitIsUnit("target", unit) then - local x1, y1, z1 = UnitPosition("player") - local x2, y2, z2 = UnitPosition(unit) - if x1 and x2 then - local distance = ((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)^.5 - unitdata[unit] = distance < 45 and 1 or 0 - end - end - this.id = this.id + 1 - else - this.id = 1 - end -end) - -function librange:NeedRangeScan(unit) - if not UnitExists(unit) then return nil end - if not UnitIsVisible(unit) then return nil end - if CheckInteractDistance(unit, 4) then return nil end - return true -end - -function librange:GetRealUnit(unit) - if unitdata[unit] then return unit end - - if unitcache[unit] and UnitIsUnit(unitcache[unit], unit) then - return unitcache[unit] - end - - for id, realunit in pairs(units) do - if UnitIsUnit(realunit, unit) then - unitcache[unit] = realunit - return realunit - end - end - - return unit -end - -function librange:GetRangeSlot() - if not spells[class] then return nil end - for i=1,120 do - -- Resolve the slot to a spellID for both spell and macro actions; the old - -- `not GetActionText` macro-filter missed macros that cast a 40y heal but - -- displayed a non-spell icon. C_Spell.GetSpellTexture(spellID) gives the - -- spell's *intrinsic* icon, which is what we match against. - local kind, id = GetActionInfo(i) - local spellID - if kind == "spell" then - spellID = id - elseif kind == "macro" then - local _, _, sid = GetMacroSpell(id) - spellID = sid - end - if spellID then - local texture = C_Spell.GetSpellTexture(spellID) - if texture then - for _, check in pairs(spells[class]) do - if check == texture then return i end - end - end - end - end - return nil -end +local librange = {} function librange:UnitInSpellRange(unit) - if UnitIsUnit("target", unit) then - if not librange.slot then return nil end - return IsActionInRange(librange.slot) == 1 and 1 or nil - end - - local unit = librange:GetRealUnit(unit) - - if unitdata[unit] and unitdata[unit] == 1 then - return 1 - elseif not unitdata[unit] then - return 1 - else - return nil - end + -- _G-qualified: bare `UnitInRange` resolves to pfUI.api.UnitInRange inside + -- the pfUI environment (which calls us), so this must reach ClassicAPI's + -- global directly or it recurses. + local inRange, checked = _G.UnitInRange(unit) + -- position miss (e.g. a unit outside the client's sync range): we can't + -- tell, so default to in-range -- matches the old cache's nil behavior. + if not checked then return 1 end + return inRange and 1 or nil end -- add librange to pfUI API diff --git a/modules/gui.lua b/modules/gui.lua index 98923e00..8b214b4e 100644 --- a/modules/gui.lua +++ b/modules/gui.lua @@ -2119,7 +2119,6 @@ pfUI:RegisterModule("gui", function () CreateConfig(nil, T["Enable 40y-Range Check"], C.unitframes, "rangecheck", "checkbox", nil, nil, nil, nil) CreateConfig(nil, T["Range Check Mode"], C.unitframes, "rangecheck_mode", "dropdown", pfUI.gui.dropdowns.uf_rangecheck_mode, nil, nil, nil) CreateConfig(nil, T["UnitXP Range Threshold (yards)"], C.unitframes, "rangecheck_distance", nil, nil, nil, nil, nil) - CreateConfig(nil, T["Range Check Interval"], C.unitframes, "rangechecki", "dropdown", pfUI.gui.dropdowns.uf_rangecheckinterval, nil, nil, nil) CreateConfig(nil, T["Use Raid Frames To Display Group Members"], C.unitframes, "raidforgroup", "checkbox") CreateConfig(nil, T["Always Show Self In Raid Frames"], C.unitframes, "selfinraid", "checkbox") CreateConfig(nil, T["Show Self In Group Frames"], C.unitframes, "selfingroup", "checkbox")