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 UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI;
14 local UnitLevel, UnitClassification = UnitLevel, UnitClassification;
15 local UnitAffectingCombat, IsResting = UnitAffectingCombat, IsResting;
16 local UnitIsPVPFreeForAll, UnitIsPVP = UnitIsPVPFreeForAll, UnitIsPVP;
17 local UnitFactionGroup, UnitIsMercenary = UnitFactionGroup, UnitIsMercenary;
18 local UnitIsGroupLeader, UnitIsGroupAssistant = UnitIsGroupLeader, UnitIsGroupAssistant;
19 local HasLFGRestrictions = HasLFGRestrictions;
20 local UnitPlayerControlled, UnitIsPlayer = UnitPlayerControlled, UnitIsPlayer;
21 local UnitIsTapDenied, UnitSelectionColor = UnitIsTapDenied, UnitSelectionColor;
22 local GetRaidTargetIndex, SetRaidTargetIconTexture = GetRaidTargetIndex, SetRaidTargetIconTexture;
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 and FrameXML/TargetFrame.lua
36 -- TODO player flags support (/afk, /dnd)
37 frame:RegisterEvent("RAID_TARGET_UPDATE"); -- have to register all and just check
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);
43 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
44 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
45 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed);
46 frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", frame.unit, displayed);
50 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
53 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
55 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
56 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
57 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
58 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
60 local registerUnitEvents = M.RegisterUnitEvents;
62 local function updateMaxHealth(frame, unit)
63 frame.health.max = UnitHealthMax(unit);
66 local function updateHealth(frame, unit)
67 local current, max = UnitHealth(unit), frame.health.max;
68 if current > max or max <= 0 then
69 -- somehow current health has gone over the maximum (missed maxhealth event)
70 frame.health:SetWidth(frame.width);
71 updateMaxHealth(frame, unit);
73 elseif current <= 0 or UnitIsDeadOrGhost(unit) then
76 frame.health:SetWidth(current/max*frame.width);
81 local function updateHealthText(frame, unit)
82 if UnitIsDeadOrGhost(unit) then
83 frame.healthText:SetText("Dead");
84 elseif not UnitIsConnected(unit) then
85 frame.healthText:SetText("DC");
86 elseif frame.healthText.percent then
87 frame.healthText:SetFormattedText("%.1f", UnitHealth(unit)/frame.health.max*100);
89 local current = UnitHealth(unit);
90 if current > 1000000000 then -- 1.0B
91 frame.healthText:SetFormattedText("%.2fB", current / 1000000000);
92 elseif current > 1000000 then -- 1.0M
93 frame.healthText:SetFormattedText("%.2fM", current / 1000000);
94 elseif current > 1000 then -- 1K
95 frame.healthText:SetFormattedText("%.1fK", current / 1000);
97 frame.healthText:SetFormattedText("%d", current)
102 local function updateMaxPower(frame, unit)
103 frame.mana.max = UnitPowerMax(unit);
106 local function updatePower(frame, unit)
107 local current, max = UnitPower(unit), frame.mana.max;
110 elseif current > max or max <= 0 then
111 frame.mana:SetWidth(frame.width);
112 updateMaxPower(frame, unit);
115 frame.mana:SetWidth(current/max*frame.width);
120 local function updatePowerText(frame, unit)
121 local current, max = UnitPower(unit), frame.mana.max;
122 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
123 frame.manaText:Hide();
124 elseif max > 0 and current > 0 and current < max then
125 frame.manaText:SetText(ceil(current/max*100));
126 frame.manaText:Show();
128 frame.manaText:Hide();
132 local function updatePowerColor(frame, unit)
133 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
136 local function updateName(frame, unit)
137 local name = UnitName(unit);
138 if not name then return end
139 frame.name:SetText(ssub(name, 1, frame.name.count));
142 local function updateShield(frame, unit)
143 local shield = UnitGetTotalAbsorbs(unit) or 0;
145 local space = frame.width - frame.health:GetWidth();
146 shield = (shield / frame.health.max) * frame.width;
149 frame.shieldhl:Show();
150 elseif space < shield then
151 frame.shield:SetWidth(space);
153 frame.shieldhl:Show();
155 frame.shield:SetWidth(shield);
157 frame.shieldhl:Hide();
161 frame.shieldhl:Hide();
165 local function updateAuras(frame, unit)
166 updateAuraFrames(frame, unit);
169 local function updateAggro(frame, unit)
170 local status = UnitThreatSituation(unit);
171 if status and status > 0 then
172 frame.base:SetVertexColor(GetThreatStatusColor(status));
174 frame.base:SetVertexColor(unpack(baseColor));
178 -- only works for player frame
179 local function updateVehicle(frame)
180 local shouldTargetVehicle = UnitHasVehicleUI("player") and
181 UnitTargetsVehicleInRaidUI("player") and UnitExists("vehicle");
182 if shouldTargetVehicle then
183 if not frame.inVehicle then
184 frame.inVehicle = true;
185 frame.displayed = frame.vehicle;
186 registerUnitEvents(frame);
188 elseif frame.inVehicle then
189 frame.inVehicle = false;
190 frame.displayed = frame.unit;
191 registerUnitEvents(frame);
195 local function updateLevelText(frame, unit, levelup)
198 frame.level:SetText(levelup);
200 local level = UnitLevel(unit);
201 local class = UnitClassification(unit);
202 local leveltext, classtext;
204 if class == "worldboss" then
212 if class == "rareelite" then
213 classtext = " Rare Elite";
214 elseif class == "elite" then
215 classtext = " Elite";
216 elseif class == "rare" then
221 frame.level:SetFormattedText("%s%s", leveltext, classtext);
225 local function updateStatus(frame, unit)
226 -- coords from FrameXML/PlayerFrame.lua
227 if frame.inCombat or UnitAffectingCombat(unit) then
228 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
230 elseif unit == "player" and IsResting() then
231 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
239 Alliance = "Interface\\TARGETINGFRAME\\UI-PVP-Alliance",
240 Horde = "Interface\\TARGETINGFRAME\\UI-PVP-Horde"
242 local function updatePVP(frame, unit)
243 if UnitIsPVPFreeForAll(unit) then
244 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
246 elseif UnitIsPVP(unit) then
247 local faction = UnitFactionGroup(unit);
248 if faction and faction ~= "Neutral" then
249 -- from FrameXML/PlayerFrame.lua, mercenary checks
250 if UnitIsMercenary(unit) then
251 if faction == "Horde" then
252 faction = "Alliance";
253 elseif faction == "Alliance" then
257 frame.pvp:SetTexture(pvpIcons[faction]);
267 local function updateLeaderIcon(frame, unit)
268 if UnitIsGroupLeader(frame.unit) then
269 if HasLFGRestrictions() then
270 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
271 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
273 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
274 frame.leader:SetTexCoord(0, 1, 0, 1);
277 elseif UnitIsGroupAssistant(frame.unit) then
278 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
279 frame.leader:SetTexCoord(0, 1, 0, 1);
286 local function updateHealthColor(frame, unit)
287 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
288 frame.health:SetVertexColor(0.5, 0.5, 0.5);
289 elseif UnitIsPlayer(unit) then
290 local _, class = UnitClass(unit);
291 local color = RAID_CLASS_COLORS[class];
293 frame.health:SetVertexColor(color.r, color.g, color.b)
295 frame.health:SetVertexColor(unpack(healthColor))
297 elseif UnitPlayerControlled(unit) then
298 frame.health:SetVertexColor(0, 1, 0);
300 frame.health:SetVertexColor(UnitSelectionColor(unit));
304 local function updateRaidMarker(frame, unit)
305 local index = GetRaidTargetIndex(unit);
307 SetRaidTargetIconTexture(frame.targeticon, index);
308 frame.targeticon:Show();
310 frame.targeticon:Hide();
315 ["UNIT_HEALTH"] = function(frame)
316 updateHealth(frame, frame.displayed);
317 updateHealthText(frame, frame.displayed);
318 if frame.shield then updateShield(frame, frame.displayed) end
320 ["UNIT_POWER"] = function(frame)
321 updatePower(frame, frame.displayed);
322 updatePowerText(frame, frame.displayed);
324 ["UNIT_AURA"] = function(frame)
325 updateAuras(frame, frame.displayed);
327 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
328 updateShield(frame, frame.displayed);
330 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
331 updateAggro(frame, frame.displayed);
333 ["UNIT_MAXHEALTH"] = function(frame)
334 updateMaxHealth(frame, frame.displayed);
335 updateHealth(frame, frame.displayed);
336 updateHealthText(frame, frame.displayed);
337 if frame.shield then updateShield(frame, frame.displayed) end
339 ["UNIT_MAXPOWER"] = function(frame)
340 updateMaxPower(frame, frame.displayed);
341 updatePower(frame, frame.displayed);
342 updatePowerText(frame, frame.displayed);
344 ["UNIT_DISPLAYPOWER"] = function(frame)
345 updatePowerColor(frame, frame.displayed);
346 updateMaxPower(frame, frame.displayed);
347 updatePower(frame, frame.displayed);
348 updatePowerText(frame, frame.displayed);
350 ["UNIT_NAME_UPDATE"] = function(frame)
351 if frame.name then updateName(frame, frame.displayed) end
352 updateHealthColor(frame, frame.displayed);
354 ["UNIT_CONNECTION"] = function(frame)
355 updateHealthText(frame, frame.displayed);
356 updatePowerText(frame, frame.displayed);
358 ["UNIT_LEVEL"] = function(frame)
359 -- if this is registered, frame has frame.level
360 updateLevelText(frame, frame.unit);
362 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
363 updateLevelText(frame, frame.unit, arg1);
365 ["PLAYER_UPDATE_RESTING"] = function(frame)
366 -- player frame has frame.status
367 updateStatus(frame, frame.unit);
369 ["PLAYER_REGEN_DISABLED"] = function(frame)
370 frame.inCombat = true;
371 if frame.status then updateStatus(frame, frame.unit) end
373 ["PLAYER_REGEN_ENABLED"] = function(frame)
374 frame.inCombat = false;
375 if frame.status then updateStatus(frame, frame.unit) end
377 ["UNIT_FACTION"] = function(frame)
378 if frame.pvp then updatePVP(frame, frame.unit) end
379 updateHealthColor(frame, frame.displayed);
381 ["PARTY_LEADER_CHANGED"] = function(frame)
382 updateLeaderIcon(frame, frame.unit);
384 ["RAID_TARGET_UPDATE"] = function(frame)
385 updateRaidMarker(frame, frame.displayed);
387 ["UPDATE_ALL_BARS"] = function(frame)
388 if frame.vehicle then updateVehicle(frame) end
389 updateMaxHealth(frame, frame.displayed);
390 updateHealth(frame, frame.displayed);
391 updateHealthText(frame, frame.displayed);
392 updateHealthColor(frame, frame.displayed);
393 updateAggro(frame, frame.displayed);
394 updateRaidMarker(frame, frame.displayed);
396 updateMaxPower(frame, frame.displayed);
397 updatePower(frame, frame.displayed);
398 updatePowerText(frame, frame.displayed);
399 updatePowerColor(frame, frame.displayed);
401 if frame.auras then updateAuras(frame, frame.displayed) end
402 if frame.shield then updateShield(frame, frame.displayed) end
403 if frame.name then updateName(frame, frame.displayed) end
404 if frame.level then updateLevelText(frame, frame.unit) end
405 if frame.status then updateStatus(frame, frame.unit) end
406 if frame.pvp then updatePVP(frame, frame.unit) end
407 if frame.leader then updateLeaderIcon(frame, frame.unit) end
410 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
411 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
412 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
413 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
414 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
415 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
416 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
417 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
418 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
419 eventFuncs["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = eventFuncs["UPDATE_ALL_BARS"];
420 eventFuncs["UNIT_TARGETABLE_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
422 function M.UnitEvent(self, event, arg1)
423 eventFuncs[event](self, arg1);