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