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);
254 local function updatePVP(frame, unit)
255 if UnitIsPVPFreeForAll(unit) then
256 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
258 elseif UnitIsPVP(unit) then
259 local faction = UnitFactionGroup(unit);
260 if faction and faction ~= "Neutral" then
261 -- from FrameXML/PlayerFrame.lua, mercenary checks
262 if UnitIsMercenary(unit) then
263 if faction == "Horde" then
264 faction = "Alliance";
265 elseif faction == "Alliance" then
269 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
279 local function updateLeaderIcon(frame, unit)
280 if UnitIsGroupLeader(frame.unit) then
281 if HasLFGRestrictions() then
282 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
283 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
285 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
286 frame.leader:SetTexCoord(0, 1, 0, 1);
289 elseif UnitIsGroupAssistant(frame.unit) then
290 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
291 frame.leader:SetTexCoord(0, 1, 0, 1);
298 local function updateHealthColor(frame, unit)
299 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
300 frame.health:SetVertexColor(0.5, 0.5, 0.5);
301 elseif UnitIsPlayer(unit) then
302 local _, class = UnitClass(unit);
303 local color = RAID_CLASS_COLORS[class];
305 frame.health:SetVertexColor(color.r, color.g, color.b)
307 frame.health:SetVertexColor(unpack(healthColor))
309 elseif UnitPlayerControlled(unit) then
310 frame.health:SetVertexColor(0, 1, 0);
312 frame.health:SetVertexColor(UnitSelectionColor(unit));
316 local function updateRaidMarker(frame, unit)
317 local index = GetRaidTargetIndex(unit);
319 SetRaidTargetIconTexture(frame.targeticon, index);
320 frame.targeticon:Show();
322 frame.targeticon:Hide();
327 ["UNIT_HEALTH"] = function(frame)
328 updateHealth(frame, frame.displayed);
329 updateHealthText(frame, frame.displayed);
330 if frame.shield then updateShield(frame, frame.displayed) end
331 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
333 ["UNIT_POWER"] = function(frame)
334 updatePower(frame, frame.displayed);
335 updatePowerText(frame, frame.displayed);
337 ["UNIT_AURA"] = function(frame)
338 updateAuras(frame, frame.displayed);
340 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
341 updateShield(frame, frame.displayed);
343 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
344 updateHealAbsorb(frame, frame.displayed);
346 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
347 updateAggro(frame, frame.displayed);
349 ["UNIT_MAXHEALTH"] = function(frame)
350 updateMaxHealth(frame, frame.displayed);
351 updateHealth(frame, frame.displayed);
352 updateHealthText(frame, frame.displayed);
353 if frame.shield then updateShield(frame, frame.displayed) end
354 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
356 ["UNIT_MAXPOWER"] = function(frame)
357 updateMaxPower(frame, frame.displayed);
358 updatePower(frame, frame.displayed);
359 updatePowerText(frame, frame.displayed);
361 ["UNIT_DISPLAYPOWER"] = function(frame)
362 updatePowerColor(frame, frame.displayed);
363 updateMaxPower(frame, frame.displayed);
364 updatePower(frame, frame.displayed);
365 updatePowerText(frame, frame.displayed);
367 ["UNIT_NAME_UPDATE"] = function(frame)
368 if frame.name then updateName(frame, frame.displayed) end
369 updateHealthColor(frame, frame.displayed);
371 ["UNIT_CONNECTION"] = function(frame)
372 updateHealthText(frame, frame.displayed);
373 updatePowerText(frame, frame.displayed);
375 ["UNIT_LEVEL"] = function(frame)
376 -- if this is registered, frame has frame.level
377 updateLevelText(frame, frame.unit);
379 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
380 updateLevelText(frame, frame.unit, arg1);
382 ["PLAYER_UPDATE_RESTING"] = function(frame)
383 -- player frame has frame.status
384 updateStatus(frame, frame.unit);
386 ["PLAYER_REGEN_DISABLED"] = function(frame)
387 frame.inCombat = true;
388 if frame.status then updateStatus(frame, frame.unit) end
390 ["PLAYER_REGEN_ENABLED"] = function(frame)
391 frame.inCombat = false;
392 if frame.status then updateStatus(frame, frame.unit) end
394 ["UNIT_FACTION"] = function(frame)
395 if frame.pvp then updatePVP(frame, frame.unit) end
396 updateHealthColor(frame, frame.displayed);
398 ["PARTY_LEADER_CHANGED"] = function(frame)
399 updateLeaderIcon(frame, frame.unit);
401 ["RAID_TARGET_UPDATE"] = function(frame)
402 updateRaidMarker(frame, frame.displayed);
404 ["UPDATE_ALL_BARS"] = function(frame)
405 if frame.vehicle then updateVehicle(frame) end
406 updateMaxHealth(frame, frame.displayed);
407 updateHealth(frame, frame.displayed);
408 updateHealthText(frame, frame.displayed);
409 updateHealthColor(frame, frame.displayed);
410 updateAggro(frame, frame.displayed);
411 updateRaidMarker(frame, frame.displayed);
413 updateMaxPower(frame, frame.displayed);
414 updatePower(frame, frame.displayed);
415 updatePowerText(frame, frame.displayed);
416 updatePowerColor(frame, frame.displayed);
418 if frame.auras then updateAuras(frame, frame.displayed) end
419 if frame.shield then updateShield(frame, frame.displayed) end
420 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
421 if frame.name then updateName(frame, frame.displayed) end
422 if frame.level then updateLevelText(frame, frame.unit) end
423 if frame.status then updateStatus(frame, frame.unit) end
424 if frame.pvp then updatePVP(frame, frame.unit) end
425 if frame.leader then updateLeaderIcon(frame, frame.unit) end
428 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
429 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
430 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
431 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
432 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
433 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
434 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
435 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
436 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
437 eventFuncs["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = eventFuncs["UPDATE_ALL_BARS"];
438 eventFuncs["UNIT_TARGETABLE_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
440 function M.UnitEvent(self, event, arg1)
441 eventFuncs[event](self, arg1);