From b54647d00658c6c5035802565da32d144a3ad10c Mon Sep 17 00:00:00 2001 From: Rainrider Date: Sat, 18 Feb 2023 16:43:03 +0100 Subject: [PATCH] fix: update for Dragonflight --- .luacheckrc | 5 +- oUF_Dispellable.lua | 140 +++++++++++++++++++++++++++++++------------- oUF_Dispellable.toc | 2 +- 3 files changed, 103 insertions(+), 44 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 6bc10a3..d50ddc4 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -10,12 +10,15 @@ read_globals = { table = { fields = { 'wipe' } }, -- API + C_UnitAuras = { + fields = { 'GetAuraByAuraInstanceID', 'GetAuraDataBySlot' } + }, 'CreateFrame', 'IsPlayerSpell', 'IsSpellKnown', + 'UnitAuraSlots', 'UnitCanAssist', 'UnitClass', - 'UnitDebuff', 'UnitRace', -- Widgets diff --git a/oUF_Dispellable.lua b/oUF_Dispellable.lua index 22fde0f..98bec6f 100644 --- a/oUF_Dispellable.lua +++ b/oUF_Dispellable.lua @@ -108,7 +108,6 @@ local wipe = table.wipe local IsPlayerSpell = IsPlayerSpell local IsSpellKnown = IsSpellKnown local UnitCanAssist = UnitCanAssist -local UnitDebuff = UnitDebuff local _, playerClass = UnitClass('player') local _, playerRace = UnitRace('player') @@ -132,13 +131,19 @@ end local canDispel = {} +local function IsDispellable(aura, unit) + local dispellable = canDispel[aura.dispelName] + + return dispellable == true or dispellable == unit +end + --[[ Override: Dispellable.dispelIcon:UpdateTooltip() Called to update the widget's tooltip. * self - the dispelIcon sub-widget --]] local function UpdateTooltip(dispelIcon) - GameTooltip:SetUnitAura(dispelIcon.unit, dispelIcon.id, 'HARMFUL') + GameTooltip:SetUnitDebuffByAuraInstanceID(dispelIcon.unit, dispelIcon.id) end local function OnEnter(dispelIcon) @@ -168,60 +173,90 @@ local function UpdateColor(dispelTexture, _, r, g, b, a) dispelTexture:SetVertexColor(r, g, b, a) end -local function Update(self, _, unit) - if self.unit ~= unit then - return - end - +local function UpdateDebuffs(self, updateInfo) + local unit = self.unit local element = self.Dispellable + local debuffs = element.debuffs - --[[ Callback: Dispellable:PreUpdate() - Called before the element has been updated. + if not UnitCanAssist('player', unit) then + wipe(debuffs) - * self - the Dispellable element - --]] - if element.PreUpdate then - element:PreUpdate() + return end - local dispelTexture = element.dispelTexture - local dispelIcon = element.dispelIcon + if not updateInfo or updateInfo.isFullUpdate then + wipe(debuffs) + local slots = { UnitAuraSlots(unit, 'HARMFUL') } + + for i = 2, #slots do + local debuff = C_UnitAuras.GetAuraDataBySlot(unit, slots[i]) + + if IsDispellable(debuff, unit) then + debuffs[debuff.auraInstanceID] = debuff + end + end + else + for _, aura in next, updateInfo.addedAuras or {} do + if aura.isHarmful and IsDispellable(aura, unit) then + debuffs[aura.auraInstanceID] = aura + end + end - local texture, count, debuffType, duration, expiration, id, dispellable - if UnitCanAssist('player', unit) then - for i = 1, 40 do - _, texture, count, debuffType, duration, expiration = UnitDebuff(unit, i) + for _, auraInstanceID in next, updateInfo.updatedAuraInstanceIDs or {} do + local aura = C_UnitAuras.GetAuraByAuraInstanceID(unit, auraInstanceID) - if not texture or canDispel[debuffType] == true or canDispel[debuffType] == unit then - dispellable = debuffType - id = i - break + if aura.isHarmful and IsDispellable(aura, unit) then + debuffs[aura.auraInstanceID] = aura end end + + for _, auraInstanceID in next, updateInfo.removedAuraInstanceIDs or {} do + debuffs[auraInstanceID] = nil + end + end +end + +local function UpdateDisplay(self) + local element = self.Dispellable + local lowestID = nil + + for auraInstanceID in next, element.debuffs do + if not lowestID or auraInstanceID < lowestID then + lowestID = auraInstanceID + end end - if dispellable then - local color = self.colors.debuff[debuffType] - local r, g, b = color[1], color[2], color[3] + local dispelTexture = element.dispelTexture + local dispelIcon = element.dispelIcon + + if lowestID and lowestID ~= element.__current then + element.__current = lowestID + local debuff = element.debuffs[lowestID] + local debuffType = debuff.dispelName + local r, g, b = self.colors.debuff[debuffType]:GetRGB() + if dispelTexture then dispelTexture:UpdateColor(debuffType, r, g, b, dispelTexture.dispelAlpha) end if dispelIcon then - dispelIcon.unit = unit - dispelIcon.id = id + dispelIcon.unit = self.unit + dispelIcon.id = lowestID if dispelIcon.icon then - dispelIcon.icon:SetTexture(texture) + dispelIcon.icon:SetTexture(debuff.icon) end if dispelIcon.overlay then dispelIcon.overlay:SetVertexColor(r, g, b) end if dispelIcon.count then - dispelIcon.count:SetText(count and count > 1 and count) + local count = debuff.applications + dispelIcon.count:SetText(count and count > 1 and count or '') end if dispelIcon.cd then - if duration and duration > 0 then - dispelIcon.cd:SetCooldown(expiration - duration, duration) + local duration = debuff.duration + + if duration > 0 then + dispelIcon.cd:SetCooldown(debuff.expirationTime - duration, duration, debuff.timeMod) dispelIcon.cd:Show() else dispelIcon.cd:Hide() @@ -230,7 +265,11 @@ local function Update(self, _, unit) dispelIcon:Show() end - else + + return debuff + elseif not lowestID and element.__current ~= nil then + element.__current = nil + if dispelTexture then dispelTexture:UpdateColor(nil, 1, 1, 1, dispelTexture.noDispelAlpha) end @@ -238,19 +277,35 @@ local function Update(self, _, unit) dispelIcon:Hide() end end +end + +local function Update(self, _, unit, updateInfo) + if self.unit ~= unit then + return + end + + local element = self.Dispellable + + --[[ Callback: Dispellable:PreUpdate() + Called before the element has been updated. + + * self - the Dispellable element + --]] + if element.PreUpdate then + element:PreUpdate() + end + + UpdateDebuffs(self, updateInfo) + local displayed = UpdateDisplay(self) --[[ Callback: Dispellable:PostUpdate(debuffType, texture, count, duration, expiration) Called after the element has been updated. - * self - the Dispellable element - * debuffType - the type of the dispellable debuff (string?)['Curse', 'Disease', 'Magic', 'Poison'] - * texture - the texture representing the debuff icon (number?) - * count - the stack count of the dispellable debuff (number?) - * duration - the duration of the dispellable debuff in seconds (number?) - * expiration - the point in time when the debuff will expire. Can be compared to `GetTime()` (number?) + * self - the Dispellable element + * displayed - the displayed debuff (UnitAuraInfo?) --]] if element.PostUpdate then - element:PostUpdate(dispellable, texture, count, duration, expiration) + element:PostUpdate(displayed) end end @@ -276,6 +331,7 @@ local function Enable(self) end element.__owner = self + element.debuffs = {} element.ForceUpdate = ForceUpdate local dispelTexture = element.dispelTexture @@ -312,8 +368,8 @@ local function Enable(self) if not self.colors.debuff then self.colors.debuff = {} - for debuffType, color in next, DebuffTypeColor do - self.colors.debuff[debuffType] = { color.r, color.g, color.b } + for debuffType, color in next, oUF.colors.debuff do + self.colors.debuff[debuffType] = color end end diff --git a/oUF_Dispellable.toc b/oUF_Dispellable.toc index ab99a5f..d11bee2 100644 --- a/oUF_Dispellable.toc +++ b/oUF_Dispellable.toc @@ -1,4 +1,4 @@ -## Interface: 90200 +## Interface: 100005 ## Title: oUF_Dispellable ## Notes: oUF element for highlighting debuffs that are dispellable by the player ## Author: Rainrider