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 UnitGroupRolesAssigned = UnitGroupRolesAssigned;
19 local CTimerAfter = C_Timer.After;
20 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
22 local Frames = OmaFrames;
23 local registerEvents = OmaFrames.RegisterEvents;
24 local Indicators = OmaIndicators;
25 local checkIndicators = Indicators.CheckIndicators;
27 local CFrame = CreateFrame("Frame", "OmaCFrame", UIParent);
32 local width, height = Frames.Width, Frames.Height;
33 local anchorX, anchorY = Frames.AnchorX, Frames.AnchorY;
34 local baseColor = Frames.BaseColor;
35 local overlayColorDispel = Frames.OverlayColorDispel;
36 local overlayColorCharm = Frames.OverlayColorCharm;
37 local overlayColorAlert = Frames.OverlayColorAlert;
38 local powerColors = Frames.PowerColors;
40 local function updateHealth(frame, unit)
41 local current, max = UnitHealth(unit), frame.health.max;
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);
54 frame.health:SetWidth(current/frame.health.max*width);
56 frame.health:SetWidth(width);
60 if UnitIsDeadOrGhost(unit) then
65 local function updateText(frame, unit)
66 local current, max = UnitHealth(unit), frame.health.max;
67 local healthLost = max - current;
68 if UnitIsDeadOrGhost(unit) then
69 frame.text:SetText("Dead");
70 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 updateIncomingRes(frame, unit)
89 if UnitHasIncomingResurrection(unit) then
96 local function updateMaxHealth(frame, unit)
97 frame.health.max = UnitHealthMax(unit);
100 local function updatePower(frame, unit)
101 local current, max = UnitPower(unit), frame.mana.max;
102 -- sanity check, occasionally UnitPowerMax gives zero
103 if current > max then
104 frame.mana.max = UnitPowerMax(unit);
105 max = frame.mana.max;
106 if current > max then
108 frame.mana:SetWidth(width);
112 frame.mana:SetWidth(UnitPower(unit)/max*width);
114 frame.mana:SetWidth(width);
118 local function updateMaxPower(frame, unit)
119 frame.mana.max = UnitPowerMax(unit);
122 local function updatePowerColor(frame, unit)
123 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
126 local function updateName(frame, unit)
127 local name = UnitName(unit);
128 if not name then return end
129 frame.name:SetText(ssub(name, 1, 6));
131 local _, class = UnitClass(unit);
132 local color = RAID_CLASS_COLORS[class];
133 if color then frame.name:SetVertexColor(color.r, color.g, color.b) end
136 local function updateHealPred(frame, unit)
137 local incoming = UnitGetIncomingHeals(unit) or 0;
139 local max = frame.health.max;
140 local space = width - frame.health:GetWidth() + 1;
141 local pred = (incoming / max) * width;
142 frame.healpred:SetWidth(min(space, pred));
143 frame.healpred:Show();
145 frame.healpred:Hide();
149 local function updateShield(frame, unit)
150 local shield = UnitGetTotalAbsorbs(unit) or 0;
152 local max = frame.health.max;
153 local space = width - frame.health:GetWidth();
154 shield = (shield / max) * width;
155 if space < shield then
156 frame.shield:SetWidth(space);
157 frame.shieldhl:Show();
159 frame.shield:SetWidth(shield);
160 frame.shieldhl:Hide();
165 frame.shieldhl:Hide();
169 local function updateHealAbsorb(frame, unit)
170 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
172 local max = frame.health.max;
173 local space = frame.health:GetWidth();
174 absorb = (absorb / max) * width;
175 frame.healabsorb:SetWidth(min(space, absorb));
176 frame.healabsorb:Show();
178 frame.healabsorb:Hide();
182 local function updateAuras(frame, unit)
183 checkIndicators(frame, unit);
184 if UnitDebuff(unit, 1, "RAID") ~= nil then
185 -- something dispellable
186 if frame.overlay.color ~= overlayColorDispel then
187 frame.overlay:SetVertexColor(unpack(overlayColorDispel));
188 frame.overlay:Show();
189 frame.overlay.color = overlayColorDispel;
191 -- don't overlay charmed when in vehicle
192 elseif UnitIsCharmed(unit) and unit == frame.unit then
193 if frame.overlay.color ~= overlayColorCharm then
194 frame.overlay:SetVertexColor(unpack(overlayColorCharm));
195 frame.overlay:Show();
196 frame.overlay.color = overlayColorCharm;
199 if frame.overlay.color ~= nil then
200 frame.overlay:Hide();
201 frame.overlay.color = nil;
206 local function updateAggro(frame, unit)
207 local status = UnitThreatSituation(unit);
208 if status and status > 0 then
209 frame.base:SetVertexColor(GetThreatStatusColor(status));
211 frame.base:SetVertexColor(unpack(baseColor));
215 local function updateVehicle(frame)
216 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
217 if shouldTargetVehicle then
218 if not frame.inVehicle then
219 frame.inVehicle = true;
220 frame.displayed = frame.vehicle;
221 registerEvents(frame);
223 elseif frame.inVehicle then
224 frame.inVehicle = false;
225 frame.displayed = frame.unit;
226 registerEvents(frame);
230 local function updateRole(frame, unit)
231 local role = UnitGroupRolesAssigned(unit);
232 if role == "HEALER" then
233 frame.role:SetTexCoord(0.75, 1, 0, 1);
235 elseif role == "TANK" then
236 frame.role:SetTexCoord(0.5, 0.75, 0, 1);
244 ["UNIT_HEALTH"] = function(frame)
245 updateHealth(frame, frame.displayed);
246 updateText(frame, frame.displayed);
247 updateShield(frame, frame.displayed);
248 updateHealAbsorb(frame, frame.displayed);
249 -- no heal prediction update, that doesn't overflow too much
251 ["UNIT_POWER"] = function(frame)
252 updatePower(frame, frame.displayed);
254 ["UNIT_AURA"] = function(frame)
255 updateAuras(frame, frame.displayed);
257 ["UNIT_HEAL_PREDICTION"] = function(frame)
258 updateHealPred(frame, frame.displayed);
260 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
261 updateShield(frame, frame.displayed);
263 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
264 updateHealAbsorb(frame, frame.displayed);
266 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
267 updateAggro(frame, frame.displayed);
269 ["UNIT_MAXHEALTH"] = function(frame)
270 updateMaxHealth(frame, frame.displayed);
271 updateHealth(frame, frame.displayed);
272 updateText(frame, frame.displayed);
273 updateShield(frame, frame.displayed);
274 updateHealAbsorb(frame, frame.displayed);
276 ["UNIT_MAXPOWER"] = function(frame)
277 updateMaxPower(frame, frame.displayed);
278 updatePower(frame, frame.displayed);
280 ["UNIT_DISPLAYPOWER"] = function(frame)
281 updatePowerColor(frame, frame.displayed);
283 ["UNIT_NAME_UPDATE"] = function(frame)
284 updateName(frame, frame.displayed);
286 ["UNIT_CONNECTION"] = function(frame)
287 updateText(frame, frame.displayed);
289 ["INCOMING_RESURRECT_CHANGED"] = function(frame)
290 updateIncomingRes(frame, frame.unit);
292 ["PARTY_MEMBER_ENABLE"] = function(frame)
293 -- new power info possibly (FrameXML/CompactUnitFrame.lua)
294 updateMaxPower(frame, frame.displayed);
295 updatePowerColor(frame, frame.displayed);
297 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
298 updateRole(frame, frame.unit);
300 ["UPDATE_ALL_BARS"] = function(frame)
301 updateVehicle(frame);
302 updateMaxHealth(frame, frame.displayed);
303 updateMaxPower(frame, frame.displayed);
304 updateHealth(frame, frame.displayed);
305 updateText(frame, frame.displayed);
306 updatePower(frame, frame.displayed);
307 updateAuras(frame, frame.displayed);
308 updateShield(frame, frame.displayed);
309 updateHealPred(frame, frame.displayed);
310 updateHealAbsorb(frame, frame.displayed);
311 updatePowerColor(frame, frame.displayed);
312 updateAggro(frame, frame.displayed);
313 updateName(frame, frame.displayed);
314 updateRole(frame, frame.unit);
317 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
318 eventFuncs["PARTY_MEMBER_DISABLE"] = eventFuncs["PARTY_MEMBER_ENABLE"];
319 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
320 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
321 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
322 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
323 --local function unitEvent(self, event, ...)
324 local function unitEvent(self, event)
325 --local arg1, arg2, arg3, arg4 = ...;
326 eventFuncs[event](self);
329 local function initialize()
330 CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY);
331 CFrame:SetHeight((height+2)*8);
332 CFrame:SetWidth((width+2)*5+1); -- extra pixel for shield overflow
333 Frames.InitializeParty(CFrame, party, unitEvent);
334 Frames.InitializeRaid(CFrame, raid, unitEvent);
337 CFrame:RegisterEvent("ADDON_LOADED");
338 CFrame:RegisterEvent("PLAYER_LOGIN");
339 CFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
340 CFrame:RegisterEvent("GROUP_ROSTER_UPDATE");
341 CFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
342 CFrame:SetScript("OnEvent", function(self, event, ...)
343 if event == "GROUP_ROSTER_UPDATE" or event == "PLAYER_REGEN_ENABLED" or
344 event == "PLAYER_ENTERING_WORLD" then
346 elseif event == "PLAYER_LOGIN" then
348 elseif event == "ADDON_LOADED" then