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
29 [Enum.PowerType.Mana] = {0.1, 0.5, 0.9},
30 [Enum.PowerType.Rage] = {1, 0, 0},
31 [Enum.PowerType.Pain] = {1, 0, 0},
32 [Enum.PowerType.Focus] = {1, 0.5, 0},
33 [Enum.PowerType.Energy] = {1, 0.8, 0},
34 [Enum.PowerType.Fury] = {0.8, 0.3, 0.9},
35 [Enum.PowerType.RunicPower] = {0.8, 0, 0.2},
36 [Enum.PowerType.LunarPower] = {0.3, 0.5, 0.9},
37 [Enum.PowerType.Maelstrom] = {0, 0.5, 1},
38 [Enum.PowerType.Insanity] = {0.4, 0, 0.8},
41 function addon.FrameUpdate(frame)
42 assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
44 local unit = frame.displayed;
45 local width = frame.barwidth;
46 -- range check (doesn't have an event) frames can be marked constantly visible
47 if not frame.constant then
48 local inrange, checked = UnitInRange(unit);
49 local inphase = UnitInPhase(unit);
50 if (checked and not inrange) or not inphase then
57 if UnitIsDeadOrGhost(unit) then
58 frame.text:SetText("Dead");
59 if not frame.text:IsShown() then frame.text:Show() end
60 if frame.health:IsShown() then frame.health:Hide() end
61 if frame.shield:IsShown() then frame.shield:Hide() end
62 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
63 if frame.healpred:IsShown() then frame.healpred:Hide() end
64 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
65 frame.prev.health = nil;
66 frame.prev.hmax = nil;
67 elseif not UnitIsConnected(unit) then
68 frame.text:SetText("DC");
69 if not frame.text:IsShown() then frame.text:Show() end
70 if frame.health:IsShown() then frame.health:Hide() end
71 if frame.shield:IsShown() then frame.shield:Hide() end
72 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
73 if frame.healpred:IsShown() then frame.healpred:Hide() end
74 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
75 frame.prev.health = nil;
76 frame.prev.hmax = nil;
78 if UnitIsAFK(unit) then
79 frame.text.status = true;
80 frame.prev.htext = nil;
81 frame.text:SetText("afk");
82 if not frame.text:IsShown() then frame.text:Show() end
83 elseif UnitIsDND(unit) then
84 frame.text.status = true;
85 frame.prev.htext = nil;
86 frame.text:SetText("dnd");
87 if not frame.text:IsShown() then frame.text:Show() end
89 frame.text.status = false;
90 if frame.raid and frame.text:IsShown() then
94 if not frame.raid and frame.unit == "player" then
95 if InCombatLockdown() then
96 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
98 elseif IsResting() then
99 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
101 elseif frame.status:IsShown() then
106 local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
107 if frame.prev.health ~= current or frame.prev.hmax ~= hmax then
108 frame.prev.health = current;
109 frame.prev.hmax = hmax;
110 if hmax < current or hmax <= 1 then
111 frame.health:SetWidth(width);
112 frame.health.width = width;
113 if not frame.health:IsShown() then frame.health:Show() end
114 elseif current <= 0 then
115 if frame.health:IsShown() then frame.health:Hide() end
117 local w = current/hmax*width;
118 frame.health:SetWidth(w);
119 frame.health.width = w;
120 if not frame.health:IsShown() then frame.health:Show() end
124 if not frame.raid and not frame.text.status and frame.prev.htext ~= current then
125 frame.prev.htext = current;
127 if hmax < current or hmax <= 1 then
128 frame.text:SetText("100");
129 if not frame.text:IsShown() then frame.text:Show() end
130 elseif current <= 0 then
131 if frame.text:IsShown() then frame.text:Hide() end
133 frame.text:SetFormattedText("%.1f", current/hmax*100);
134 if not frame.text:IsShown() then frame.text:Show() end
137 if current > 1000000000 then -- 1.0B
138 frame.text:SetFormattedText("%.2fB", current / 1000000000);
139 elseif current > 1000000 then -- 1.0M
140 frame.text:SetFormattedText("%.2fM", current / 1000000);
141 elseif current > 1000 then -- 1.0K
142 frame.text:SetFormattedText("%.1fK", current / 1000);
144 if not frame.text:IsShown() then frame.text:Show() end
148 local hwidth = frame.health.width;
149 current = UnitGetTotalAbsorbs(unit) or 0;
151 local space = width - hwidth;
152 current = (current / hmax) * width;
154 if frame.shield:IsShown() then frame.shield:Hide() end
155 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
156 elseif space < current then
157 frame.shield:SetWidth(space);
158 if not frame.shield:IsShown() then frame.shield:Show() end
159 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
161 frame.shield:SetWidth(current);
162 if not frame.shield:IsShown() then frame.shield:Show() end
163 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
166 if frame.shield:IsShown() then frame.shield:Hide() end
167 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
170 current = UnitGetTotalHealAbsorbs(unit) or 0;
172 current = (current / hmax) * width;
173 frame.healabsorb:SetWidth(min(hwidth, current));
174 if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end
175 elseif frame.healabsorb:IsShown() then
176 frame.healabsorb:Hide();
179 current = UnitGetIncomingHeals(unit) or 0;
181 current = (current / hmax) * width;
182 -- at least 1 pixel prediction shown
183 frame.healpred:SetWidth(min(width - hwidth + 1, current));
184 if not frame.healpred:IsShown() then frame.healpred:Show() end
185 elseif frame.healpred:IsShown() then
186 frame.healpred:Hide();
189 if frame.mana ~= nil then
190 local current, max = UnitPower(unit), UnitPowerMax(unit);
191 local ptype = UnitPowerType(unit);
192 if frame.mana.ptype ~= ptype then
193 frame.mana.ptype = ptype;
194 frame.mana:SetVertexColor(unpack(powerColors[ptype]));
196 if frame.prev.mana ~= current or frame.prev.mmax ~= max then
197 frame.prev.mana = current;
198 frame.prev.mmax = max;
200 if frame.mana:IsShown() then frame.mana:Hide() end
201 if frame.manatext:IsShown() then frame.manatext:Hide() end
202 elseif max < current then
203 frame.mana:SetWidth(width);
204 frame.manatext:SetText("100");
205 if not frame.mana:IsShown() then frame.mana:Show() end
206 if not frame.manatext:IsShown() then frame.manatext:Show() end
207 elseif current <= 0 then
208 if frame.mana:IsShown() then frame.mana:Hide() end
209 if frame.manatext:IsShown() then frame.manatext:Hide() end
211 local percent = current/max;
212 frame.mana:SetWidth(percent*width);
213 frame.manatext:SetText(format("%d", percent*100+0.5));
214 if not frame.mana:IsShown() then frame.mana:Show() end
215 if not frame.manatext:IsShown() then frame.manatext:Show() end
219 -- forced aura updates
220 if frame.rounds ~= nil then
221 frame.rounds = frame.rounds + 1;
222 if (frame.rounds > 7) then
228 addon.SetAuras(frame.unit, frame.guid);
234 if next(frame.tankcd) then
235 if not frame.defensive:IsShown() then frame.defensive:Show() end
236 elseif frame.defensive:IsShown() then
237 frame.defensive:Hide();
240 if next(frame.stacks) then
241 local _, amount = next(frame.stacks);
242 frame.stack:SetText(amount);
243 if not frame.stack:IsShown() then frame.stack:Show() end
244 elseif frame.stack:IsShown() then
247 -- custom buff indicator 1
248 if next(frame.buff1) then
249 if not frame.buffind1:IsShown() then frame.buffind1:Show() end
250 elseif frame.buffind1:IsShown() then
251 frame.buffind1:Hide();
253 -- custom buff indicator 2
254 if next(frame.buff2) then
255 if not frame.buffind2:IsShown() then frame.buffind2:Show() end
256 elseif frame.buffind2:IsShown() then
257 frame.buffind2:Hide();
260 if next(frame.incoming) then
261 if not frame.glow:IsShown() then frame.glow:Show() end
262 elseif frame.glow:IsShown() then
266 if next(frame.alert) then
268 if frame.overlay.color ~= majorcolor then
269 frame.overlay:SetVertexColor(unpack(majorcolor));
270 frame.overlay.color = majorcolor;
271 if not frame.overlay:IsShown() then frame.overlay:Show() end
274 local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
275 if UnitIsCharmed(unit) and frame.unit == frame.displayed then
277 if frame.overlay.color ~= charmcolor then
278 frame.overlay:SetVertexColor(unpack(charmcolor));
279 frame.overlay.color = charmcolor;
280 if not frame.overlay:IsShown() then frame.overlay:Show() end
282 elseif spellid ~= nil and not ignoredAuras[spellid] then
284 if frame.overlay.color ~= dispelcolor then
285 frame.overlay:SetVertexColor(unpack(dispelcolor));
286 frame.overlay.color = dispelcolor;
287 if not frame.overlay:IsShown() then frame.overlay:Show() end
289 elseif next(frame.heal) then
290 -- major heals needed
291 if frame.overlay.color ~= healcolor then
292 frame.overlay:SetVertexColor(unpack(healcolor));
293 frame.overlay.color = healcolor;
294 if not frame.overlay:IsShown() then frame.overlay:Show() end
297 if frame.overlay.color ~= nil then
298 frame.overlay.color = nil;
299 if frame.overlay:IsShown() then frame.overlay:Hide() end