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 IsResting = 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
27 function addon.FrameUpdate(frame)
28 assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
30 local unit = frame.displayed;
31 local width = frame.barwidth;
32 -- range check (doesn't have an event) frames can be marked constantly visible
33 if not frame.constant then
34 local inrange, checked = UnitInRange(unit);
35 if checked and not inrange then
42 if UnitIsDeadOrGhost(unit) then
43 frame.text:SetText("Dead");
44 if not frame.text:IsShown() then frame.text:Show() end
45 if frame.health:IsShown() then frame.health:Hide() end
46 if frame.shield:IsShown() then frame.shield:Hide() end
47 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
48 if frame.healpred:IsShown() then frame.healpred:Hide() end
49 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
50 frame.prev.health = nil;
51 frame.prev.hmax = nil;
52 elseif not UnitIsConnected(unit) then
53 frame.text:SetText("DC");
54 if not frame.text:IsShown() then frame.text:Show() end
55 if frame.health:IsShown() then frame.health:Hide() end
56 if frame.shield:IsShown() then frame.shield:Hide() end
57 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
58 if frame.healpred:IsShown() then frame.healpred:Hide() end
59 if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
60 frame.prev.health = nil;
61 frame.prev.hmax = nil;
63 if UnitIsAFK(unit) then
64 frame.text:SetText("afk");
65 if not frame.text:IsShown() then frame.text:Show() end
66 elseif UnitIsDND(unit) then
67 frame.text:SetText("dnd");
68 if not frame.text:IsShown() then frame.text:Show() end
69 elseif frame.nonraid and frame.unit == "player" and IsResting() then
70 frame.text:SetText("zzz");
71 if not frame.text:IsShown() then frame.text:Show() end
73 if frame.text:IsShown() then frame.text:Hide() end
75 -- TODO incoming res, maybe just with events?
77 local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
78 if frame.prev.health ~= current or frame.prev.hmax ~= hmax then
79 frame.prev.health = current;
80 frame.prev.hmax = hmax;
81 if hmax < current or hmax <= 1 then
82 frame.health:SetWidth(width);
83 frame.health.width = width;
84 if not frame.health:IsShown() then frame.health:Show() end
85 elseif current <= 0 then
86 if frame.health:IsShown() then frame.health:Hide() end
88 local w = current/hmax*width;
89 frame.health:SetWidth(w);
90 frame.health.width = w;
91 if not frame.health:IsShown() then frame.health:Show() end
95 local hwidth = frame.health.width;
96 current = UnitGetTotalAbsorbs(unit) or 0;
98 local space = width - hwidth;
99 current = (current / hmax) * width;
101 if frame.shield:IsShown() then frame.shield:Hide() end
102 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
103 elseif space < current then
104 frame.shield:SetWidth(space);
105 if not frame.shield:IsShown() then frame.shield:Show() end
106 if not frame.shieldhl:IsShown() then frame.shieldhl:Show() end
108 frame.shield:SetWidth(current);
109 if not frame.shield:IsShown() then frame.shield:Show() end
110 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
113 if frame.shield:IsShown() then frame.shield:Hide() end
114 if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
117 current = UnitGetTotalHealAbsorbs(unit) or 0;
119 current = (current / hmax) * width;
120 frame.healabsorb:SetWidth(min(hwidth, current));
121 if not frame.healabsorb:IsShown() then frame.healabsorb:Show() end
122 elseif frame.healabsorb:IsShown() then
123 frame.healabsorb:Hide();
126 current = UnitGetIncomingHeals(unit) or 0;
128 current = (current / hmax) * width;
129 -- at least 1 pixel prediction shown
130 frame.healpred:SetWidth(min(width - hwidth + 1, current));
131 if not frame.healpred:IsShown() then frame.healpred:Show() end
132 elseif frame.healpred:IsShown() then
133 frame.healpred:Hide();
136 if frame.mana ~= nil then
137 local current, max = UnitPower(unit), UnitPowerMax(unit);
138 if frame.prev.mana ~= current or frame.prev.mmax ~= max then
139 frame.prev.mana = current;
140 frame.prev.mmax = max;
141 if max < current or max <= 1 then
142 frame.mana:SetWidth(width);
143 frame.mana:SetText("100");
144 if not frame.mana:IsShown() then frame.mana:Show() end
145 if not frame.manatext:IsShown() then frame.manatext:Show() end
146 elseif current <= 0 then
147 if frame.mana:IsShown() then frame.mana:Hide() end
148 if frame.manatext:IsShown() then frame.manatext:Hide() end
150 local percent = current/max;
151 frame.mana:SetWidth(percent*width);
152 frame.manatext:SetText(format("%d", percent*100));
153 if not frame.mana:IsShown() then frame.mana:Show() end
154 if not frame.manatext:IsShown() then frame.manatext:Show() end
158 -- forced aura updates
159 if frame.rounds ~= nil then
160 frame.rounds = frame.rounds + 1;
161 if (frame.rounds > 7) then
167 addon.SetAuras(frame.unit, frame.guid);
172 if next(frame.tankcd) then
173 if not frame.defensive:IsShown() then frame.defensive:Show() end
174 elseif frame.defensive:IsShown() then
175 frame.defensive:Hide();
178 if next(frame.stacks) then
179 local _, amount = next(frame.stacks);
180 frame.stack:SetText(amount);
181 if not frame.stack:IsShown() then frame.stack:Show() end
182 elseif frame.stack:IsShown() then
185 -- custom buff indicator 1
186 if next(frame.buff1) then
187 if not frame.buffind1:IsShown() then frame.buffind1:Show() end
188 elseif frame.buffind1:IsShown() then
189 frame.buffind1:Hide();
192 if next(frame.incoming) then
193 if not frame.glow:IsShown() then frame.glow:Show() end
194 elseif frame.glow:IsShown() then
198 if next(frame.alert) then
200 if frame.overlay.color ~= majorcolor then
201 frame.overlay:SetVertexColor(unpack(majorcolor));
202 frame.overlay.color = majorcolor;
203 if not frame.overlay:IsShown() then frame.overlay:Show() end
205 elseif frame.overlay ~= nil then
206 local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
207 if UnitIsCharmed(unit) and frame.unit == frame.displayed then
209 if frame.overlay.color ~= charmcolor then
210 frame.overlay:SetVertexColor(unpack(charmcolor));
211 frame.overlay.color = charmcolor;
212 if not frame.overlay:IsShown() then frame.overlay:Show() end
214 elseif spellid ~= nil and not ignoredAuras[spellid] then
216 if frame.overlay.color ~= dispelcolor then
217 frame.overlay:SetVertexColor(unpack(dispelcolor));
218 frame.overlay.color = dispelcolor;
219 if not frame.overlay:IsShown() then frame.overlay:Show() end
221 elseif next(frame.heal) then
222 -- major heals needed
223 if frame.overlay.color ~= healcolor then
224 frame.overlay:SetVertexColor(unpack(healcolor));
225 frame.overlay.color = healcolor;
226 if not frame.overlay:IsShown() then frame.overlay:Show() end
229 if frame.overlay.color ~= nil then
230 frame.overlay.color = nil;
231 if frame.overlay:IsShown() then frame.overlay:Hide() end