4 local ssub = string.sub;
6 local ceil = math.ceil;
7 local UnitName, UnitClass, UnitExists = UnitName, UnitClass, UnitExists;
8 local UnitPower, UnitPowerMax, UnitPowerType = UnitPower, UnitPowerMax, UnitPowerType;
9 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
10 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
11 local UnitThreatSituation, GetThreatStatusColor = UnitThreatSituation, GetThreatStatusColor;
12 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
13 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
14 local UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI;
15 local UnitLevel, UnitClassification = UnitLevel, UnitClassification;
16 local UnitAffectingCombat, IsResting = UnitAffectingCombat, IsResting;
17 local UnitIsPVPFreeForAll, UnitIsPVP = UnitIsPVPFreeForAll, UnitIsPVP;
18 local UnitFactionGroup, UnitIsMercenary = UnitFactionGroup, UnitIsMercenary;
19 local UnitIsGroupLeader, UnitIsGroupAssistant = UnitIsGroupLeader, UnitIsGroupAssistant;
20 local HasLFGRestrictions = HasLFGRestrictions;
21 local UnitPlayerControlled, UnitIsPlayer = UnitPlayerControlled, UnitIsPlayer;
22 local UnitIsTapDenied, UnitSelectionColor = UnitIsTapDenied, UnitSelectionColor;
23 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
25 local updateAuraFrames = OmaUFAuras.UpdateAuras;
27 local Settings = OmaUFSettings;
28 local baseColor = Settings.BaseColor;
29 local healthColor = Settings.HealthColor;
30 local powerColors = Settings.PowerColors;
34 function M.RegisterUnitEvents(frame)
35 -- events are taken from FrameXML/CompactUnitFrame.lua
36 -- TODO raid marker support,
37 -- player flags support (/afk, /dnd)
38 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
39 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
40 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed);
42 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
43 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
44 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed);
45 frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", frame.unit, displayed);
46 frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
48 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
49 frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed);
50 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
51 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
52 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
53 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
54 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
56 local registerUnitEvents = M.RegisterUnitEvents;
58 local function updateMaxHealth(frame, unit)
59 frame.health.max = UnitHealthMax(unit);
62 local function updateHealth(frame, unit)
63 local current, max = UnitHealth(unit), frame.health.max;
64 if current > max or max <= 0 then
65 -- somehow current health has gone over the maximum (missed maxhealth event)
66 frame.health:SetWidth(frame.width);
67 updateMaxHealth(frame, unit);
69 elseif current <= 0 or UnitIsDeadOrGhost(unit) then
72 frame.health:SetWidth(current/max*frame.width);
77 local function updateHealthText(frame, unit)
78 if UnitIsDeadOrGhost(unit) then
79 frame.healthText:SetText("Dead");
80 elseif not UnitIsConnected(unit) then
81 frame.healthText:SetText("DC");
83 local current = UnitHealth(unit);
84 if current > 1200000000 then -- 1.2B
85 frame.healthText:SetFormattedText("%.1fB", current / 1000000000);
86 elseif current > 1200000 then -- 1.2M
87 frame.healthText:SetFormattedText("%.1fM", current / 1000000);
88 elseif current > 1000 then -- 1K
89 frame.healthText:SetFormattedText("%.1fK", current / 1000);
91 frame.healthText:SetFormattedText("%d", current)
96 local function updateMaxPower(frame, unit)
97 frame.mana.max = UnitPowerMax(unit);
100 local function updatePower(frame, unit)
101 local current, max = UnitPower(unit), frame.mana.max;
104 elseif current > max or max <= 0 then
105 frame.mana:SetWidth(frame.width);
106 updateMaxPower(frame, unit);
109 frame.mana:SetWidth(current/max*frame.width);
114 local function updatePowerText(frame, unit)
115 local current, max = UnitPower(unit), frame.mana.max;
116 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
117 frame.manaText:Hide();
118 elseif max > 0 and current > 0 and current < max then
119 frame.manaText:SetText(ceil(current/max*100));
120 frame.manaText:Show();
122 frame.manaText:Hide();
126 local function updatePowerColor(frame, unit)
127 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
130 local function updateName(frame, unit)
131 local name = UnitName(unit);
132 if not name then return end
133 frame.name:SetText(ssub(name, 1, 10));
136 local function updateHealPred(frame, unit)
137 local incoming = UnitGetIncomingHeals(unit) or 0;
139 local space = frame.width - frame.health:GetWidth() + 1;
140 incoming = (incoming / frame.health.max) * frame.width;
141 frame.healpred:SetWidth(min(space, incoming));
142 frame.healpred:Show();
144 frame.healpred:Hide();
148 local function updateShield(frame, unit)
149 local shield = UnitGetTotalAbsorbs(unit) or 0;
151 local space = frame.width - frame.health:GetWidth();
152 shield = (shield / frame.health.max) * frame.width;
155 frame.shieldhl:Show();
156 elseif space < shield then
157 frame.shield:SetWidth(space);
159 frame.shieldhl:Show();
161 frame.shield:SetWidth(shield);
163 frame.shieldhl:Hide();
167 frame.shieldhl:Hide();
171 local function updateHealAbsorb(frame, unit)
172 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
174 local space = frame.health:GetWidth();
175 absorb = (absorb / frame.health.max) * frame.width;
176 frame.healabsorb:SetWidth(min(space, absorb));
177 frame.healabsorb:Show();
179 frame.healabsorb:Hide();
183 local function updateAuras(frame, unit)
184 if frame.auras then updateAuraFrames(frame, unit) end
187 local function updateAggro(frame, unit)
188 local status = UnitThreatSituation(unit);
189 if status and status > 0 then
190 frame.base:SetVertexColor(GetThreatStatusColor(status));
192 frame.base:SetVertexColor(unpack(baseColor));
196 local function updateVehicle(frame)
197 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and
198 UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
199 if shouldTargetVehicle then
200 if not frame.inVehicle then
201 frame.inVehicle = true;
202 frame.displayed = frame.vehicle;
203 registerUnitEvents(frame);
205 elseif frame.inVehicle then
206 frame.inVehicle = false;
207 frame.displayed = frame.unit;
208 registerUnitEvents(frame);
212 local function updateLevelText(frame, unit, levelup)
215 frame.level:SetText(levelup);
217 local level = UnitLevel(unit);
218 local class = UnitClassification(unit);
219 local leveltext, classtext;
221 if class == "worldboss" then
229 if class == "rareelite" then
230 classtext = " Rare Elite";
231 elseif class == "elite" then
232 classtext = " Elite";
233 elseif class == "rare" then
238 frame.level:SetFormattedText("%s%s", leveltext, classtext);
242 local function updateStatus(frame, unit)
243 -- coords from FrameXML/PlayerFrame.lua
244 if frame.inCombat or UnitAffectingCombat(unit) then
245 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
247 elseif unit == "player" and IsResting() then
248 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
255 local function updatePVP(frame, unit)
256 if UnitIsPVPFreeForAll(unit) then
257 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
259 elseif UnitIsPVP(unit) then
260 local faction = UnitFactionGroup(unit);
261 if faction and faction ~= "Neutral" then
262 -- from FrameXML/PlayerFrame.lua, mercenary checks
263 if UnitIsMercenary(unit) then
264 if faction == "Horde" then
265 faction = "Alliance";
266 elseif faction == "Alliance" then
270 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
280 local function updateLeaderIcon(frame, unit)
281 if UnitIsGroupLeader(frame.unit) then
282 if HasLFGRestrictions() then
283 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
284 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
286 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
287 frame.leader:SetTexCoord(0, 1, 0, 1);
290 elseif UnitIsGroupAssistant(frame.unit) then
291 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
292 frame.leader:SetTexCoord(0, 1, 0, 1);
299 local function updateHealthColor(frame, unit)
300 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
301 frame.health:SetVertexColor(0.5, 0.5, 0.5);
302 elseif UnitIsPlayer(unit) then
303 local _, class = UnitClass(unit);
304 local color = RAID_CLASS_COLORS[class];
306 frame.health:SetVertexColor(color.r, color.g, color.b)
308 frame.health:SetVertexColor(unpack(healthColor))
310 elseif UnitPlayerControlled(unit) then
311 frame.health:SetVertexColor(0, 1, 0);
313 frame.health:SetVertexColor(UnitSelectionColor(unit));
318 ["UNIT_HEALTH"] = function(frame)
319 updateHealth(frame, frame.displayed);
320 updateHealthText(frame, frame.displayed);
321 updateShield(frame, frame.displayed);
322 updateHealAbsorb(frame, frame.displayed);
324 ["UNIT_POWER"] = function(frame)
325 updatePower(frame, frame.displayed);
326 updatePowerText(frame, frame.displayed);
328 ["UNIT_AURA"] = function(frame)
329 updateAuras(frame, frame.displayed);
331 ["UNIT_HEAL_PREDICTION"] = function(frame)
332 updateHealPred(frame, frame.displayed);
334 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
335 updateShield(frame, frame.displayed);
337 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
338 updateHealAbsorb(frame, frame.displayed);
340 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
341 updateAggro(frame, frame.displayed);
343 ["UNIT_MAXHEALTH"] = function(frame)
344 updateMaxHealth(frame, frame.displayed);
345 updateHealth(frame, frame.displayed);
346 updateHealthText(frame, frame.displayed);
347 updateShield(frame, frame.displayed);
348 updateHealAbsorb(frame, frame.displayed);
350 ["UNIT_MAXPOWER"] = function(frame)
351 updateMaxPower(frame, frame.displayed);
352 updatePower(frame, frame.displayed);
353 updatePowerText(frame, frame.displayed);
355 ["UNIT_DISPLAYPOWER"] = function(frame)
356 updatePowerColor(frame, frame.displayed);
357 updateMaxPower(frame, frame.displayed);
358 updatePower(frame, frame.displayed);
359 updatePowerText(frame, frame.displayed);
361 ["UNIT_NAME_UPDATE"] = function(frame)
362 if frame.name then updateName(frame, frame.displayed) end
363 updateHealthColor(frame, frame.displayed);
365 ["UNIT_CONNECTION"] = function(frame)
366 updateHealthText(frame, frame.displayed);
367 updatePowerText(frame, frame.displayed);
369 ["UNIT_LEVEL"] = function(frame)
370 -- if this is registered, frame has frame.level
371 updateLevelText(frame, frame.unit);
373 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
374 updateLevelText(frame, frame.unit, arg1);
376 ["PLAYER_UPDATE_RESTING"] = function(frame)
377 -- player frame has frame.status
378 updateStatus(frame, frame.unit);
380 ["PLAYER_REGEN_DISABLED"] = function(frame)
381 frame.inCombat = true;
382 if frame.status then updateStatus(frame, frame.unit) end
384 ["PLAYER_REGEN_ENABLED"] = function(frame)
385 frame.inCombat = false;
386 if frame.status then updateStatus(frame, frame.unit) end
388 ["UNIT_FACTION"] = function(frame)
389 if frame.pvp then updatePVP(frame, frame.unit) end
390 updateHealthColor(frame, frame.displayed);
392 ["PARTY_LEADER_CHANGED"] = function(frame)
393 updateLeaderIcon(frame, frame.unit);
395 ["UPDATE_ALL_BARS"] = function(frame)
396 if frame.vehicle then updateVehicle(frame) end
397 updateMaxHealth(frame, frame.displayed);
398 updateMaxPower(frame, frame.displayed);
399 updateHealth(frame, frame.displayed);
400 updateHealthText(frame, frame.displayed);
401 updatePower(frame, frame.displayed);
402 updatePowerText(frame, frame.displayed);
403 updateAuras(frame, frame.displayed);
404 updateShield(frame, frame.displayed);
405 updateHealPred(frame, frame.displayed);
406 updateHealAbsorb(frame, frame.displayed);
407 updatePowerColor(frame, frame.displayed);
408 updateAggro(frame, frame.displayed);
409 if frame.name then updateName(frame, frame.displayed) end
410 if frame.level then updateLevelText(frame, frame.unit) end
411 if frame.status then updateStatus(frame, frame.unit) end
412 if frame.pvp then updatePVP(frame, frame.unit) end
413 if frame.leader then updateLeaderIcon(frame, frame.unit) end
414 updateHealthColor(frame, frame.displayed);
417 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
418 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
419 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
420 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
421 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
422 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
423 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
424 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
425 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
427 function M.UnitEvent(self, event, arg1)
428 eventFuncs[event](self, arg1);