9fb47ba - Add incoming ability glow and fix periodic aura update
[wowui.git] / kehys / updater.lua
1 -- updater.lua
2 -- 2019 Aleksi Blinnikka
3 --
4 -- Main update function for all frames. Gets around issues with events.
5 local _, addon = ...;
6 local unpack = unpack;
7 local min = math.min;
8 local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed;
9 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
10 local UnitIsAFK, UnitIsDND = UnitIsAFK, UnitIsDND;
11 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
12 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
13 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
14
15 local dispelcolor = addon.Colors.OverlayColorDispel;
16 local charmcolor = addon.Colors.OverlayColorCharm;
17 local majorcolor = addon.Colors.OverlayColorAlert;
18 local healcolor = addon.Colors.OverlayColorHeal;
19
20 local ignoredAuras = {
21     [315176] = true, -- Grasping Tendrils
22 };
23
24 function addon.FrameUpdate(frame)
25     assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
26
27     local unit = frame.displayed;
28     local width = frame.barwidth;
29     -- range check (doesn't have an event)
30     local inrange, checked = UnitInRange(unit);
31     if checked and not inrange then
32         frame:SetAlpha(0.55);
33     else
34         frame:SetAlpha(1);
35     end
36     -- states
37     if UnitIsDeadOrGhost(unit) then
38         frame.text:SetText("Dead");
39         if not frame.text:IsShown() then frame.text:Show() end
40         if frame.health:IsShown() then frame.health:Hide() end
41         if frame.shield:IsShown() then frame.shield:Hide() end
42         if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
43         if frame.healpred:IsShown() then frame.healpred:Hide() end
44         if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
45         frame.prev.health = nil;
46         frame.prev.hmax = nil;
47     elseif not UnitIsConnected(unit) then
48         frame.text:SetText("DC");
49         if not frame.text:IsShown() then frame.text:Show() end
50         if frame.health:IsShown() then frame.health:Hide() end
51         if frame.shield:IsShown() then frame.shield:Hide() end
52         if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
53         if frame.healpred:IsShown() then frame.healpred:Hide() end
54         if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
55         frame.prev.health = nil;
56         frame.prev.hmax = nil;
57     else
58         if UnitIsAFK(unit) then
59             frame.text:SetText("afk");
60             if not frame.text:IsShown() then frame.text:Show() end
61         elseif UnitIsDND(unit) then
62             frame.text:SetText("dnd");
63             if not frame.text:IsShown() then frame.text:Show() end
64         else
65             if frame.text:IsShown() then frame.text:Hide() end
66         end
67         -- health
68         local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
69         if frame.prev.health ~= current or frame.prev.hmax ~= hmax then
70             frame.prev.health = current;
71             frame.prev.hmax = hmax;
72             if hmax < current or hmax <= 1 then
73                 frame.health:SetWidth(width);
74                 frame.health.width = width;
75                 if not frame.health:IsShown() then frame.health:Show() end
76             elseif current <= 0 then
77                 if frame.health:IsShown() then frame.health:Hide() end
78             else
79                 local w = current/hmax*width;
80                 frame.health:SetWidth(w);
81                 frame.health.width = w;
82                 if not frame.health:IsShown() then frame.health:Show() end
83             end
84         end
85         -- shield
86         local hwidth = frame.health.width;
87         current = UnitGetTotalAbsorbs(unit) or 0;
88         if current > 0 then
89             local space = width - hwidth;
90             current = (current / hmax) * width;
91             if space == 0 then
92                 if frame.shield:IsShown() then frame.shield:Hide() end
93                 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
94             elseif space < current then
95                 frame.shield:SetWidth(space);
96                 if not frame.shield:IsShown() then frame.shield:Show() end
97                 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
98             else
99                 frame.shield:SetWidth(current);
100                 if not frame.shield:IsShown() then frame.shield:Show() end
101                 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
102             end
103         else
104             if frame.shield:IsShown() then frame.shield:Hide() end
105             if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
106         end
107         -- heal absorb
108         current = UnitGetTotalHealAbsorbs(unit) or 0;
109         if current > 0 then
110             current = (current / hmax) * width;
111             frame.healabsorb:SetWidth(min(hwidth, current));
112             if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end
113         elseif frame.healabsorb:IsShown() then
114             frame.healabsorb:Hide();
115         end
116         -- heal prediction
117         current = UnitGetIncomingHeals(unit) or 0;
118         if current > 0 then
119             current = (current / hmax) * width;
120             -- at least 1 pixel prediction shown
121             frame.healpred:SetWidth(min(width - hwidth + 1, current));
122             if not frame.healpred:IsShown() then frame.healpred:Show() end
123         elseif frame.healpred:IsShown() then
124             frame.healpred:Hide();
125         end
126         frame.rounds = frame.rounds + 1;
127         if (frame.rounds > 7) then
128             frame.tankcd = {};
129             frame.alert = {};
130             frame.stacks = {};
131             frame.heal = {};
132             frame.buff1 = {};
133             addon.SetAuras(frame.unit, frame.guid);
134             frame.rounds = 0;
135         end
136         -- tank CD marker
137         if next(frame.tankcd) then
138             if not frame.defensive:IsShown() then frame.defensive:Show() end
139         elseif frame.defensive:IsShown() then
140             frame.defensive:Hide();
141         end
142         -- aura stacks
143         if next(frame.stacks) then
144             local _, amount = next(frame.stacks);
145             frame.stack:SetText(amount);
146             if not frame.stack:IsShown() then frame.stack:Show() end
147         elseif frame.stack:IsShown() then
148             frame.stack:Hide();
149         end
150         -- custom buff indicator 1
151         if next(frame.buff1) then
152             if not frame.buffind1:IsShown() then frame.buffind1:Show() end
153         elseif frame.buffind1:IsShown() then
154             frame.buffind1:Hide();
155         end
156         -- incoming ability
157         if next(frame.incoming) then
158             if not frame.glow:IsShown() then frame.glow:Show() end
159         elseif frame.glow:IsShown() then
160             frame.glow:Hide();
161         end
162         -- overlays
163         if next(frame.alert) then
164             -- major
165             if frame.overlay.color ~= majorcolor then
166                 frame.overlay:SetVertexColor(unpack(majorcolor));
167                 frame.overlay.color = majorcolor;
168                 if not frame.overlay:IsShown() then frame.overlay:Show() end
169             end
170         else
171             local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
172             if UnitIsCharmed(unit) and frame.unit == frame.displayed then
173                 -- charmed
174                 if frame.overlay.color ~= charmcolor then
175                     frame.overlay:SetVertexColor(unpack(charmcolor));
176                     frame.overlay.color = charmcolor;
177                     if not frame.overlay:IsShown() then frame.overlay:Show() end
178                 end
179             elseif spellid ~= nil and not ignoredAuras[spellid] then
180                 -- dispellable
181                 if frame.overlay.color ~= dispelcolor then
182                     frame.overlay:SetVertexColor(unpack(dispelcolor));
183                     frame.overlay.color = dispelcolor;
184                     if not frame.overlay:IsShown() then frame.overlay:Show() end
185                 end
186             elseif next(frame.heal) then
187                 -- major heals needed
188                 if frame.overlay.color ~= healcolor then
189                     frame.overlay:SetVertexColor(unpack(healcolor));
190                     frame.overlay.color = healcolor;
191                     if not frame.overlay:IsShown() then frame.overlay:Show() end
192                 end
193             else
194                 if frame.overlay.color ~= nil then
195                     frame.overlay.color = nil;
196                     if frame.overlay:IsShown() then frame.overlay:Hide() end
197                 end
198             end
199         end
200     end
201 end