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 if UnitHasIncomingResurrection(unit) then
70 frame.text:SetText("Rez");
72 frame.text:SetText("Dead");
74 elseif not UnitIsConnected(unit) then
75 frame.text:SetText("DC");
76 elseif healthLost > 0 then
77 if healthLost > 1200000000 then -- 1.2B
78 frame.text:SetFormattedText("-%.1fB", healthLost / 1000000000);
79 elseif healthLost > 1200000 then -- 1.2M
80 frame.text:SetFormattedText("-%.1fM", healthLost / 1000000);
81 elseif healthLost > 1000 then -- 1K
82 frame.text:SetFormattedText("-%dK", healthLost / 1000);
84 frame.text:SetFormattedText("-%d", healthLost)
92 local function updateMaxHealth(frame, unit)
93 frame.health.max = UnitHealthMax(unit);
96 local function updatePower(frame, unit)
97 local current, max = UnitPower(unit), frame.mana.max;
98 -- sanity check, occasionally UnitPowerMax gives zero
100 frame.mana.max = UnitPowerMax(unit);
101 max = frame.mana.max;
102 if current > max then
104 frame.mana:SetWidth(width);
108 frame.mana:SetWidth(UnitPower(unit)/max*width);
110 frame.mana:SetWidth(width);
114 local function updateMaxPower(frame, unit)
115 frame.mana.max = UnitPowerMax(unit);
118 local function updatePowerColor(frame, unit)
119 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
122 local function updateName(frame, unit)
123 local name = UnitName(unit);
124 if not name then return end
125 frame.name:SetText(ssub(name, 1, 6));
127 local _, class = UnitClass(unit);
128 local color = RAID_CLASS_COLORS[class];
129 if color then frame.name:SetVertexColor(color.r, color.g, color.b) end
132 local function updateHealPred(frame, unit)
133 local incoming = UnitGetIncomingHeals(unit) or 0;
135 local max = frame.health.max;
136 local space = width - frame.health:GetWidth() + 1;
137 local pred = (incoming / max) * width;
138 frame.healpred:SetWidth(min(space, pred));
139 frame.healpred:Show();
141 frame.healpred:Hide();
145 local function updateShield(frame, unit)
146 local shield = UnitGetTotalAbsorbs(unit) or 0;
148 local max = frame.health.max;
149 local space = width - frame.health:GetWidth();
150 shield = (shield / max) * width;
151 if space < shield then
152 frame.shield:SetWidth(space);
153 frame.shieldhl:Show();
155 frame.shield:SetWidth(shield);
156 frame.shieldhl:Hide();
161 frame.shieldhl:Hide();
165 local function updateHealAbsorb(frame, unit)
166 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
168 local max = frame.health.max;
169 local space = frame.health:GetWidth();
170 absorb = (absorb / max) * width;
171 frame.healabsorb:SetWidth(min(space, absorb));
172 frame.healabsorb:Show();
174 frame.healabsorb:Hide();
178 local function updateAuras(frame, unit)
179 checkIndicators(frame, unit);
180 if UnitDebuff(unit, 1, "RAID") ~= nil then
181 -- something dispellable
182 if frame.overlay.color ~= overlayColorDispel then
183 frame.overlay:SetVertexColor(unpack(overlayColorDispel));
184 frame.overlay:Show();
185 frame.overlay.color = overlayColorDispel;
187 -- don't overlay charmed when in vehicle
188 elseif UnitIsCharmed(unit) and unit == frame.unit then
189 if frame.overlay.color ~= overlayColorCharm then
190 frame.overlay:SetVertexColor(unpack(overlayColorCharm));
191 frame.overlay:Show();
192 frame.overlay.color = overlayColorCharm;
195 if frame.overlay.color ~= nil then
196 frame.overlay:Hide();
197 frame.overlay.color = nil;
202 local function updateAggro(frame, unit)
203 local status = UnitThreatSituation(unit);
204 if status and status > 0 then
205 frame.base:SetVertexColor(GetThreatStatusColor(status));
207 frame.base:SetVertexColor(unpack(baseColor));
211 local function updateVehicle(frame)
212 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
213 if shouldTargetVehicle then
214 if not frame.inVehicle then
215 frame.inVehicle = true;
216 frame.displayed = frame.vehicle;
217 registerEvents(frame);
219 elseif frame.inVehicle then
220 frame.inVehicle = false;
221 frame.displayed = frame.unit;
222 registerEvents(frame);
226 local function updateRole(frame, unit)
227 local role = UnitGroupRolesAssigned(unit);
228 if role == "HEALER" then
229 frame.role:SetTexCoord(0.75, 1, 0, 1);
231 elseif role == "TANK" then
232 frame.role:SetTexCoord(0.5, 0.75, 0, 1);
240 ["UNIT_HEALTH"] = function(frame)
241 updateHealth(frame, frame.displayed);
242 updateText(frame, frame.displayed);
243 updateShield(frame, frame.displayed);
244 updateHealAbsorb(frame, frame.displayed);
245 -- no heal prediction update, that doesn't overflow too much
247 ["UNIT_POWER"] = function(frame)
248 updatePower(frame, frame.displayed);
250 ["UNIT_AURA"] = function(frame)
251 updateAuras(frame, frame.displayed);
253 ["UNIT_HEAL_PREDICTION"] = function(frame)
254 updateHealPred(frame, frame.displayed);
256 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
257 updateShield(frame, frame.displayed);
259 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
260 updateHealAbsorb(frame, frame.displayed);
262 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
263 updateAggro(frame, frame.displayed);
265 ["UNIT_MAXHEALTH"] = function(frame)
266 updateMaxHealth(frame, frame.displayed);
267 updateHealth(frame, frame.displayed);
268 updateText(frame, frame.displayed);
269 updateShield(frame, frame.displayed);
270 updateHealAbsorb(frame, frame.displayed);
272 ["UNIT_MAXPOWER"] = function(frame)
273 updateMaxPower(frame, frame.displayed);
274 updatePower(frame, frame.displayed);
276 ["UNIT_DISPLAYPOWER"] = function(frame)
277 updatePowerColor(frame, frame.displayed);
279 ["UNIT_NAME_UPDATE"] = function(frame)
280 updateName(frame, frame.displayed);
282 ["UNIT_CONNECTION"] = function(frame)
283 updateText(frame, frame.displayed);
285 ["INCOMING_RESURRECT_CHANGED"] = function(frame)
287 updateText(frame, frame.displayed);
289 ["PARTY_MEMBER_ENABLE"] = function(frame)
290 -- new power info possibly (FrameXML/CompactUnitFrame.lua)
291 updateMaxPower(frame, frame.displayed);
292 updatePowerColor(frame, frame.displayed);
294 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
295 updateRole(frame, frame.unit);
297 ["UPDATE_ALL_BARS"] = function(frame)
298 updateVehicle(frame);
299 updateMaxHealth(frame, frame.displayed);
300 updateMaxPower(frame, frame.displayed);
301 updateHealth(frame, frame.displayed);
302 updateText(frame, frame.displayed);
303 updatePower(frame, frame.displayed);
304 updateAuras(frame, frame.displayed);
305 updateShield(frame, frame.displayed);
306 updateHealPred(frame, frame.displayed);
307 updateHealAbsorb(frame, frame.displayed);
308 updatePowerColor(frame, frame.displayed);
309 updateAggro(frame, frame.displayed);
310 updateName(frame, frame.displayed);
311 updateRole(frame, frame.unit);
314 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
315 eventFuncs["PARTY_MEMBER_DISABLE"] = eventFuncs["PARTY_MEMBER_ENABLE"];
316 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
317 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
318 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
319 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
320 --local function unitEvent(self, event, ...)
321 local function unitEvent(self, event)
322 --local arg1, arg2, arg3, arg4 = ...;
323 eventFuncs[event](self);
326 local function initialize()
327 CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY);
328 CFrame:SetHeight((height+2)*8);
329 CFrame:SetWidth((width+2)*5+1); -- extra pixel for shield overflow
330 Frames.InitializeParty(CFrame, party, unitEvent);
331 Frames.InitializeRaid(CFrame, raid, unitEvent);
334 CFrame:RegisterEvent("ADDON_LOADED");
335 CFrame:RegisterEvent("PLAYER_LOGIN");
336 CFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
337 CFrame:RegisterEvent("GROUP_ROSTER_UPDATE");
338 CFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
339 CFrame:SetScript("OnEvent", function(self, event, ...)
340 if event == "GROUP_ROSTER_UPDATE" or event == "PLAYER_REGEN_ENABLED" or
341 event == "PLAYER_ENTERING_WORLD" then
343 elseif event == "PLAYER_LOGIN" then
345 elseif event == "ADDON_LOADED" then