mirror of
https://github.com/brues-code/pfUI.git
synced 2026-09-22 07:36:56 +00:00
b7c3fe5333
ClassicAPI's RegisterUnitEvent registers for an event but only delivers it when arg1 is one of the given units, so a handler for one unit stops waking for every other one in the world. Convert the 26 registrations whose unit set is fixed and known at registration time. The rule throughout is register the superset and keep the handler's own check: the filter narrows what arrives, it does not decide what to act on. castbar is the case that matters -- the player's own casts only ever fire arg1=="player", never "target"/"focus", so the target and focus bars must register "player" too, and their UnitIsUnit test is what still rejects a "player" event while you are targeting a mob. Two that are not one-line swaps: actionbar's two unit events are keys in tables that also drive dispatch, so they cannot leave the tables -- and they cannot be plain-registered first, because a registration keeps its kind and RegisterUnitEvent over a plain one stays plain. They route through a small event_units map instead. swingtimer's UNIT_DIED carries a GUID, not a token. The filter is a plain case-insensitive string compare with no GUID resolution, so the player's own GUID -- fixed for the session -- filters it exactly. Guards that are now unreachable stay put: the filter applies only when arg1 is a string, so an event that ever fires with a number or no argument is delivered as if plainly registered, and the handler's own test is what still rejects it. Left alone: api/unitframes.lua (the frame's unit changes at runtime and the handler also matches on GUID), nameplates' six nameplateN events, libdebuff and libpredict's UNIT_HEALTH (genuinely any unit), and raid.lua's UNIT_PET (any raid member can own the pet).
109 lines
3.8 KiB
Lua
109 lines
3.8 KiB
Lua
-- load pfUI environment
|
|
setfenv(1, pfUI:GetEnvironment())
|
|
|
|
if pfUI.libhealth then return end
|
|
|
|
local mobdb = {}
|
|
local target, dmg, perc, diff = nil, 0, 0, 0, 0
|
|
local UnitHealth, UnitHealthMax
|
|
local libhealth = CreateFrame("Frame")
|
|
libhealth.enabled = true
|
|
libhealth.reqhit = 4
|
|
libhealth.reqdmg = 5
|
|
libhealth:RegisterUnitEvent("UNIT_HEALTH", "target")
|
|
libhealth:RegisterUnitEvent("UNIT_COMBAT", "target")
|
|
libhealth:RegisterEvent("PLAYER_TARGET_CHANGED")
|
|
libhealth:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
libhealth:SetScript("OnEvent", function()
|
|
if event == "PLAYER_ENTERING_WORLD" then
|
|
-- create initial health cache tables
|
|
pfUI_cache["libhealth"] = pfUI_cache["libhealth"] or {}
|
|
mobdb = pfUI_cache["libhealth"]
|
|
|
|
-- load enable state and set functions
|
|
libhealth.enabled = pfUI_config["global"]["libhealth"] == "1" and true or nil
|
|
libhealth.reqhit = (tonumber(pfUI_config["global"]["libhealth_hit"]) or 4)
|
|
libhealth.reqdmg = (tonumber(pfUI_config["global"]["libhealth_dmg"]) or 0.5) * 100
|
|
end
|
|
|
|
-- return as we're not supposed to be here
|
|
if not libhealth.enabled then this:UnregisterAllEvents() return end
|
|
|
|
-- try to estimate mob health based on combat and health events
|
|
if event == "PLAYER_TARGET_CHANGED" then
|
|
dmg, perc = 0, _G.UnitHealth("target")
|
|
if UnitName("target") and UnitLevel("target") and _G.UnitHealthMax("target") == 100 then
|
|
target = string.format("%s:%d",UnitName("target"), UnitLevel("target"))
|
|
else
|
|
target = nil
|
|
end
|
|
elseif target and event == "UNIT_COMBAT" and arg1 == "target" then
|
|
if arg2 and arg2 == "HEAL" then return end
|
|
dmg = dmg + arg4
|
|
elseif target and event == "UNIT_HEALTH" and arg1 == "target" then
|
|
diff = perc-_G.UnitHealth("target")
|
|
if dmg > 0 and diff > 0 then
|
|
mobdb[target] = mobdb[target] or {}
|
|
if not mobdb[target][2] or diff > mobdb[target][2] then
|
|
mobdb[target][1] = ceil(dmg / diff * 100)
|
|
mobdb[target][2] = diff
|
|
mobdb[target][3] = mobdb[target][3] and mobdb[target][3] + 1 or 1
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- core function to query the generated database
|
|
local unit, level, cur, max, dbstring
|
|
local function GetUnitHealth(self, unitstr)
|
|
unit = UnitName(unitstr)
|
|
level = UnitLevel(unitstr)
|
|
cur = _G.UnitHealth(unitstr)
|
|
max = _G.UnitHealthMax(unitstr)
|
|
|
|
-- return raw values if another addon is replacing global API calls
|
|
if cur > 100 or max > 100 or max < 100 then
|
|
return cur, max, true
|
|
end
|
|
|
|
-- return raw values if no unit data could be found (unlikely but happened...)
|
|
if not unit or not level then
|
|
return cur, max
|
|
end
|
|
|
|
-- query the database for known values
|
|
dbstring = string.format("%s:%s", unit, level)
|
|
if mobdb[dbstring] and mobdb[dbstring][1] and mobdb[dbstring][2] > libhealth.reqdmg and (not mobdb[dbstring][3] or mobdb[dbstring][3] > libhealth.reqhit) then
|
|
return ceil(mobdb[dbstring][1]/100*cur), mobdb[dbstring][1], true
|
|
end
|
|
|
|
-- return raw values as fallback
|
|
return cur, max
|
|
end
|
|
|
|
local function GetUnitHealthByName(self, unit, level, cur, max)
|
|
-- return raw values if another addon is replacing global API calls
|
|
if cur > 100 or max > 100 or max < 100 then
|
|
return cur, max, true
|
|
end
|
|
|
|
-- return raw values if no unit data could be found (unlikely but happened...)
|
|
if not unit or not level then
|
|
return cur, max
|
|
end
|
|
|
|
-- query the database for known values
|
|
dbstring = string.format("%s:%s", unit, level)
|
|
if mobdb[dbstring] and mobdb[dbstring][1] and mobdb[dbstring][2] > libhealth.reqdmg and (not mobdb[dbstring][3] or mobdb[dbstring][3] > libhealth.reqhit) then
|
|
return ceil(mobdb[dbstring][1]/100*cur), mobdb[dbstring][1], true
|
|
end
|
|
|
|
-- return raw values as fallback
|
|
return cur, max
|
|
end
|
|
|
|
-- add api calls to global tree
|
|
pfUI.libhealth = libhealth
|
|
pfUI.libhealth.GetUnitHealth = GetUnitHealth
|
|
pfUI.libhealth.GetUnitHealthByName = GetUnitHealthByName
|