3 local unpack, pairs, ipairs = unpack, pairs, ipairs;
4 local ssub = string.sub;
6 local UnitName, UnitClass, UnitExists = UnitName, UnitClass, UnitExists;
7 local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed;
8 local UnitPower, UnitPowerMax, UnitPowerType = UnitPower, UnitPowerMax, UnitPowerType;
9 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
10 local UnitInParty, UnitInRaid = UnitInParty, UnitInRaid;
11 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
12 local UnitThreatSituation, GetThreatStatusColor = UnitThreatSituation, GetThreatStatusColor;
13 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
14 local UnitHasIncomingResurrection = UnitHasIncomingResurrection;
15 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
16 local IsInGroup, IsInRaid = IsInGroup, IsInRaid;
17 local UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI;
18 local CTimerAfter = C_Timer.After;
19 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
21 local Frames = OmaFrames;
22 local registerEvents = OmaFrames.RegisterEvents;
23 local Indicators = OmaIndicators;
24 local checkIndicators = Indicators.CheckIndicators;
26 local CFrame = CreateFrame("Frame", "OmaCFrame", UIParent);
31 local width, height = Frames.Width, Frames.Height;
32 local anchorX, anchorY = Frames.AnchorX, Frames.AnchorY;
33 local baseColor = Frames.BaseColor;
34 local overlayColorDispel = Frames.OverlayColorDispel;
35 local overlayColorCharm = Frames.OverlayColorCharm;
36 local overlayColorAlert = Frames.OverlayColorAlert;
37 local powerColors = Frames.PowerColors;
39 local function updateHealth(frame, unit)
40 local current, max = UnitHealth(unit), frame.health.max;
41 local healthLost = max - current;
43 -- sanity check, occasionally UnitHealthMax gives zero
45 -- somehow current health has gone over the maximum (missed maxhealth event)
46 frame.health.max = UnitHealthMax(unit);
47 max = frame.health.max;
49 -- error state, still over maximum
50 frame.health:SetWidth(width);
55 frame.health:SetWidth(current/frame.health.max*width);
57 frame.health:SetWidth(width);
62 if UnitIsDeadOrGhost(unit) then
64 if UnitHasIncomingResurrection(unit) then
65 frame.text:SetText("Rez");
67 frame.text:SetText("Dead");
69 elseif not UnitIsConnected(unit) then
71 frame.text:SetText("DC");
72 elseif healthLost > 0 then
73 if healthLost > 1200000000 then -- 1.2B
74 frame.text:SetFormattedText("-%.1fB", healthLost / 1000000000);
75 elseif healthLost > 1200000 then -- 1.2M
76 frame.text:SetFormattedText("-%.1fM", healthLost / 1000000);
77 elseif healthLost > 1000 then -- 1K
78 frame.text:SetFormattedText("-%dK", healthLost / 1000);
80 frame.text:SetFormattedText("-%d", healthLost)
88 local function updateMaxHealth(frame, unit)
89 frame.health.max = UnitHealthMax(unit);
92 local function updatePower(frame, unit)
93 local current, max = UnitPower(unit), frame.mana.max;
94 -- sanity check, occasionally UnitPowerMax gives zero
96 frame.mana.max = UnitPowerMax(unit);
100 frame.mana:SetWidth(width);
104 frame.mana:SetWidth(UnitPower(unit)/max*width);
106 frame.mana:SetWidth(width);
110 local function updateMaxPower(frame, unit)
111 frame.mana.max = UnitPowerMax(unit);
114 local function updatePowerColor(frame, unit)
115 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
118 local function updateName(frame, unit)
119 local name = UnitName(unit);
120 if not name then return end
121 frame.name:SetText(ssub(name, 1, 6));
123 local _, class = UnitClass(unit);
124 local color = RAID_CLASS_COLORS[class];
125 if color then frame.name:SetVertexColor(color.r, color.g, color.b) end
128 local function updateHealPred(frame, unit)
129 local incoming = UnitGetIncomingHeals(unit) or 0;
131 local max = frame.health.max;
132 local space = width - frame.health:GetWidth() + 1;
133 local pred = (incoming / max) * width;
134 frame.healpred:SetWidth(min(space, pred));
135 frame.healpred:Show();
137 frame.healpred:Hide();
141 local function updateShield(frame, unit)
142 local shield = UnitGetTotalAbsorbs(unit) or 0;
144 local max = frame.health.max;
145 local space = width - frame.health:GetWidth();
146 shield = (shield / max) * width;
147 if space < shield then
148 frame.shield:SetWidth(space);
149 frame.shieldhl:Show();
151 frame.shield:SetWidth(shield);
152 frame.shieldhl:Hide();
157 frame.shieldhl:Hide();
161 local function updateHealAbsorb(frame, unit)
162 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
164 local max = frame.health.max;
165 local space = frame.health:GetWidth();
166 absorb = (absorb / max) * width;
167 frame.healabsorb:SetWidth(min(space, absorb));
168 frame.healabsorb:Show();
170 frame.healabsorb:Hide();
174 local function updateAuras(frame, unit)
175 checkIndicators(frame, unit);
176 if UnitDebuff(unit, 1, "RAID") ~= nil then
177 -- something dispellable
178 if frame.overlay.color ~= overlayColorDispel then
179 frame.overlay:SetVertexColor(unpack(overlayColorDispel));
180 frame.overlay:Show();
181 frame.overlay.color = overlayColorDispel;
183 -- don't overlay charmed when in vehicle
184 elseif UnitIsCharmed(unit) and unit == frame.unit then
185 if frame.overlay.color ~= overlayColorCharm then
186 frame.overlay:SetVertexColor(unpack(overlayColorCharm));
187 frame.overlay:Show();
188 frame.overlay.color = overlayColorCharm;
191 if frame.overlay.color ~= nil then
192 frame.overlay:Hide();
193 frame.overlay.color = nil;
198 local function updateAggro(frame, unit)
199 local status = UnitThreatSituation(unit);
200 if status and status > 0 then
201 frame.base:SetVertexColor(GetThreatStatusColor(status));
203 frame.base:SetVertexColor(unpack(baseColor));
207 local function updateVehicle(frame)
208 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
209 if shouldTargetVehicle then
210 if not frame.inVehicle then
211 frame.inVehicle = true;
212 frame.displayed = frame.vehicle;
213 registerEvents(frame);
215 elseif frame.inVehicle then
216 frame.inVehicle = false;
217 frame.displayed = frame.unit;
218 registerEvents(frame);
223 ["UNIT_HEALTH"] = function(frame)
224 updateHealth(frame, frame.displayed);
225 updateShield(frame, frame.displayed);
226 updateHealAbsorb(frame, frame.displayed);
227 -- no heal prediction update, that doesn't overflow too much
229 ["UNIT_POWER"] = function(frame)
230 updatePower(frame, frame.displayed);
232 ["UNIT_AURA"] = function(frame)
233 updateAuras(frame, frame.displayed);
235 ["UNIT_HEAL_PREDICTION"] = function(frame)
236 updateHealPred(frame, frame.displayed);
238 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
239 updateShield(frame, frame.displayed);
241 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
242 updateHealAbsorb(frame, frame.displayed);
244 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
245 updateAggro(frame, frame.displayed);
247 ["UNIT_MAXHEALTH"] = function(frame)
248 updateMaxHealth(frame, frame.displayed);
249 updateHealth(frame, frame.displayed);
250 updateShield(frame, frame.displayed);
251 updateHealAbsorb(frame, frame.displayed);
253 ["UNIT_MAXPOWER"] = function(frame)
254 updateMaxPower(frame, frame.displayed);
255 updatePower(frame, frame.displayed);
257 ["UNIT_DISPLAYPOWER"] = function(frame)
258 updatePowerColor(frame, frame.displayed);
260 ["UNIT_NAME_UPDATE"] = function(frame)
261 updateName(frame, frame.displayed);
263 ["UNIT_CONNECTION"] = function(frame)
264 updateHealth(frame, frame.displayed);
266 ["INCOMING_RESURRECT_CHANGED"] = function(frame)
268 updateHealth(frame, frame.displayed);
270 ["PARTY_MEMBER_ENABLE"] = function(frame)
271 -- new power info possibly (FrameXML/CompactUnitFrame.lua)
272 updateMaxPower(frame, frame.displayed);
273 updatePowerColor(frame, frame.displayed);
275 ["UPDATE_ALL_BARS"] = function(frame)
276 updateVehicle(frame);
277 updateMaxHealth(frame, frame.displayed);
278 updateMaxPower(frame, frame.displayed);
279 updateHealth(frame, frame.displayed);
280 updatePower(frame, frame.displayed);
281 updateAuras(frame, frame.displayed);
282 updateShield(frame, frame.displayed);
283 updateHealPred(frame, frame.displayed);
284 updateHealAbsorb(frame, frame.displayed);
285 updatePowerColor(frame, frame.displayed);
286 updateAggro(frame, frame.displayed);
287 updateName(frame, frame.displayed);
290 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
291 eventFuncs["PARTY_MEMBER_DISABLE"] = eventFuncs["PARTY_MEMBER_ENABLE"];
292 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
293 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
294 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
295 --local function unitEvent(self, event, ...)
296 local function unitEvent(self, event)
297 --local arg1, arg2, arg3, arg4 = ...;
298 eventFuncs[event](self);
301 local function initialize()
302 CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY);
303 CFrame:SetHeight((height+2)*8);
304 CFrame:SetWidth((width+2)*5+1); -- extra pixel for shield overflow
305 Frames.InitializeParty(CFrame, party, unitEvent);
306 Frames.InitializeRaid(CFrame, raid, unitEvent);
309 CFrame:RegisterEvent("ADDON_LOADED");
310 CFrame:RegisterEvent("PLAYER_LOGIN");
311 CFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
312 CFrame:RegisterEvent("GROUP_ROSTER_UPDATE");
313 CFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
314 CFrame:SetScript("OnEvent", function(self, event, ...)
315 if event == "GROUP_ROSTER_UPDATE" or event == "PLAYER_REGEN_ENABLED" or
316 event == "PLAYER_ENTERING_WORLD" then
318 elseif event == "PLAYER_LOGIN" then
320 elseif event == "ADDON_LOADED" then