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;
17 local UnitInRange, UnitInPhase = UnitInRange, UnitInPhase;
19 local dispelcolor = addon.Colors.OverlayColorDispel;
20 local charmcolor = addon.Colors.OverlayColorCharm;
21 local majorcolor = addon.Colors.OverlayColorAlert;
22 local healcolor = addon.Colors.OverlayColorHeal;
24 local ignoredAuras = {
25 [315176] = true, -- Grasping Tendrils
26 [313759] = true, -- Cursed Blood (Il'gynoth)
27 [312486] = true, -- Recurring Nightmare (Il'gynoth)
31 [Enum.PowerType.Mana] = {0.1, 0.5, 0.9},
32 [Enum.PowerType.Rage] = {1, 0, 0},
33 [Enum.PowerType.Pain] = {1, 0, 0},
34 [Enum.PowerType.Focus] = {1, 0.5, 0},
35 [Enum.PowerType.Energy] = {1, 0.8, 0},
36 [Enum.PowerType.Fury] = {0.8, 0.3, 0.9},
37 [Enum.PowerType.RunicPower] = {0.8, 0, 0.2},
38 [Enum.PowerType.LunarPower] = {0.3, 0.5, 0.9},
39 [Enum.PowerType.Maelstrom] = {0, 0.5, 1},
40 [Enum.PowerType.Insanity] = {0.4, 0, 0.8},
43 function addon.FrameUpdate(frame)
44 assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
46 local unit = frame.displayed;
47 local width = frame.barwidth;
48 -- range check (doesn't have an event) frames can be marked constantly visible
49 if not frame.constant then
50 local inrange, checked = UnitInRange(unit);
51 local inphase = UnitPhaseReason(unit);
52 if (checked and not inrange) or inphase then
59 if UnitIsDeadOrGhost(unit) then
60 frame.text:SetText("Dead");
61 if not frame.text:IsShown() then frame.text:Show() end
62 if frame.health:IsShown() then frame.health:Hide() end
63 if frame.shield:IsShown() then frame.shield:Hide() end
64 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
65 if frame.healpred:IsShown() then frame.healpred:Hide() end
66 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
67 frame.prev.health = nil;
68 frame.prev.hmax = nil;
69 elseif not UnitIsConnected(unit) then
70 frame.text:SetText("DC");
71 if not frame.text:IsShown() then frame.text:Show() end
72 if frame.health:IsShown() then frame.health:Hide() end
73 if frame.shield:IsShown() then frame.shield:Hide() end
74 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
75 if frame.healpred:IsShown() then frame.healpred:Hide() end
76 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
77 frame.prev.health = nil;
78 frame.prev.hmax = nil;
80 if UnitIsAFK(unit) then
81 frame.text.status = true;
82 frame.prev.htext = nil;
83 frame.text:SetText("afk");
84 if not frame.text:IsShown() then frame.text:Show() end
85 elseif UnitIsDND(unit) then
86 frame.text.status = true;
87 frame.prev.htext = nil;
88 frame.text:SetText("dnd");
89 if not frame.text:IsShown() then frame.text:Show() end
91 frame.text.status = false;
92 if frame.raid and frame.text:IsShown() then
96 if not frame.raid and frame.unit == "player" then
97 if InCombatLockdown() then
98 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
100 elseif IsResting() then
101 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
103 elseif frame.status:IsShown() then
108 local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
109 if frame.prev.health ~= current or frame.prev.hmax ~= hmax then
110 frame.prev.health = current;
111 frame.prev.hmax = hmax;
112 if hmax < current or hmax <= 1 then
113 frame.health:SetWidth(width);
114 frame.health.width = width;
115 if not frame.health:IsShown() then frame.health:Show() end
116 elseif current <= 0 then
117 if frame.health:IsShown() then frame.health:Hide() end
119 local w = current/hmax*width;
120 frame.health:SetWidth(w);
121 frame.health.width = w;
122 if not frame.health:IsShown() then frame.health:Show() end
126 if not frame.raid and not frame.text.status and frame.prev.htext ~= current then
127 frame.prev.htext = current;
129 if hmax < current or hmax <= 1 then
130 frame.text:SetText("100");
131 if not frame.text:IsShown() then frame.text:Show() end
132 elseif current <= 0 then
133 if frame.text:IsShown() then frame.text:Hide() end
135 frame.text:SetFormattedText("%.1f", current/hmax*100);
136 if not frame.text:IsShown() then frame.text:Show() end
139 if current > 1000000000 then -- 1.0B
140 frame.text:SetFormattedText("%.2fB", current / 1000000000);
141 elseif current > 1000000 then -- 1.0M
142 frame.text:SetFormattedText("%.2fM", current / 1000000);
143 elseif current > 1000 then -- 1.0K
144 frame.text:SetFormattedText("%.1fK", current / 1000);
146 frame.text:SetFormattedText("%i", current);
148 if not frame.text:IsShown() then frame.text:Show() end
152 local hwidth = frame.health.width;
153 current = UnitGetTotalAbsorbs(unit) or 0;
155 local space = width - hwidth;
156 current = (current / hmax) * width;
158 if frame.shield:IsShown() then frame.shield:Hide() end
159 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
160 elseif space < current then
161 frame.shield:SetWidth(space);
162 if not frame.shield:IsShown() then frame.shield:Show() end
163 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
165 frame.shield:SetWidth(current);
166 if not frame.shield:IsShown() then frame.shield:Show() end
167 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
170 if frame.shield:IsShown() then frame.shield:Hide() end
171 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
174 current = UnitGetTotalHealAbsorbs(unit) or 0;
176 current = (current / hmax) * width;
177 frame.healabsorb:SetWidth(min(hwidth, current));
178 if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end
179 elseif frame.healabsorb:IsShown() then
180 frame.healabsorb:Hide();
183 current = UnitGetIncomingHeals(unit) or 0;
185 current = (current / hmax) * width;
186 -- at least 1 pixel prediction shown
187 frame.healpred:SetWidth(min(width - hwidth + 1, current));
188 if not frame.healpred:IsShown() then frame.healpred:Show() end
189 elseif frame.healpred:IsShown() then
190 frame.healpred:Hide();
193 if frame.mana ~= nil then
194 local current, max = UnitPower(unit), UnitPowerMax(unit);
195 local ptype = UnitPowerType(unit);
196 if frame.mana.ptype ~= ptype then
197 frame.mana.ptype = ptype;
198 frame.mana:SetVertexColor(unpack(powerColors[ptype]));
200 if frame.prev.mana ~= current or frame.prev.mmax ~= max then
201 frame.prev.mana = current;
202 frame.prev.mmax = max;
204 if frame.mana:IsShown() then frame.mana:Hide() end
205 if frame.manatext:IsShown() then frame.manatext:Hide() end
206 elseif max < current then
207 frame.mana:SetWidth(width);
208 frame.manatext:SetText("100");
209 if not frame.mana:IsShown() then frame.mana:Show() end
210 if not frame.manatext:IsShown() then frame.manatext:Show() end
211 elseif current <= 0 then
212 if frame.mana:IsShown() then frame.mana:Hide() end
213 if frame.manatext:IsShown() then frame.manatext:Hide() end
215 local percent = current/max;
216 frame.mana:SetWidth(percent*width);
217 frame.manatext:SetText(format("%d", percent*100+0.5));
218 if not frame.mana:IsShown() then frame.mana:Show() end
219 if not frame.manatext:IsShown() then frame.manatext:Show() end
223 -- forced aura updates
224 if frame.rounds ~= nil then
225 frame.rounds = frame.rounds + 1;
226 if (frame.rounds > 7) then
233 addon.SetAuras(frame.unit, frame.guid);
239 if next(frame.tankcd) then
240 if not frame.defensive:IsShown() then frame.defensive:Show() end
241 elseif frame.defensive:IsShown() then
242 frame.defensive:Hide();
245 if next(frame.stacks) then
246 local _, amount = next(frame.stacks);
247 frame.stack:SetText(amount);
248 if not frame.stack:IsShown() then frame.stack:Show() end
249 elseif frame.stack:IsShown() then
252 -- custom buff indicator 1
253 if next(frame.buff1) then
254 if not frame.buffind1:IsShown() then frame.buffind1:Show() end
255 elseif frame.buffind1:IsShown() then
256 frame.buffind1:Hide();
258 -- custom buff indicator 2
259 if next(frame.buff2) then
260 if not frame.buffind2:IsShown() then frame.buffind2:Show() end
261 elseif frame.buffind2:IsShown() then
262 frame.buffind2:Hide();
265 if next(frame.incoming) then
266 if not frame.glow:IsShown() then frame.glow:Show() end
267 elseif frame.glow:IsShown() then
271 if next(frame.alert) then
273 if frame.overlay.color ~= majorcolor then
274 frame.overlay:SetVertexColor(unpack(majorcolor));
275 frame.overlay.color = majorcolor;
276 if not frame.overlay:IsShown() then frame.overlay:Show() end
279 local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
280 if UnitIsCharmed(unit) and frame.unit == frame.displayed then
282 if frame.overlay.color ~= charmcolor then
283 frame.overlay:SetVertexColor(unpack(charmcolor));
284 frame.overlay.color = charmcolor;
285 if not frame.overlay:IsShown() then frame.overlay:Show() end
287 elseif spellid ~= nil and not ignoredAuras[spellid] then
289 if frame.overlay.color ~= dispelcolor then
290 frame.overlay:SetVertexColor(unpack(dispelcolor));
291 frame.overlay.color = dispelcolor;
292 if not frame.overlay:IsShown() then frame.overlay:Show() end
294 elseif next(frame.heal) then
295 -- major heals needed
296 if frame.overlay.color ~= healcolor then
297 frame.overlay:SetVertexColor(unpack(healcolor));
298 frame.overlay.color = healcolor;
299 if not frame.overlay:IsShown() then frame.overlay:Show() end
302 if frame.overlay.color ~= nil then
303 frame.overlay.color = nil;
304 if frame.overlay:IsShown() then frame.overlay:Hide() end