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 updateAuras = 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);
65 M.UpdateMaxHealth = updateMaxHealth;
67 local function updateHealth(frame, unit)
68 local current, max = UnitHealth(unit), frame.health.max;
69 if current > max or max <= 0 then
70 -- somehow current health has gone over the maximum (missed maxhealth event)
71 frame.health:SetWidth(frame.width);
72 updateMaxHealth(frame, unit);
74 elseif current <= 0 or UnitIsDeadOrGhost(unit) then
77 frame.health:SetWidth(current/max*frame.width);
81 M.UpdateHealth = updateHealth;
83 local function updateHealthText(frame, unit)
84 if UnitIsDeadOrGhost(unit) then
85 frame.healthText:SetText("Dead");
86 elseif not UnitIsConnected(unit) then
87 frame.healthText:SetText("DC");
88 elseif frame.healthText.percent then
89 frame.healthText:SetFormattedText("%.1f", UnitHealth(unit)/frame.health.max*100);
91 local current = UnitHealth(unit);
92 if current > 1000000000 then -- 1.0B
93 frame.healthText:SetFormattedText("%.2fB", current / 1000000000);
94 elseif current > 1000000 then -- 1.0M
95 frame.healthText:SetFormattedText("%.2fM", current / 1000000);
96 elseif current > 1000 then -- 1K
97 frame.healthText:SetFormattedText("%.1fK", current / 1000);
99 frame.healthText:SetFormattedText("%d", current)
103 M.UpdateHealthText = updateHealthText;
105 local function updateMaxPower(frame, unit)
106 frame.mana.max = UnitPowerMax(unit);
108 M.UpdateMaxPower = updateMaxPower;
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);
123 M.UpdatePower = updatePower;
125 local function updatePowerText(frame, unit)
126 local current, max = UnitPower(unit), frame.mana.max;
127 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
128 frame.manaText:Hide();
129 elseif max > 0 and current > 0 and current < max then
130 frame.manaText:SetText(ceil(current/max*100));
131 frame.manaText:Show();
133 frame.manaText:Hide();
136 M.UpdatePowerText = updatePowerText;
138 local function updatePowerColor(frame, unit)
139 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
141 M.UpdatePowerColor = updatePowerColor;
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));
148 M.UpdateName = updateName;
150 local function updateShield(frame, unit)
151 local shield = UnitGetTotalAbsorbs(unit) or 0;
153 local space = frame.width - frame.health:GetWidth();
154 shield = (shield / frame.health.max) * frame.width;
157 frame.shieldhl:Show();
158 elseif space < shield then
159 frame.shield:SetWidth(space);
161 frame.shieldhl:Show();
163 frame.shield:SetWidth(shield);
165 frame.shieldhl:Hide();
169 frame.shieldhl:Hide();
172 M.UpdateShield = updateShield;
174 local function updateAggro(frame, unit)
175 local status = UnitThreatSituation(unit);
176 if status and status > 0 then
177 frame.base:SetVertexColor(GetThreatStatusColor(status));
179 frame.base:SetVertexColor(unpack(baseColor));
182 M.UpdateAggro = updateAggro;
184 -- only works for player frame
185 local function updateVehicle(frame)
186 local shouldTargetVehicle = UnitHasVehicleUI("player") and
187 UnitTargetsVehicleInRaidUI("player") and UnitExists("vehicle");
188 if shouldTargetVehicle then
189 if not frame.inVehicle then
190 frame.inVehicle = true;
191 frame.displayed = frame.vehicle;
192 registerUnitEvents(frame);
194 elseif frame.inVehicle then
195 frame.inVehicle = false;
196 frame.displayed = frame.unit;
197 registerUnitEvents(frame);
200 M.UpdateVehicle = updateVehicle;
202 local function updateLevelText(frame, unit, levelup)
205 frame.level:SetText(levelup);
207 local level = UnitLevel(unit);
208 local class = UnitClassification(unit);
209 local leveltext, classtext;
211 if class == "worldboss" then
219 if class == "rareelite" then
220 classtext = " Rare Elite";
221 elseif class == "elite" then
222 classtext = " Elite";
223 elseif class == "rare" then
228 frame.level:SetFormattedText("%s%s", leveltext, classtext);
231 M.UpdateLevelText = updateLevelText;
233 local function updateStatus(frame, unit)
234 -- coords from FrameXML/PlayerFrame.lua
235 if frame.inCombat or UnitAffectingCombat(unit) then
236 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
238 elseif unit == "player" and IsResting() then
239 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
245 M.UpdateStatus = updateStatus;
248 Alliance = "Interface\\TARGETINGFRAME\\UI-PVP-Alliance",
249 Horde = "Interface\\TARGETINGFRAME\\UI-PVP-Horde"
251 local function updatePVP(frame, unit)
252 if UnitIsPVPFreeForAll(unit) then
253 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
255 elseif UnitIsPVP(unit) then
256 local faction = UnitFactionGroup(unit);
257 if faction and faction ~= "Neutral" then
258 -- from FrameXML/PlayerFrame.lua, mercenary checks
259 if UnitIsMercenary(unit) then
260 if faction == "Horde" then
261 faction = "Alliance";
262 elseif faction == "Alliance" then
266 frame.pvp:SetTexture(pvpIcons[faction]);
275 M.UpdatePVP = updatePVP;
277 local function updateLeaderIcon(frame, unit)
278 if UnitIsGroupLeader(frame.unit) then
279 if HasLFGRestrictions() then
280 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
281 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
283 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
284 frame.leader:SetTexCoord(0, 1, 0, 1);
287 elseif UnitIsGroupAssistant(frame.unit) then
288 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
289 frame.leader:SetTexCoord(0, 1, 0, 1);
295 M.UpdateLeaderIcon = updateLeaderIcon;
297 local function updateHealthColor(frame, unit)
298 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
299 frame.health:SetVertexColor(0.5, 0.5, 0.5);
300 elseif UnitIsPlayer(unit) then
301 local _, class = UnitClass(unit);
302 local color = RAID_CLASS_COLORS[class];
304 frame.health:SetVertexColor(color.r, color.g, color.b)
306 frame.health:SetVertexColor(unpack(healthColor))
308 elseif UnitPlayerControlled(unit) then
309 frame.health:SetVertexColor(0, 1, 0);
311 frame.health:SetVertexColor(UnitSelectionColor(unit));
314 M.UpdateHealthColor = updateHealthColor;
316 local function updateRaidMarker(frame, unit)
317 local index = GetRaidTargetIndex(unit);
319 SetRaidTargetIconTexture(frame.targeticon, index);
320 frame.targeticon:Show();
322 frame.targeticon:Hide();
325 M.UpdateRaidMarker = updateRaidMarker;
328 ["UNIT_HEALTH"] = function(frame)
329 updateHealth(frame, frame.displayed);
330 updateHealthText(frame, frame.displayed);
331 if frame.shield then updateShield(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_THREAT_SITUATION_UPDATE"] = function(frame)
344 updateAggro(frame, frame.displayed);
346 ["UNIT_MAXHEALTH"] = function(frame)
347 updateMaxHealth(frame, frame.displayed);
348 updateHealth(frame, frame.displayed);
349 updateHealthText(frame, frame.displayed);
350 if frame.shield then updateShield(frame, frame.displayed) end
352 ["UNIT_MAXPOWER"] = function(frame)
353 updateMaxPower(frame, frame.displayed);
354 updatePower(frame, frame.displayed);
355 updatePowerText(frame, frame.displayed);
357 ["UNIT_DISPLAYPOWER"] = function(frame)
358 updatePowerColor(frame, frame.displayed);
359 updateMaxPower(frame, frame.displayed);
360 updatePower(frame, frame.displayed);
361 updatePowerText(frame, frame.displayed);
363 ["UNIT_NAME_UPDATE"] = function(frame)
364 if frame.name then updateName(frame, frame.displayed) end
365 updateHealthColor(frame, frame.displayed);
367 ["UNIT_CONNECTION"] = function(frame)
368 updateHealthText(frame, frame.displayed);
369 updatePowerText(frame, frame.displayed);
371 ["UNIT_LEVEL"] = function(frame)
372 -- if this is registered, frame has frame.level
373 updateLevelText(frame, frame.unit);
375 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
376 updateLevelText(frame, frame.unit, arg1);
378 ["PLAYER_UPDATE_RESTING"] = function(frame)
379 -- player frame has frame.status
380 updateStatus(frame, frame.unit);
382 ["PLAYER_REGEN_DISABLED"] = function(frame)
383 frame.inCombat = true;
384 if frame.status then updateStatus(frame, frame.unit) end
386 ["PLAYER_REGEN_ENABLED"] = function(frame)
387 frame.inCombat = false;
388 if frame.status then updateStatus(frame, frame.unit) end
390 ["UNIT_FACTION"] = function(frame)
391 if frame.pvp then updatePVP(frame, frame.unit) end
392 updateHealthColor(frame, frame.displayed);
394 ["PARTY_LEADER_CHANGED"] = function(frame)
395 updateLeaderIcon(frame, frame.unit);
397 ["RAID_TARGET_UPDATE"] = function(frame)
398 updateRaidMarker(frame, frame.displayed);
400 ["UPDATE_ALL_BARS"] = function(frame)
401 if frame.vehicle then updateVehicle(frame) end
402 updateMaxHealth(frame, frame.displayed);
403 updateHealth(frame, frame.displayed);
404 updateHealthText(frame, frame.displayed);
405 updateHealthColor(frame, frame.displayed);
406 updateAggro(frame, frame.displayed);
407 updateRaidMarker(frame, frame.displayed);
409 updateMaxPower(frame, frame.displayed);
410 updatePower(frame, frame.displayed);
411 updatePowerText(frame, frame.displayed);
412 updatePowerColor(frame, frame.displayed);
414 if frame.auras then updateAuras(frame, frame.displayed) end
415 if frame.shield then updateShield(frame, frame.displayed) end
416 if frame.name then updateName(frame, frame.displayed) end
417 if frame.level then updateLevelText(frame, frame.unit) end
418 if frame.status then updateStatus(frame, frame.unit) end
419 if frame.pvp then updatePVP(frame, frame.unit) end
420 if frame.leader then updateLeaderIcon(frame, frame.unit) end
423 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
424 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
425 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
426 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
427 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
428 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
429 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
430 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
431 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
432 eventFuncs["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = eventFuncs["UPDATE_ALL_BARS"];
433 eventFuncs["UNIT_TARGETABLE_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
435 function M.UnitEvent(self, event, arg1)
436 return eventFuncs[event](self, arg1);