2 -- TODO -- recheck these, pvp functions not added yet
5 local ssub = string.sub;
7 local ceil = math.ceil;
8 local UnitName, UnitClass, UnitExists = UnitName, UnitClass, UnitExists;
9 local UnitDebuff, UnitIsCharmed, UnitIsFriend = UnitDebuff, UnitIsCharmed, UnitIsFriend;
10 local UnitPower, UnitPowerMax, UnitPowerType = UnitPower, UnitPowerMax, UnitPowerType;
11 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
12 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
13 local UnitThreatSituation, GetThreatStatusColor = UnitThreatSituation, GetThreatStatusColor;
14 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
15 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
16 local UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI;
17 local UnitGroupRolesAssigned = UnitGroupRolesAssigned;
18 local UnitLevel, UnitClassification = UnitLevel, UnitClassification;
19 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
21 local updateAuraFrames = OmaUFAuras.UpdateAuras;
23 local Settings = OmaUFSettings;
24 local baseColor = Settings.BaseColor;
25 local healthColor = Settings.HealthColor;
26 local powerColors = Settings.PowerColors;
30 function M.RegisterEvents(frame)
31 -- events are taken from FrameXML/CompactUnitFrame.lua
32 -- TODO raid marker support,
33 -- player flags support (/afk, /dnd)
34 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
35 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
36 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
37 frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed);
38 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
39 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
40 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", frame.unit, displayed);
42 frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", frame.unit, displayed);
43 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
44 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
45 frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed);
46 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
48 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
49 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
50 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
52 local registerEvents = M.RegisterEvents;
54 local function updateHealth(frame, unit)
55 local current, max = UnitHealth(unit), frame.health.max;
57 -- sanity check, occasionally UnitHealthMax gives zero
59 -- somehow current health has gone over the maximum (missed maxhealth event)
60 frame.health.max = UnitHealthMax(unit);
61 max = frame.health.max;
63 -- error state, still over maximum
64 frame.health:SetWidth(frame.width);
68 frame.health:SetWidth(current/frame.health.max*frame.width);
70 frame.health:SetWidth(frame.width);
74 if UnitIsDeadOrGhost(unit) then
79 local function updateHealthText(frame, unit)
80 local current, max = UnitHealth(unit), frame.health.max;
81 if UnitIsDeadOrGhost(unit) then
82 frame.healthText:SetText("Dead");
83 frame.healthText:Show();
84 elseif not UnitIsConnected(unit) then
85 frame.healthText:SetText("DC");
86 frame.healthText:Show();
88 if current > 1200000000 then -- 1.2B
89 frame.healthText:SetFormattedText("%.1fB", current / 1000000000);
90 elseif current > 1200000 then -- 1.2M
91 frame.healthText:SetFormattedText("%.1fM", current / 1000000);
92 elseif current > 1000 then -- 1K
93 frame.healthText:SetFormattedText("%.1fK", current / 1000);
95 frame.healthText:SetFormattedText("%d", current)
97 frame.healthText:Show();
99 frame.healthText:Hide();
103 local function updateMaxHealth(frame, unit)
104 frame.health.max = UnitHealthMax(unit);
107 local function updatePower(frame, unit)
108 local current, max = UnitPower(unit), frame.mana.max;
109 -- sanity check, occasionally UnitPowerMax gives zero
113 elseif current > max then
115 frame.mana.max = UnitPowerMax(unit);
116 max = frame.mana.max;
117 if current > max then
119 frame.mana:SetWidth(frame.width);
124 frame.mana:SetWidth(UnitPower(unit)/max*frame.width);
127 frame.mana:SetWidth(frame.width);
132 local function updatePowerText(frame, unit)
133 local current, max = UnitPower(unit), frame.mana.max;
134 if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
135 frame.healthText:Hide();
136 elseif max > 0 and current > 0 and current < max then
137 frame.manaText:SetText(ceil(current/max*100));
138 frame.manaText:Show();
140 frame.manaText:Hide();
144 local function updateMaxPower(frame, unit)
145 frame.mana.max = UnitPowerMax(unit);
148 local function updatePowerColor(frame, unit)
149 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
152 local function updateName(frame, unit)
153 if not frame.name then return end
154 local name = UnitName(unit);
155 if not name then return end
156 frame.name:SetText(ssub(name, 1, 10));
159 local function updateHealPred(frame, unit)
160 local incoming = UnitGetIncomingHeals(unit) or 0;
162 local max = frame.health.max;
163 local space = frame.width - frame.health:GetWidth() + 1;
164 local pred = (incoming / max) * frame.width;
165 frame.healpred:SetWidth(min(space, pred));
166 frame.healpred:Show();
168 frame.healpred:Hide();
172 local function updateShield(frame, unit)
173 local shield = UnitGetTotalAbsorbs(unit) or 0;
175 local max = frame.health.max;
176 local space = frame.width - frame.health:GetWidth();
177 shield = (shield / max) * frame.width;
180 frame.shieldhl:Show();
181 elseif space < shield then
182 frame.shield:SetWidth(space);
184 frame.shieldhl:Show();
186 frame.shield:SetWidth(shield);
188 frame.shieldhl:Hide();
192 frame.shieldhl:Hide();
196 local function updateHealAbsorb(frame, unit)
197 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
199 local max = frame.health.max;
200 local space = frame.health:GetWidth();
201 absorb = (absorb / max) * frame.width;
202 frame.healabsorb:SetWidth(min(space, absorb));
203 frame.healabsorb:Show();
205 frame.healabsorb:Hide();
209 local function updateAuras(frame, unit)
210 updateAuraFrames(frame, unit);
213 local function updateAggro(frame, unit)
214 local status = UnitThreatSituation(unit);
215 if status and status > 0 then
216 frame.base:SetVertexColor(GetThreatStatusColor(status));
218 frame.base:SetVertexColor(unpack(baseColor));
222 local function updateVehicle(frame)
223 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
224 if shouldTargetVehicle then
225 if not frame.inVehicle then
226 frame.inVehicle = true;
227 frame.displayed = frame.vehicle;
228 registerEvents(frame);
230 elseif frame.inVehicle then
231 frame.inVehicle = false;
232 frame.displayed = frame.unit;
233 registerEvents(frame);
237 local function updateRole(frame, unit)
238 local role = UnitGroupRolesAssigned(unit);
239 if role == "HEALER" or role == "TANK" or role == "DAMAGER" then
240 frame.role:SetTexCoord(GetTexCoordsForRoleSmallCircle(role));
247 local function updateLevelText(frame, unit, levelup)
248 if not frame.level then return end
251 frame.level:SetText(levelup);
253 local level = UnitLevel(unit);
254 local class = UnitClassification(unit);
255 local leveltext, classtext;
257 if class == "worldboss" then
265 if class == "rareelite" then
266 classtext = " Rare Elite";
267 elseif class == "elite" then
268 classtext = " Elite";
269 elseif class == "rare" then
274 frame.level:SetFormattedText("%s%s", leveltext, classtext);
278 local function updateStatus(frame, unit)
279 -- coords from PlayerFrame
280 if frame.inCombat or UnitAffectingCombat(unit) then
281 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
283 elseif unit == "player" and IsResting() then
284 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
291 local function updatePVP(frame, unit)
292 if UnitIsPVPFreeForAll(unit) then
293 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
295 elseif UnitIsPVP(unit) then
296 local faction = UnitFactionGroup(unit);
297 if faction and faction ~= "Neutral" then
298 -- from PlayerFrame, mercenary checks
299 if UnitIsMercenary(unit) then
300 if faction == "Horde" then
301 faction = "Alliance";
302 elseif faction == "Alliance" then
306 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
316 local function updateLeaderIcon(frame, unit)
317 if UnitIsGroupLeader(frame.unit) then
318 if HasLFGRestrictions() then
319 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
320 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
322 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
323 frame.leader:SetTexCoord(0, 1, 0, 1);
326 elseif UnitIsGroupAssistant(frame.unit) then
327 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
328 frame.leader:SetTexCoord(0, 1, 0, 1);
335 local function updateHealthColor(frame, unit)
336 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
337 frame.health:SetVertexColor(0.5, 0.5, 0.5);
338 elseif UnitIsPlayer(unit) then
339 local _, class = UnitClass(unit);
340 local color = RAID_CLASS_COLORS[class];
342 frame.health:SetVertexColor(color.r, color.g, color.b)
344 frame.health:SetVertexColor(unpack(healthColor))
346 elseif UnitPlayerControlled(unit) then
347 frame.health:SetVertexColor(0, 1, 0);
349 frame.health:SetVertexColor(UnitSelectionColor(unit));
354 ["UNIT_HEALTH"] = function(frame)
355 updateHealth(frame, frame.displayed);
356 updateHealthText(frame, frame.displayed);
357 updateShield(frame, frame.displayed);
358 updateHealAbsorb(frame, frame.displayed);
359 -- no heal prediction update, that doesn't overflow too much
361 ["UNIT_POWER"] = function(frame)
362 updatePower(frame, frame.displayed);
363 updatePowerText(frame, frame.displayed);
365 ["UNIT_AURA"] = function(frame)
366 updateAuras(frame, frame.displayed);
368 ["UNIT_HEAL_PREDICTION"] = function(frame)
369 updateHealPred(frame, frame.displayed);
371 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
372 updateShield(frame, frame.displayed);
374 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
375 updateHealAbsorb(frame, frame.displayed);
377 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
378 updateAggro(frame, frame.displayed);
380 ["UNIT_MAXHEALTH"] = function(frame)
381 updateMaxHealth(frame, frame.displayed);
382 updateHealth(frame, frame.displayed);
383 updateHealthText(frame, frame.displayed);
384 updateShield(frame, frame.displayed);
385 updateHealAbsorb(frame, frame.displayed);
387 ["UNIT_MAXPOWER"] = function(frame)
388 updateMaxPower(frame, frame.displayed);
389 updatePower(frame, frame.displayed);
390 updatePowerText(frame, frame.displayed);
392 ["UNIT_DISPLAYPOWER"] = function(frame)
393 updatePowerColor(frame, frame.displayed);
394 updateMaxPower(frame, frame.displayed);
395 updatePower(frame, frame.displayed);
396 updatePowerText(frame, frame.displayed);
398 ["UNIT_NAME_UPDATE"] = function(frame)
399 updateName(frame, frame.displayed);
400 updateHealthColor(frame, frame.displayed);
402 ["UNIT_CONNECTION"] = function(frame)
403 updateHealthText(frame, frame.displayed);
404 updatePowerText(frame, frame.displayed);
406 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
407 updateRole(frame, frame.unit);
409 ["UNIT_LEVEL"] = function(frame)
410 updateLevelText(frame, frame.unit);
412 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
413 updateLevelText(frame, frame.unit, arg1);
415 ["PLAYER_UPDATE_RESTING"] = function(frame)
416 updateStatus(frame, frame.unit);
418 ["PLAYER_REGEN_DISABLED"] = function(frame)
419 frame.inCombat = true;
420 updateStatus(frame, frame.unit);
422 ["PLAYER_REGEN_ENABLED"] = function(frame)
423 frame.inCombat = false;
424 updateStatus(frame, frame.unit);
426 ["UNIT_FACTION"] = function(frame)
427 updatePVP(frame, frame.unit);
428 updateHealthColor(frame, frame.displayed);
430 ["PARTY_LEADER_CHANGED"] = function(frame)
431 updateLeaderIcon(frame, frame.unit);
433 ["UPDATE_ALL_BARS"] = function(frame)
434 updateVehicle(frame);
435 updateMaxHealth(frame, frame.displayed);
436 updateMaxPower(frame, frame.displayed);
437 updateHealth(frame, frame.displayed);
438 updateHealthText(frame, frame.displayed);
439 updatePower(frame, frame.displayed);
440 updatePowerText(frame, frame.displayed);
441 updateAuras(frame, frame.displayed);
442 updateShield(frame, frame.displayed);
443 updateHealPred(frame, frame.displayed);
444 updateHealAbsorb(frame, frame.displayed);
445 updatePowerColor(frame, frame.displayed);
446 updateAggro(frame, frame.displayed);
447 updateName(frame, frame.displayed);
448 updateRole(frame, frame.unit);
449 updateLevelText(frame, frame.unit);
450 updateStatus(frame, frame.unit);
451 updatePVP(frame, frame.unit);
452 updateLeaderIcon(frame, frame.unit);
453 updateHealthColor(frame, frame.displayed);
456 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
457 eventFuncs["UNIT_POWER_BAR_SHOW"] = eventFuncs["UNIT_DISPLAYPOWER"];
458 eventFuncs["UNIT_POWER_BAR_HIDE"] = eventFuncs["UNIT_DISPLAYPOWER"];
459 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
460 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
461 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
462 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
463 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
464 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
466 function M.UnitEvent(self, event, arg1)
467 eventFuncs[event](self, arg1);