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);
50 if frame.healpred then
51 frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed);
54 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
56 if frame.healabsorb then
57 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
60 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
62 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
63 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
64 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
65 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
67 local registerUnitEvents = M.RegisterUnitEvents;
69 local function updateMaxHealth(frame, unit)
70 frame.health.max = UnitHealthMax(unit);
73 local function updateHealth(frame, unit)
74 local current, max = UnitHealth(unit), frame.health.max;
75 if current > max or max <= 0 then
76 -- somehow current health has gone over the maximum (missed maxhealth event)
77 frame.health:SetWidth(frame.width);
78 updateMaxHealth(frame, unit);
80 elseif current <= 0 or UnitIsDeadOrGhost(unit) then
83 frame.health:SetWidth(current/max*frame.width);
88 local function updateHealthText(frame, unit)
89 if UnitIsDeadOrGhost(unit) then
90 frame.healthText:SetText("Dead");
91 elseif not UnitIsConnected(unit) then
92 frame.healthText:SetText("DC");
93 elseif frame.healthText.percent then
94 frame.healthText:SetFormattedText("%.1f", UnitHealth(unit)/frame.health.max*100);
96 local current = UnitHealth(unit);
97 if current > 1000000000 then -- 1.0B
98 frame.healthText:SetFormattedText("%.2fB", current / 1000000000);
99 elseif current > 1000000 then -- 1.0M
100 frame.healthText:SetFormattedText("%.2fM", current / 1000000);
101 elseif current > 1000 then -- 1K
102 frame.healthText:SetFormattedText("%.1fK", current / 1000);
104 frame.healthText:SetFormattedText("%d", current)
109 local function updateMaxPower(frame, unit)
110 frame.mana.max = UnitPowerMax(unit);
113 local function updatePower(frame, unit)
114 local current, max = UnitPower(unit), frame.mana.max;
117 elseif current > max or max <= 0 then
118 frame.mana:SetWidth(frame.width);
119 updateMaxPower(frame, unit);
122 frame.mana:SetWidth(current/max*frame.width);
127 local function updatePowerText(frame, unit)
128 local current, max = UnitPower(unit), frame.mana.max;
129 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
130 frame.manaText:Hide();
131 elseif max > 0 and current > 0 and current < max then
132 frame.manaText:SetText(ceil(current/max*100));
133 frame.manaText:Show();
135 frame.manaText:Hide();
139 local function updatePowerColor(frame, unit)
140 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
143 local function updateName(frame, unit)
144 local name = UnitName(unit);
145 if not name then return end
146 frame.name:SetText(ssub(name, 1, frame.name.count));
149 local function updateHealPred(frame, unit)
150 local incoming = UnitGetIncomingHeals(unit) or 0;
152 local space = frame.width - frame.health:GetWidth() + 1;
153 incoming = (incoming / frame.health.max) * frame.width;
154 frame.healpred:SetWidth(min(space, incoming));
155 frame.healpred:Show();
157 frame.healpred:Hide();
161 local function updateShield(frame, unit)
162 local shield = UnitGetTotalAbsorbs(unit) or 0;
164 local space = frame.width - frame.health:GetWidth();
165 shield = (shield / frame.health.max) * frame.width;
168 frame.shieldhl:Show();
169 elseif space < shield then
170 frame.shield:SetWidth(space);
172 frame.shieldhl:Show();
174 frame.shield:SetWidth(shield);
176 frame.shieldhl:Hide();
180 frame.shieldhl:Hide();
184 local function updateHealAbsorb(frame, unit)
185 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
187 local space = frame.health:GetWidth();
188 absorb = (absorb / frame.health.max) * frame.width;
189 frame.healabsorb:SetWidth(min(space, absorb));
190 frame.healabsorb:Show();
192 frame.healabsorb:Hide();
196 local function updateAuras(frame, unit)
197 if frame.auras then updateAuraFrames(frame, unit) end
200 local function updateAggro(frame, unit)
201 local status = UnitThreatSituation(unit);
202 if status and status > 0 then
203 frame.base:SetVertexColor(GetThreatStatusColor(status));
205 frame.base:SetVertexColor(unpack(baseColor));
209 -- only works for player frame
210 local function updateVehicle(frame)
211 local shouldTargetVehicle = UnitHasVehicleUI("player") and
212 UnitTargetsVehicleInRaidUI("player") and UnitExists("vehicle");
213 if shouldTargetVehicle then
214 if not frame.inVehicle then
215 frame.inVehicle = true;
216 frame.displayed = frame.vehicle;
217 registerUnitEvents(frame);
219 elseif frame.inVehicle then
220 frame.inVehicle = false;
221 frame.displayed = frame.unit;
222 registerUnitEvents(frame);
226 local function updateLevelText(frame, unit, levelup)
229 frame.level:SetText(levelup);
231 local level = UnitLevel(unit);
232 local class = UnitClassification(unit);
233 local leveltext, classtext;
235 if class == "worldboss" then
243 if class == "rareelite" then
244 classtext = " Rare Elite";
245 elseif class == "elite" then
246 classtext = " Elite";
247 elseif class == "rare" then
252 frame.level:SetFormattedText("%s%s", leveltext, classtext);
256 local function updateStatus(frame, unit)
257 -- coords from FrameXML/PlayerFrame.lua
258 if frame.inCombat or UnitAffectingCombat(unit) then
259 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
261 elseif unit == "player" and IsResting() then
262 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
269 local function updatePVP(frame, unit)
270 if UnitIsPVPFreeForAll(unit) then
271 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
273 elseif UnitIsPVP(unit) then
274 local faction = UnitFactionGroup(unit);
275 if faction and faction ~= "Neutral" then
276 -- from FrameXML/PlayerFrame.lua, mercenary checks
277 if UnitIsMercenary(unit) then
278 if faction == "Horde" then
279 faction = "Alliance";
280 elseif faction == "Alliance" then
284 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
294 local function updateLeaderIcon(frame, unit)
295 if UnitIsGroupLeader(frame.unit) then
296 if HasLFGRestrictions() then
297 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
298 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
300 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
301 frame.leader:SetTexCoord(0, 1, 0, 1);
304 elseif UnitIsGroupAssistant(frame.unit) then
305 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
306 frame.leader:SetTexCoord(0, 1, 0, 1);
313 local function updateHealthColor(frame, unit)
314 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
315 frame.health:SetVertexColor(0.5, 0.5, 0.5);
316 elseif UnitIsPlayer(unit) then
317 local _, class = UnitClass(unit);
318 local color = RAID_CLASS_COLORS[class];
320 frame.health:SetVertexColor(color.r, color.g, color.b)
322 frame.health:SetVertexColor(unpack(healthColor))
324 elseif UnitPlayerControlled(unit) then
325 frame.health:SetVertexColor(0, 1, 0);
327 frame.health:SetVertexColor(UnitSelectionColor(unit));
331 local function updateRaidMarker(frame, unit)
332 local index = GetRaidTargetIndex(unit);
334 SetRaidTargetIconTexture(frame.targeticon, index);
335 frame.targeticon:Show();
337 frame.targeticon:Hide();
342 ["UNIT_HEALTH"] = function(frame)
343 updateHealth(frame, frame.displayed);
344 updateHealthText(frame, frame.displayed);
345 if frame.shield then updateShield(frame, frame.displayed) end
346 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
348 ["UNIT_POWER"] = function(frame)
349 updatePower(frame, frame.displayed);
350 updatePowerText(frame, frame.displayed);
352 ["UNIT_AURA"] = function(frame)
353 updateAuras(frame, frame.displayed);
355 ["UNIT_HEAL_PREDICTION"] = function(frame)
356 updateHealPred(frame, frame.displayed);
358 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
359 updateShield(frame, frame.displayed);
361 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
362 updateHealAbsorb(frame, frame.displayed);
364 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
365 updateAggro(frame, frame.displayed);
367 ["UNIT_MAXHEALTH"] = function(frame)
368 updateMaxHealth(frame, frame.displayed);
369 updateHealth(frame, frame.displayed);
370 updateHealthText(frame, frame.displayed);
371 if frame.shield then updateShield(frame, frame.displayed) end
372 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
374 ["UNIT_MAXPOWER"] = function(frame)
375 updateMaxPower(frame, frame.displayed);
376 updatePower(frame, frame.displayed);
377 updatePowerText(frame, frame.displayed);
379 ["UNIT_DISPLAYPOWER"] = function(frame)
380 updatePowerColor(frame, frame.displayed);
381 updateMaxPower(frame, frame.displayed);
382 updatePower(frame, frame.displayed);
383 updatePowerText(frame, frame.displayed);
385 ["UNIT_NAME_UPDATE"] = function(frame)
386 if frame.name then updateName(frame, frame.displayed) end
387 updateHealthColor(frame, frame.displayed);
389 ["UNIT_CONNECTION"] = function(frame)
390 updateHealthText(frame, frame.displayed);
391 updatePowerText(frame, frame.displayed);
393 ["UNIT_LEVEL"] = function(frame)
394 -- if this is registered, frame has frame.level
395 updateLevelText(frame, frame.unit);
397 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
398 updateLevelText(frame, frame.unit, arg1);
400 ["PLAYER_UPDATE_RESTING"] = function(frame)
401 -- player frame has frame.status
402 updateStatus(frame, frame.unit);
404 ["PLAYER_REGEN_DISABLED"] = function(frame)
405 frame.inCombat = true;
406 if frame.status then updateStatus(frame, frame.unit) end
408 ["PLAYER_REGEN_ENABLED"] = function(frame)
409 frame.inCombat = false;
410 if frame.status then updateStatus(frame, frame.unit) end
412 ["UNIT_FACTION"] = function(frame)
413 if frame.pvp then updatePVP(frame, frame.unit) end
414 updateHealthColor(frame, frame.displayed);
416 ["PARTY_LEADER_CHANGED"] = function(frame)
417 updateLeaderIcon(frame, frame.unit);
419 ["RAID_TARGET_UPDATE"] = function(frame)
420 updateRaidMarker(frame, frame.displayed);
422 ["UPDATE_ALL_BARS"] = function(frame)
423 if frame.vehicle then updateVehicle(frame) end
424 updateMaxHealth(frame, frame.displayed);
425 updateHealth(frame, frame.displayed);
426 updateHealthText(frame, frame.displayed);
427 updateHealthColor(frame, frame.displayed);
428 updateAggro(frame, frame.displayed);
429 updateRaidMarker(frame, frame.displayed);
431 updateMaxPower(frame, frame.displayed);
432 updatePower(frame, frame.displayed);
433 updatePowerText(frame, frame.displayed);
434 updatePowerColor(frame, frame.displayed);
436 if frame.auras then updateAuras(frame, frame.displayed) end
437 if frame.shield then updateShield(frame, frame.displayed) end
438 if frame.healpred then updateHealPred(frame, frame.displayed) end
439 if frame.healabsorb then updateHealAbsorb(frame, frame.displayed) end
440 if frame.name then updateName(frame, frame.displayed) end
441 if frame.level then updateLevelText(frame, frame.unit) end
442 if frame.status then updateStatus(frame, frame.unit) end
443 if frame.pvp then updatePVP(frame, frame.unit) end
444 if frame.leader then updateLeaderIcon(frame, frame.unit) end
447 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
448 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
449 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
450 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
451 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
452 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
453 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
454 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
455 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
456 eventFuncs["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = eventFuncs["UPDATE_ALL_BARS"];
457 eventFuncs["UNIT_TARGETABLE_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
459 function M.UnitEvent(self, event, arg1)
460 eventFuncs[event](self, arg1);