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 GetRaidTargetIndex, SetRaidTargetIconTexture = GetRaidTargetIndex, SetRaidTargetIconTexture;
24 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
26 local updateAuraFrames = OmaUFAuras.UpdateAuras;
28 local Settings = OmaUFSettings;
29 local baseColor = Settings.BaseColor;
30 local healthColor = Settings.HealthColor;
31 local powerColors = Settings.PowerColors;
35 function M.RegisterUnitEvents(frame)
36 -- events are taken from FrameXML/CompactUnitFrame.lua and FrameXML/TargetFrame.lua
37 -- TODO player flags support (/afk, /dnd)
38 frame:RegisterEvent("RAID_TARGET_UPDATE"); -- have to register all and just check
39 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
40 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
42 frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed);
44 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
45 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
46 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", frame.unit, displayed);
48 frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", frame.unit, displayed);
51 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
53 if frame.healabsorb then
54 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
57 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
59 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
60 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
61 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
62 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
64 local registerUnitEvents = M.RegisterUnitEvents;
66 local function updateMaxHealth(frame, unit)
67 frame.health.max = UnitHealthMax(unit);
70 local function updateHealth(frame, unit)
71 local current, max = UnitHealth(unit), frame.health.max;
72 if current > max or max <= 0 then
73 -- somehow current health has gone over the maximum (missed maxhealth event)
74 frame.health:SetWidth(frame.width);
75 updateMaxHealth(frame, unit);
77 elseif current <= 0 or UnitIsDeadOrGhost(unit) then
80 frame.health:SetWidth(current/max*frame.width);
85 local function updateHealthText(frame, unit)
86 if UnitIsDeadOrGhost(unit) then
87 frame.healthText:SetText("Dead");
88 elseif not UnitIsConnected(unit) then
89 frame.healthText:SetText("DC");
90 elseif frame.healthText.percent then
91 frame.healthText:SetFormattedText("%.1f", UnitHealth(unit)/frame.health.max*100);
93 local current = UnitHealth(unit);
94 if current > 1000000000 then -- 1.0B
95 frame.healthText:SetFormattedText("%.2fB", current / 1000000000);
96 elseif current > 1000000 then -- 1.0M
97 frame.healthText:SetFormattedText("%.2fM", current / 1000000);
98 elseif current > 1000 then -- 1K
99 frame.healthText:SetFormattedText("%.1fK", current / 1000);
101 frame.healthText:SetFormattedText("%d", current)
106 local function updateMaxPower(frame, unit)
107 frame.mana.max = UnitPowerMax(unit);
110 local function updatePower(frame, unit)
111 local current, max = UnitPower(unit), frame.mana.max;
114 elseif current > max or max <= 0 then
115 frame.mana:SetWidth(frame.width);
116 updateMaxPower(frame, unit);
119 frame.mana:SetWidth(current/max*frame.width);
124 local function updatePowerText(frame, unit)
125 local current, max = UnitPower(unit), frame.mana.max;
126 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
127 frame.manaText:Hide();
128 elseif max > 0 and current > 0 and current < max then
129 frame.manaText:SetText(ceil(current/max*100));
130 frame.manaText:Show();
132 frame.manaText:Hide();
136 local function updatePowerColor(frame, unit)
137 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
140 local function updateName(frame, unit)
141 local name = UnitName(unit);
142 if not name then return end
143 frame.name:SetText(ssub(name, 1, frame.name.count));
146 local function updateShield(frame, unit)
147 local shield = UnitGetTotalAbsorbs(unit) or 0;
149 local space = frame.width - frame.health:GetWidth();
150 shield = (shield / frame.health.max) * frame.width;
153 frame.shieldhl:Show();
154 elseif space < shield then
155 frame.shield:SetWidth(space);
157 frame.shieldhl:Show();
159 frame.shield:SetWidth(shield);
161 frame.shieldhl:Hide();
165 frame.shieldhl:Hide();
169 local function updateHealAbsorb(frame, unit)
170 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
172 local space = frame.health:GetWidth();
173 absorb = (absorb / frame.health.max) * frame.width;
174 frame.healabsorb:SetWidth(min(space, absorb));
175 frame.healabsorb:Show();
177 frame.healabsorb:Hide();
181 local function updateAuras(frame, unit)
182 if frame.auras then updateAuraFrames(frame, unit) end
185 local function updateAggro(frame, unit)
186 local status = UnitThreatSituation(unit);
187 if status and status > 0 then
188 frame.base:SetVertexColor(GetThreatStatusColor(status));
190 frame.base:SetVertexColor(unpack(baseColor));
194 -- only works for player frame
195 local function updateVehicle(frame)
196 local shouldTargetVehicle = UnitHasVehicleUI("player") and
197 UnitTargetsVehicleInRaidUI("player") and UnitExists("vehicle");
198 if shouldTargetVehicle then
199 if not frame.inVehicle then
200 frame.inVehicle = true;
201 frame.displayed = frame.vehicle;
202 registerUnitEvents(frame);
204 elseif frame.inVehicle then
205 frame.inVehicle = false;
206 frame.displayed = frame.unit;
207 registerUnitEvents(frame);
211 local function updateLevelText(frame, unit, levelup)
214 frame.level:SetText(levelup);
216 local level = UnitLevel(unit);
217 local class = UnitClassification(unit);
218 local leveltext, classtext;
220 if class == "worldboss" then
228 if class == "rareelite" then
229 classtext = " Rare Elite";
230 elseif class == "elite" then
231 classtext = " Elite";
232 elseif class == "rare" then
237 frame.level:SetFormattedText("%s%s", leveltext, classtext);
241 local function updateStatus(frame, unit)
242 -- coords from FrameXML/PlayerFrame.lua
243 if frame.inCombat or UnitAffectingCombat(unit) then
244 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
246 elseif unit == "player" and IsResting() then
247 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
255 Alliance = "Interface\\TARGETINGFRAME\\UI-PVP-Alliance",
256 Horde = "Interface\\TARGETINGFRAME\\UI-PVP-Horde"
258 local function updatePVP(frame, unit)
259 if UnitIsPVPFreeForAll(unit) then
260 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
262 elseif UnitIsPVP(unit) then
263 local faction = UnitFactionGroup(unit);
264 if faction and faction ~= "Neutral" then
265 -- from FrameXML/PlayerFrame.lua, mercenary checks
266 if UnitIsMercenary(unit) then
267 if faction == "Horde" then
268 faction = "Alliance";
269 elseif faction == "Alliance" then
273 frame.pvp:SetTexture(pvpIcons[faction]);
283 local function updateLeaderIcon(frame, unit)
284 if UnitIsGroupLeader(frame.unit) then
285 if HasLFGRestrictions() then
286 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
287 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
289 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
290 frame.leader:SetTexCoord(0, 1, 0, 1);
293 elseif UnitIsGroupAssistant(frame.unit) then
294 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
295 frame.leader:SetTexCoord(0, 1, 0, 1);
302 local function updateHealthColor(frame, unit)
303 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
304 frame.health:SetVertexColor(0.5, 0.5, 0.5);
305 elseif UnitIsPlayer(unit) then
306 local _, class = UnitClass(unit);
307 local color = RAID_CLASS_COLORS[class];
309 frame.health:SetVertexColor(color.r, color.g, color.b)
311 frame.health:SetVertexColor(unpack(healthColor))
313 elseif UnitPlayerControlled(unit) then
314 frame.health:SetVertexColor(0, 1, 0);
316 frame.health:SetVertexColor(UnitSelectionColor(unit));
320 local function updateRaidMarker(frame, unit)
321 local index = GetRaidTargetIndex(unit);
323 SetRaidTargetIconTexture(frame.targeticon, index);
324 frame.targeticon:Show();
326 frame.targeticon:Hide();
331 ["UNIT_HEALTH"] = function(frame)
332 updateHealth(frame, frame.displayed);
333 updateHealthText(frame, frame.displayed);
334 if frame.shield then updateShield(frame, frame.displayed) end
335 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
337 ["UNIT_POWER"] = function(frame)
338 updatePower(frame, frame.displayed);
339 updatePowerText(frame, frame.displayed);
341 ["UNIT_AURA"] = function(frame)
342 updateAuras(frame, frame.displayed);
344 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
345 updateShield(frame, frame.displayed);
347 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
348 updateHealAbsorb(frame, frame.displayed);
350 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
351 updateAggro(frame, frame.displayed);
353 ["UNIT_MAXHEALTH"] = function(frame)
354 updateMaxHealth(frame, frame.displayed);
355 updateHealth(frame, frame.displayed);
356 updateHealthText(frame, frame.displayed);
357 if frame.shield then updateShield(frame, frame.displayed) end
358 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
360 ["UNIT_MAXPOWER"] = function(frame)
361 updateMaxPower(frame, frame.displayed);
362 updatePower(frame, frame.displayed);
363 updatePowerText(frame, frame.displayed);
365 ["UNIT_DISPLAYPOWER"] = function(frame)
366 updatePowerColor(frame, frame.displayed);
367 updateMaxPower(frame, frame.displayed);
368 updatePower(frame, frame.displayed);
369 updatePowerText(frame, frame.displayed);
371 ["UNIT_NAME_UPDATE"] = function(frame)
372 if frame.name then updateName(frame, frame.displayed) end
373 updateHealthColor(frame, frame.displayed);
375 ["UNIT_CONNECTION"] = function(frame)
376 updateHealthText(frame, frame.displayed);
377 updatePowerText(frame, frame.displayed);
379 ["UNIT_LEVEL"] = function(frame)
380 -- if this is registered, frame has frame.level
381 updateLevelText(frame, frame.unit);
383 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
384 updateLevelText(frame, frame.unit, arg1);
386 ["PLAYER_UPDATE_RESTING"] = function(frame)
387 -- player frame has frame.status
388 updateStatus(frame, frame.unit);
390 ["PLAYER_REGEN_DISABLED"] = function(frame)
391 frame.inCombat = true;
392 if frame.status then updateStatus(frame, frame.unit) end
394 ["PLAYER_REGEN_ENABLED"] = function(frame)
395 frame.inCombat = false;
396 if frame.status then updateStatus(frame, frame.unit) end
398 ["UNIT_FACTION"] = function(frame)
399 if frame.pvp then updatePVP(frame, frame.unit) end
400 updateHealthColor(frame, frame.displayed);
402 ["PARTY_LEADER_CHANGED"] = function(frame)
403 updateLeaderIcon(frame, frame.unit);
405 ["RAID_TARGET_UPDATE"] = function(frame)
406 updateRaidMarker(frame, frame.displayed);
408 ["UPDATE_ALL_BARS"] = function(frame)
409 if frame.vehicle then updateVehicle(frame) end
410 updateMaxHealth(frame, frame.displayed);
411 updateHealth(frame, frame.displayed);
412 updateHealthText(frame, frame.displayed);
413 updateHealthColor(frame, frame.displayed);
414 updateAggro(frame, frame.displayed);
415 updateRaidMarker(frame, frame.displayed);
417 updateMaxPower(frame, frame.displayed);
418 updatePower(frame, frame.displayed);
419 updatePowerText(frame, frame.displayed);
420 updatePowerColor(frame, frame.displayed);
422 if frame.auras then updateAuras(frame, frame.displayed) end
423 if frame.shield then updateShield(frame, frame.displayed) end
424 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
425 if frame.name then updateName(frame, frame.displayed) end
426 if frame.level then updateLevelText(frame, frame.unit) end
427 if frame.status then updateStatus(frame, frame.unit) end
428 if frame.pvp then updatePVP(frame, frame.unit) end
429 if frame.leader then updateLeaderIcon(frame, frame.unit) end
432 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
433 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
434 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
435 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
436 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
437 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
438 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
439 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
440 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
441 eventFuncs["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = eventFuncs["UPDATE_ALL_BARS"];
442 eventFuncs["UNIT_TARGETABLE_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
444 function M.UnitEvent(self, event, arg1)
445 eventFuncs[event](self, arg1);