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);
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 updateAuras(frame, unit)
175 updateAuraFrames(frame, unit);
177 M.UpdateAuras = updateAuras;
179 local function updateAggro(frame, unit)
180 local status = UnitThreatSituation(unit);
181 if status and status > 0 then
182 frame.base:SetVertexColor(GetThreatStatusColor(status));
184 frame.base:SetVertexColor(unpack(baseColor));
187 M.UpdateAggro = updateAggro;
189 -- only works for player frame
190 local function updateVehicle(frame)
191 local shouldTargetVehicle = UnitHasVehicleUI("player") and
192 UnitTargetsVehicleInRaidUI("player") and UnitExists("vehicle");
193 if shouldTargetVehicle then
194 if not frame.inVehicle then
195 frame.inVehicle = true;
196 frame.displayed = frame.vehicle;
197 registerUnitEvents(frame);
199 elseif frame.inVehicle then
200 frame.inVehicle = false;
201 frame.displayed = frame.unit;
202 registerUnitEvents(frame);
205 M.UpdateVehicle = updateVehicle;
207 local function updateLevelText(frame, unit, levelup)
210 frame.level:SetText(levelup);
212 local level = UnitLevel(unit);
213 local class = UnitClassification(unit);
214 local leveltext, classtext;
216 if class == "worldboss" then
224 if class == "rareelite" then
225 classtext = " Rare Elite";
226 elseif class == "elite" then
227 classtext = " Elite";
228 elseif class == "rare" then
233 frame.level:SetFormattedText("%s%s", leveltext, classtext);
236 M.UpdateLevelText = updateLevelText;
238 local function updateStatus(frame, unit)
239 -- coords from FrameXML/PlayerFrame.lua
240 if frame.inCombat or UnitAffectingCombat(unit) then
241 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
243 elseif unit == "player" and IsResting() then
244 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
250 M.UpdateStatus = updateStatus;
253 Alliance = "Interface\\TARGETINGFRAME\\UI-PVP-Alliance",
254 Horde = "Interface\\TARGETINGFRAME\\UI-PVP-Horde"
256 local function updatePVP(frame, unit)
257 if UnitIsPVPFreeForAll(unit) then
258 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
260 elseif UnitIsPVP(unit) then
261 local faction = UnitFactionGroup(unit);
262 if faction and faction ~= "Neutral" then
263 -- from FrameXML/PlayerFrame.lua, mercenary checks
264 if UnitIsMercenary(unit) then
265 if faction == "Horde" then
266 faction = "Alliance";
267 elseif faction == "Alliance" then
271 frame.pvp:SetTexture(pvpIcons[faction]);
280 M.UpdatePVP = updatePVP;
282 local function updateLeaderIcon(frame, unit)
283 if UnitIsGroupLeader(frame.unit) then
284 if HasLFGRestrictions() then
285 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
286 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
288 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
289 frame.leader:SetTexCoord(0, 1, 0, 1);
292 elseif UnitIsGroupAssistant(frame.unit) then
293 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
294 frame.leader:SetTexCoord(0, 1, 0, 1);
300 M.UpdateLeaderIcon = updateLeaderIcon;
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));
319 M.UpdateHealthColor = updateHealthColor;
321 local function updateRaidMarker(frame, unit)
322 local index = GetRaidTargetIndex(unit);
324 SetRaidTargetIconTexture(frame.targeticon, index);
325 frame.targeticon:Show();
327 frame.targeticon:Hide();
330 M.UpdateRaidMarker = updateRaidMarker;
333 ["UNIT_HEALTH"] = function(frame)
334 updateHealth(frame, frame.displayed);
335 updateHealthText(frame, frame.displayed);
336 if frame.shield then updateShield(frame, frame.displayed) end
338 ["UNIT_POWER"] = function(frame)
339 updatePower(frame, frame.displayed);
340 updatePowerText(frame, frame.displayed);
342 ["UNIT_AURA"] = function(frame)
343 updateAuras(frame, frame.displayed);
345 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
346 updateShield(frame, frame.displayed);
348 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
349 updateAggro(frame, frame.displayed);
351 ["UNIT_MAXHEALTH"] = function(frame)
352 updateMaxHealth(frame, frame.displayed);
353 updateHealth(frame, frame.displayed);
354 updateHealthText(frame, frame.displayed);
355 if frame.shield then updateShield(frame, frame.displayed) end
357 ["UNIT_MAXPOWER"] = function(frame)
358 updateMaxPower(frame, frame.displayed);
359 updatePower(frame, frame.displayed);
360 updatePowerText(frame, frame.displayed);
362 ["UNIT_DISPLAYPOWER"] = function(frame)
363 updatePowerColor(frame, frame.displayed);
364 updateMaxPower(frame, frame.displayed);
365 updatePower(frame, frame.displayed);
366 updatePowerText(frame, frame.displayed);
368 ["UNIT_NAME_UPDATE"] = function(frame)
369 if frame.name then updateName(frame, frame.displayed) end
370 updateHealthColor(frame, frame.displayed);
372 ["UNIT_CONNECTION"] = function(frame)
373 updateHealthText(frame, frame.displayed);
374 updatePowerText(frame, frame.displayed);
376 ["UNIT_LEVEL"] = function(frame)
377 -- if this is registered, frame has frame.level
378 updateLevelText(frame, frame.unit);
380 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
381 updateLevelText(frame, frame.unit, arg1);
383 ["PLAYER_UPDATE_RESTING"] = function(frame)
384 -- player frame has frame.status
385 updateStatus(frame, frame.unit);
387 ["PLAYER_REGEN_DISABLED"] = function(frame)
388 frame.inCombat = true;
389 if frame.status then updateStatus(frame, frame.unit) end
391 ["PLAYER_REGEN_ENABLED"] = function(frame)
392 frame.inCombat = false;
393 if frame.status then updateStatus(frame, frame.unit) end
395 ["UNIT_FACTION"] = function(frame)
396 if frame.pvp then updatePVP(frame, frame.unit) end
397 updateHealthColor(frame, frame.displayed);
399 ["PARTY_LEADER_CHANGED"] = function(frame)
400 updateLeaderIcon(frame, frame.unit);
402 ["RAID_TARGET_UPDATE"] = function(frame)
403 updateRaidMarker(frame, frame.displayed);
405 ["UPDATE_ALL_BARS"] = function(frame)
406 if frame.vehicle then updateVehicle(frame) end
407 updateMaxHealth(frame, frame.displayed);
408 updateHealth(frame, frame.displayed);
409 updateHealthText(frame, frame.displayed);
410 updateHealthColor(frame, frame.displayed);
411 updateAggro(frame, frame.displayed);
412 updateRaidMarker(frame, frame.displayed);
414 updateMaxPower(frame, frame.displayed);
415 updatePower(frame, frame.displayed);
416 updatePowerText(frame, frame.displayed);
417 updatePowerColor(frame, frame.displayed);
419 if frame.auras then updateAuras(frame, frame.displayed) end
420 if frame.shield then updateShield(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 return eventFuncs[event](self, arg1);