From 19b1609e82debe7790ea5ce6523c4753ea6b7104 Mon Sep 17 00:00:00 2001 From: Aleksi Blinnikka Date: Sun, 3 Feb 2019 22:35:14 +0200 Subject: [PATCH] Change main events to a constant update to fix event issues --- kehys/events.lua | 176 ---------------------------------------------- kehys/frame.lua | 3 +- kehys/kehys.toc | 1 + kehys/raid.lua | 12 +--- kehys/updater.lua | 151 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 188 deletions(-) create mode 100644 kehys/updater.lua diff --git a/kehys/events.lua b/kehys/events.lua index 16c6479..32241e4 100644 --- a/kehys/events.lua +++ b/kehys/events.lua @@ -31,7 +31,6 @@ local width = 80; function addon.RegisterEvents(frame) frame:RegisterEvent("PLAYER_ENTERING_WORLD"); - frame:RegisterEvent("PLAYER_ROLES_ASSIGNED"); frame:RegisterEvent("READY_CHECK"); frame:RegisterEvent("READY_CHECK_FINISHED"); frame:RegisterEvent("GROUP_ROSTER_UPDATE"); @@ -42,16 +41,8 @@ end function addon.RegisterUnitEvents(frame) -- events are taken from FrameXML/CompactUnitFrame.lua local displayed = frame.unit ~= frame.displayed and frame.displayed or nil; - frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed); - frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed); frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed); - frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed); - --frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed); - frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed); - frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed); frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed); - frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed); - frame:RegisterUnitEvent("PLAYER_FLAGS_CHANGED", frame.unit, displayed); frame:RegisterUnitEvent("READY_CHECK_CONFIRM", frame.unit, displayed); frame:RegisterUnitEvent("UNIT_ENTERED_VEHICLE", frame.unit, displayed); frame:RegisterUnitEvent("UNIT_EXITED_VEHICLE", frame.unit, displayed); @@ -59,62 +50,6 @@ function addon.RegisterUnitEvents(frame) end local registerUnitEvents = addon.RegisterUnitEvents; -local function updateText(frame, unit) - if UnitIsDeadOrGhost(unit) then - frame.dead = true; - frame.text:SetText("Dead"); - frame.text:Show(); - elseif not UnitIsConnected(unit) then - frame.text:SetText("DC"); - frame.text:Show(); - elseif UnitIsAFK(unit) then - frame.text:SetText("afk"); - frame.text:Show(); - elseif UnitIsDND(unit) then - frame.text:SetText("dnd"); - frame.text:Show(); - else - frame.text:Hide(); - end -end -addon.Events.UpdateText = updateText; - -local function updateMaxHealth(frame, unit) - frame.health.max = UnitHealthMax(unit); -end -addon.Events.UpdateMaxHealth = updateMaxHealth; - -local function updateHealth(frame, unit) - local current, max = UnitHealth(unit), frame.health.max; - if current == frame.prev.health then - return false; - end - frame.prev.health = current; - if current > max or max <= 0 then - -- somehow current health has gone over the maximum (missed maxhealth event possibly) - -- just put health bar full and update max health for next event - frame.health:SetWidth(width); - frame.health.width = width; - updateMaxHealth(frame, unit); - frame.health:Show(); - elseif current <= 0 or UnitIsDeadOrGhost(unit) then - frame.health:Hide(); - updateText(frame, unit); -- update death - else - local w = current/max*width; - frame.health:SetWidth(w); - frame.health.width = w; - frame.health:Show(); - end - - if frame.dead and current > 0 then - frame.dead = nil; - updateText(frame, unit); -- update revive - end - return true; -end -addon.Events.UpdateHealth = updateHealth; - local function updateName(frame, unit) local name = UnitName(unit); if not name then return end @@ -131,80 +66,6 @@ local function updateName(frame, unit) end addon.Events.UpdateName = updateName; -local function updateHealPred(frame, unit) - local incoming = UnitGetIncomingHeals(unit) or 0; - if incoming > 0 then - incoming = (incoming / frame.health.max) * width; - -- always at least 1 pixel space for heal prediction - frame.healpred:SetWidth(min(width - frame.health.width + 1, incoming)); - if not frame.healpred:IsShown() then frame.healpred:Show() end - else - if frame.healpred:IsShown() then frame.healpred:Hide() end - end -end -addon.Events.UpdateHealPred = updateHealPred; - -local function updateShield(frame, unit) - local shield = UnitGetTotalAbsorbs(unit) or 0; - if shield > 0 then - local space = width - frame.health.width; - shield = (shield / frame.health.max) * width; - if space == 0 then - if frame.shield:IsShown() then frame.shield:Hide() end - if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end - elseif space < shield then - frame.shield:SetWidth(space); - if not frame.shield:IsShown() then frame.shield:Show() end - if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end - else - frame.shield:SetWidth(shield); - if not frame.shield:IsShown() then frame.shield:Show() end - if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end - end - else - if frame.shield:IsShown() then frame.shield:Hide() end - if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end - end -end -addon.Events.UpdateShield = updateShield; - -local function updateHealAbsorb(frame, unit) - local absorb = UnitGetTotalHealAbsorbs(unit) or 0; - if absorb > 0 then - absorb = (absorb / frame.health.max) * width; - frame.healabsorb:SetWidth(min(frame.health.width, absorb)); - frame.healabsorb:Show(); - else - frame.healabsorb:Hide(); - end -end -addon.Events.UpdateHealAbsorb = updateHealAbsorb; - -local function updateAuras(frame, unit) - -- don't overlay charmed when in vehicle - --[[if UnitIsCharmed(unit) and unit == frame.unit then - if frame.overlay.color ~= overlayColorCharm then - frame.overlay:SetVertexColor(unpack(overlayColorCharm)); - frame.overlay.color = overlayColorCharm; - frame.overlay:Show(); - end - else--]] - if UnitDebuff(unit, 1, "RAID") ~= nil then - -- something dispellable - if frame.overlay.color ~= overlayColorDispel then - frame.overlay:SetVertexColor(unpack(overlayColorDispel)); - frame.overlay.color = overlayColorDispel; - if not frame.overlay:IsShown() then frame.overlay:Show() end - end - else - if frame.overlay.color ~= nil then - frame.overlay.color = nil; - if frame.overlay:IsShown() then frame.overlay:Hide() end - end - end -end -addon.Events.UpdateAuras = updateAuras; - local function updateAggro(frame, unit) local status = UnitThreatSituation(unit); if status and status > 0 then @@ -275,40 +136,12 @@ end addon.Events.UpdateRaidMarker = updateRaidMarker; local eventFuncs = { - ["UNIT_HEALTH"] = function(frame) - if updateHealth(frame, frame.displayed) then - updateShield(frame, frame.displayed); - updateHealAbsorb(frame, frame.displayed); - -- no heal prediction update, that doesn't overflow too much - end - end, - ["UNIT_AURA"] = function(frame) - updateAuras(frame, frame.displayed); - end, - ["UNIT_HEAL_PREDICTION"] = function(frame) - updateHealPred(frame, frame.displayed); - end, - ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame) - updateShield(frame, frame.displayed); - end, - ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame) - updateHealAbsorb(frame, frame.displayed); - end, ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame) updateAggro(frame, frame.displayed); end, - ["UNIT_MAXHEALTH"] = function(frame) - updateMaxHealth(frame, frame.displayed); - updateHealth(frame, frame.displayed); - updateShield(frame, frame.displayed); - updateHealAbsorb(frame, frame.displayed); - end, ["UNIT_NAME_UPDATE"] = function(frame) updateName(frame, frame.unit); end, - ["UNIT_CONNECTION"] = function(frame) - updateText(frame, frame.displayed); - end, ["PLAYER_ROLES_ASSIGNED"] = function(frame) updateRole(frame, frame.unit); end, @@ -321,21 +154,12 @@ local eventFuncs = { ["UPDATE_ALL_BARS"] = function(frame) updateRole(frame, frame.unit); updateVehicle(frame); - updateMaxHealth(frame, frame.displayed); - updateHealth(frame, frame.displayed); - updateText(frame, frame.displayed); - updateAuras(frame, frame.displayed); - updateShield(frame, frame.displayed); - --updateHealPred(frame, frame.displayed); - updateHealAbsorb(frame, frame.displayed); updateAggro(frame, frame.displayed); updateName(frame, frame.unit); updateReadyCheck(frame, frame.unit); updateRaidMarker(frame, frame.displayed); end, }; -eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"]; -eventFuncs["PLAYER_FLAGS_CHANGED"] = eventFuncs["UNIT_CONNECTION"]; eventFuncs["READY_CHECK_CONFIRM"] = eventFuncs["READY_CHECK"]; eventFuncs["READY_CHECK_FINISHED"] = eventFuncs["READY_CHECK"]; eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"]; diff --git a/kehys/frame.lua b/kehys/frame.lua index 2409d26..a723f47 100644 --- a/kehys/frame.lua +++ b/kehys/frame.lua @@ -42,6 +42,7 @@ function addon.NewRaidFrame(parent, width, height, unit, attributes, f:Hide(); -- hide frame to have an initial frame:OnShow call f:SetWidth(width); f:SetHeight(height); + f.barwidth = width - 2; -- 1px padding on both sides f:SetAttribute("unit", unit); f.unit = unit; f.displayed = unit; @@ -50,7 +51,7 @@ function addon.NewRaidFrame(parent, width, height, unit, attributes, -- set up periodic updates updaters[f] = function() if f.updating then - CTimerAfter(0.25, updaters[f]); + CTimerAfter(0.1, updaters[f]); return update(f) end end diff --git a/kehys/kehys.toc b/kehys/kehys.toc index 4dbc3b4..41bca34 100644 --- a/kehys/kehys.toc +++ b/kehys/kehys.toc @@ -7,6 +7,7 @@ hideblizz.lua setup.lua paladin.lua +updater.lua events.lua frame.lua raid.lua diff --git a/kehys/raid.lua b/kehys/raid.lua index 7a68f90..7a88174 100644 --- a/kehys/raid.lua +++ b/kehys/raid.lua @@ -8,6 +8,7 @@ local RegisterStateDriver, RegisterUnitWatch = RegisterStateDriver, RegisterUnit local registerEvents = addon.RegisterEvents; local registerUnitEvents = addon.RegisterUnitEvents; local unitEvent = addon.UnitEvent; +local unitUpdate = addon.FrameUpdate; local width, height = 82, 42; local anchorX, anchorY = 0, -330; @@ -18,17 +19,6 @@ local class = nil; local party = {}; local raid = {}; -local function unitUpdate(frame) - -- there's no in/out of range event, have to check each frame - -- from FrameXML/CompactUnitFrame.lua - local inRange, checked = UnitInRange(frame.displayed); - if checked and not inRange then - frame:SetAlpha(0.55); - else - frame:SetAlpha(1); - end -end - local function frameShow(frame) registerEvents(frame); registerUnitEvents(frame); diff --git a/kehys/updater.lua b/kehys/updater.lua new file mode 100644 index 0000000..fac538c --- /dev/null +++ b/kehys/updater.lua @@ -0,0 +1,151 @@ +-- updater.lua +-- 2019 Aleksi Blinnikka +-- +-- Main update function for all frames. Gets around issues with events. +local _, addon = ...; +local unpack = unpack; +local min = math.min; +local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed; +local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax; +local UnitIsAFK, UnitIsDND = UnitIsAFK, UnitIsDND; +local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs; +local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected; +local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs; + +local dispelcolor = addon.Colors.OverlayColorDispel; +local charmcolor = addon.Colors.OverlayColorCharm; +local majorcolor = addon.Colors.OverlayColorAlert; + +local function updateAuras() + -- TODO + return false; +end + +function addon.FrameUpdate(frame) + assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!"); + + local unit = frame.displayed; + local width = frame.barwidth; + -- range check (doesn't have an event) + local inrange, checked = UnitInRange(unit); + if checked and not inrange then + frame:SetAlpha(0.55); + else + frame:SetAlpha(1); + end + -- states + if UnitIsDeadOrGhost(unit) then + frame.text:SetText("Dead"); + if not frame.text:IsShown() then frame.text:Show() end + if frame.health:IsShown() then frame.health:Hide() end + if frame.shield:IsShown() then frame.shield:Hide() end + if frame.healpred:IsShown() then frame.healpred:Hide() end + if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end + --if frame.auras:IsShown() then frame.auras:Hide() end + elseif not UnitIsConnected(unit) then + frame.text:SetText("DC"); + if not frame.text:IsShown() then frame.text:Show() end + if frame.health:IsShown() then frame.health:Hide() end + if frame.shield:IsShown() then frame.shield:Hide() end + if frame.healpred:IsShown() then frame.healpred:Hide() end + if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end + --if frame.auras:IsShown() then frame.auras:Hide() end + else + if UnitIsAFK(unit) then + frame.text:SetText("afk"); + if not frame.text:IsShown() then frame.text:Show() end + elseif UnitIsDND(unit) then + frame.text:SetText("dnd"); + if not frame.text:IsShown() then frame.text:Show() end + else + if frame.text:IsShown() then frame.text:Hide() end + end + -- health + local current, hmax = UnitHealth(unit), UnitHealthMax(unit); + if frame.prev.health ~= current or frame.prev.hmax ~= hmax then + frame.prev.health = current; + frame.prev.hmax = hmax; + if hmax < current or hmax <= 1 then + frame.health:SetWidth(width); + frame.health.width = width; + if not frame.health:IsShown() then frame.health:Show() end + elseif current <= 0 then + if frame.health:IsShown() then frame.health:Hide() end + else + local w = current/hmax*width; + frame.health:SetWidth(w); + frame.health.width = w; + if not frame.health:IsShown() then frame.health:Show() end + end + end + -- shield + local hwidth = frame.health.width; + current = UnitGetTotalAbsorbs(unit) or 0; + if current > 0 then + local space = width - hwidth; + current = (current / hmax) * width; + if space == 0 then + if frame.shield:IsShown() then frame.shield:Hide() end + if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end + elseif space < current then + frame.shield:SetWidth(space); + if not frame.shield:IsShown() then frame.shield:Show() end + if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end + else + frame.shield:SetWidth(current); + if not frame.shield:IsShown() then frame.shield:Show() end + if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end + end + else + if frame.shield:IsShown() then frame.shield:Hide() end + if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end + end + -- heal absorb + current = UnitGetTotalHealAbsorbs(unit) or 0; + if current > 0 then + current = (current / hmax) * width; + frame.healabsorb:SetWidth(min(hwidth, current)); + if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end + elseif frame.healabsorb:IsShown() then + frame.healabsorb:Hide(); + end + -- heal prediction + current = UnitGetIncomingHeals(unit) or 0; + if current > 0 then + current = (current / hmax) * width; + -- at least 1 pixel prediction shown + frame.healpred:SetWidth(min(width - hwidth + 1, current)); + if not frame.healpred:IsShown() then frame.healpred:Show() end + elseif frame.healpred:IsShown() then + frame.healpred:Hide(); + end + -- auras + if updateAuras(frame, unit) then + -- major + if frame.overlay.color ~= majorcolor then + frame.overlay:SetVertexColor(unpack(majorcolor)); + frame.overlay.color = majorcolor; + if not frame.overlay:IsShown() then frame.overlay:Show() end + end + elseif UnitIsCharmed(unit) and frame.unit == frame.displayed then + -- charmed + if frame.overlay.color ~= charmcolor then + frame.overlay:SetVertexColor(unpack(charmcolor)); + frame.overlay.color = charmcolor; + if not frame.overlay:IsShown() then frame.overlay:Show() end + end + elseif UnitDebuff(unit, 1, "RAID") ~= nil then + -- dispellable + if frame.overlay.color ~= dispelcolor then + frame.overlay:SetVertexColor(unpack(dispelcolor)); + frame.overlay.color = dispelcolor; + if not frame.overlay:IsShown() then frame.overlay:Show() end + end + else + if frame.overlay.color ~= nil then + frame.overlay.color = nil; + if frame.overlay:IsShown() then frame.overlay:Hide() end + end + end + end +end -- 2.39.5