2 -- 2019 Aleksi Blinnikka
4 -- Main update function for all frames. Gets around issues with events.
8 local format = string.format;
9 local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed;
10 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
11 local UnitPower, UnitPowerMax = UnitPower, UnitPowerMax;
12 local UnitIsAFK, UnitIsDND = UnitIsAFK, UnitIsDND;
13 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
14 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
15 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
16 local InCombatLockdown, IsResting = InCombatLockdown, IsResting;
18 local dispelcolor = addon.Colors.OverlayColorDispel;
19 local charmcolor = addon.Colors.OverlayColorCharm;
20 local majorcolor = addon.Colors.OverlayColorAlert;
21 local healcolor = addon.Colors.OverlayColorHeal;
23 local ignoredAuras = {
24 [315176] = true, -- Grasping Tendrils
28 [Enum.PowerType.Mana] = {0.1, 0.5, 0.9},
29 [Enum.PowerType.Rage] = {1, 0, 0},
30 [Enum.PowerType.Focus] = {1, 0.5, 0},
31 [Enum.PowerType.Energy] = {1, 0.8, 0},
32 [Enum.PowerType.RunicPower] = {0.8, 0, 0.2},
35 function addon.FrameUpdate(frame)
36 assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
38 local unit = frame.displayed;
39 local width = frame.barwidth;
40 -- range check (doesn't have an event) frames can be marked constantly visible
41 if not frame.constant then
42 local inrange, checked = UnitInRange(unit);
43 if checked and not inrange then
50 if UnitIsDeadOrGhost(unit) then
51 frame.text:SetText("Dead");
52 if not frame.text:IsShown() then frame.text:Show() end
53 if frame.health:IsShown() then frame.health:Hide() end
54 if frame.shield:IsShown() then frame.shield:Hide() end
55 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
56 if frame.healpred:IsShown() then frame.healpred:Hide() end
57 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
58 frame.prev.health = nil;
59 frame.prev.hmax = nil;
60 elseif not UnitIsConnected(unit) then
61 frame.text:SetText("DC");
62 if not frame.text:IsShown() then frame.text:Show() end
63 if frame.health:IsShown() then frame.health:Hide() end
64 if frame.shield:IsShown() then frame.shield:Hide() end
65 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
66 if frame.healpred:IsShown() then frame.healpred:Hide() end
67 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
68 frame.prev.health = nil;
69 frame.prev.hmax = nil;
71 if UnitIsAFK(unit) then
72 frame.text.status = true;
73 frame.text:SetText("afk");
74 if not frame.text:IsShown() then frame.text:Show() end
75 elseif UnitIsDND(unit) then
76 frame.text.status = true;
77 frame.text:SetText("dnd");
78 if not frame.text:IsShown() then frame.text:Show() end
80 frame.text.status = false;
81 if not (frame.nonraid and frame.unit == "target") and frame.text:IsShown() then
85 if frame.nonraid and frame.unit == "player" then
86 if InCombatLockdown() then
87 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
89 elseif IsResting() then
90 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
92 elseif frame.status:IsShown() then
96 -- TODO incoming res, maybe just with events?
98 local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
99 if frame.prev.health ~= current or frame.prev.hmax ~= hmax then
100 if frame.nonraid and frame.unit == "target" and frame.prev.htext ~= current then
101 frame.prev.htext = current;
102 if current > 1000000000 then -- 1.0B
103 frame.text:SetFormattedText("%.2fB", current / 1000000000);
104 elseif current > 1000000 then -- 1.0M
105 frame.text:SetFormattedText("%.2fM", current / 1000000);
106 elseif current > 1000 then -- 1.0K
107 frame.text:SetFormattedText("%.1fK", current / 1000);
109 if not frame.text:IsShown() then frame.text:Show() end
111 frame.prev.health = current;
112 frame.prev.hmax = hmax;
113 if hmax < current or hmax <= 1 then
114 frame.health:SetWidth(width);
115 frame.health.width = width;
116 if not frame.health:IsShown() then frame.health:Show() end
117 elseif current <= 0 then
118 if frame.health:IsShown() then frame.health:Hide() end
120 local w = current/hmax*width;
121 frame.health:SetWidth(w);
122 frame.health.width = w;
123 if not frame.health:IsShown() then frame.health:Show() end
127 local hwidth = frame.health.width;
128 current = UnitGetTotalAbsorbs(unit) or 0;
130 local space = width - hwidth;
131 current = (current / hmax) * width;
133 if frame.shield:IsShown() then frame.shield:Hide() end
134 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
135 elseif space < current then
136 frame.shield:SetWidth(space);
137 if not frame.shield:IsShown() then frame.shield:Show() end
138 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
140 frame.shield:SetWidth(current);
141 if not frame.shield:IsShown() then frame.shield:Show() end
142 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
145 if frame.shield:IsShown() then frame.shield:Hide() end
146 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
149 current = UnitGetTotalHealAbsorbs(unit) or 0;
151 current = (current / hmax) * width;
152 frame.healabsorb:SetWidth(min(hwidth, current));
153 if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end
154 elseif frame.healabsorb:IsShown() then
155 frame.healabsorb:Hide();
158 current = UnitGetIncomingHeals(unit) or 0;
160 current = (current / hmax) * width;
161 -- at least 1 pixel prediction shown
162 frame.healpred:SetWidth(min(width - hwidth + 1, current));
163 if not frame.healpred:IsShown() then frame.healpred:Show() end
164 elseif frame.healpred:IsShown() then
165 frame.healpred:Hide();
168 if frame.mana ~= nil then
169 local current, max = UnitPower(unit), UnitPowerMax(unit);
170 local ptype = UnitPowerType(unit);
171 if frame.mana.ptype ~= ptype then
172 frame.mana.ptype = ptype;
173 frame.mana:SetVertexColor(unpack(powerColors[ptype]));
175 if frame.prev.mana ~= current or frame.prev.mmax ~= max then
176 frame.prev.mana = current;
177 frame.prev.mmax = max;
178 if max < current or max <= 1 then
179 frame.mana:SetWidth(width);
180 frame.manatext:SetText("100");
181 if not frame.mana:IsShown() then frame.mana:Show() end
182 if not frame.manatext:IsShown() then frame.manatext:Show() end
183 elseif current <= 0 then
184 if frame.mana:IsShown() then frame.mana:Hide() end
185 if frame.manatext:IsShown() then frame.manatext:Hide() end
187 local percent = current/max;
188 frame.mana:SetWidth(percent*width);
189 frame.manatext:SetText(format("%d", percent*100+0.5));
190 if not frame.mana:IsShown() then frame.mana:Show() end
191 if not frame.manatext:IsShown() then frame.manatext:Show() end
195 -- forced aura updates
196 if frame.rounds ~= nil then
197 frame.rounds = frame.rounds + 1;
198 if (frame.rounds > 7) then
204 addon.SetAuras(frame.unit, frame.guid);
208 if not frame.nonraid then
210 if next(frame.tankcd) then
211 if not frame.defensive:IsShown() then frame.defensive:Show() end
212 elseif frame.defensive:IsShown() then
213 frame.defensive:Hide();
216 if next(frame.stacks) then
217 local _, amount = next(frame.stacks);
218 frame.stack:SetText(amount);
219 if not frame.stack:IsShown() then frame.stack:Show() end
220 elseif frame.stack:IsShown() then
223 -- custom buff indicator 1
224 if next(frame.buff1) then
225 if not frame.buffind1:IsShown() then frame.buffind1:Show() end
226 elseif frame.buffind1:IsShown() then
227 frame.buffind1:Hide();
229 -- custom buff indicator 2
230 if next(frame.buff2) then
231 if not frame.buffind2:IsShown() then frame.buffind2:Show() end
232 elseif frame.buffind2:IsShown() then
233 frame.buffind2:Hide();
236 if next(frame.incoming) then
237 if not frame.glow:IsShown() then frame.glow:Show() end
238 elseif frame.glow:IsShown() then
242 if next(frame.alert) then
244 if frame.overlay.color ~= majorcolor then
245 frame.overlay:SetVertexColor(unpack(majorcolor));
246 frame.overlay.color = majorcolor;
247 if not frame.overlay:IsShown() then frame.overlay:Show() end
250 local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
251 if UnitIsCharmed(unit) and frame.unit == frame.displayed then
253 if frame.overlay.color ~= charmcolor then
254 frame.overlay:SetVertexColor(unpack(charmcolor));
255 frame.overlay.color = charmcolor;
256 if not frame.overlay:IsShown() then frame.overlay:Show() end
258 elseif spellid ~= nil and not ignoredAuras[spellid] then
260 if frame.overlay.color ~= dispelcolor then
261 frame.overlay:SetVertexColor(unpack(dispelcolor));
262 frame.overlay.color = dispelcolor;
263 if not frame.overlay:IsShown() then frame.overlay:Show() end
265 elseif next(frame.heal) then
266 -- major heals needed
267 if frame.overlay.color ~= healcolor then
268 frame.overlay:SetVertexColor(unpack(healcolor));
269 frame.overlay.color = healcolor;
270 if not frame.overlay:IsShown() then frame.overlay:Show() end
273 if frame.overlay.color ~= nil then
274 frame.overlay.color = nil;
275 if frame.overlay:IsShown() then frame.overlay:Hide() end