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