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;
27 local width = Settings.Width;
31 function M.RegisterEvents(frame)
32 -- events are taken from FrameXML/CompactUnitFrame.lua
33 -- TODO raid marker support,
34 -- player flags support (/afk, /dnd)
35 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
36 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
37 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
38 frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed);
39 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
40 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", frame.unit, displayed);
42 frame:RegisterUnitEvent("UNIT_POWER_BAR_SHOW", frame.unit, displayed);
43 frame:RegisterUnitEvent("UNIT_POWER_BAR_HIDE", frame.unit, displayed);
44 frame:RegisterUnitEvent("UNIT_NAME_UPDATE", frame.unit, displayed);
45 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
46 frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
48 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
49 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
50 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
51 frame:RegisterUnitEvent("UNIT_FACTION", frame.unit, displayed);
53 local registerEvents = M.RegisterEvents;
55 local function updateHealth(frame, unit)
56 local current, max = UnitHealth(unit), frame.health.max;
58 -- sanity check, occasionally UnitHealthMax gives zero
60 -- somehow current health has gone over the maximum (missed maxhealth event)
61 frame.health.max = UnitHealthMax(unit);
62 max = frame.health.max;
64 -- error state, still over maximum
65 frame.health:SetWidth(width);
69 frame.health:SetWidth(current/frame.health.max*width);
71 frame.health:SetWidth(width);
75 if UnitIsDeadOrGhost(unit) then
80 local function updateHealthText(frame, unit)
81 local current, max = UnitHealth(unit), frame.health.max;
82 if UnitIsDeadOrGhost(unit) then
83 frame.healthText:SetText("Dead");
84 frame.healthText:Show();
85 elseif not UnitIsConnected(unit) then
86 frame.healthText:SetText("DC");
87 frame.healthText:Show();
88 elseif max > 0 and current < max then
89 frame.healthText:SetText(ceil(current/max*100));
90 frame.healthText:Show();
92 frame.healthText:Hide();
96 local function updateMaxHealth(frame, unit)
97 frame.health.max = UnitHealthMax(unit);
100 local function updatePower(frame, unit)
101 local current, max = UnitPower(unit), frame.mana.max;
102 -- sanity check, occasionally UnitPowerMax gives zero
106 elseif current > max then
108 frame.mana.max = UnitPowerMax(unit);
109 max = frame.mana.max;
110 if current > max then
112 frame.mana:SetWidth(width);
117 frame.mana:SetWidth(UnitPower(unit)/max*width);
120 frame.mana:SetWidth(width);
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.healthText: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();
137 local function updateMaxPower(frame, unit)
138 frame.mana.max = UnitPowerMax(unit);
141 local function updatePowerColor(frame, unit)
142 frame.mana:SetVertexColor(unpack(powerColors[UnitPowerType(unit)]));
145 local function updateName(frame, unit)
146 local name = UnitName(unit);
147 if not name then return end
148 frame.name:SetText(ssub(name, 1, 10));
151 local function updateHealPred(frame, unit)
152 local incoming = UnitGetIncomingHeals(unit) or 0;
154 local max = frame.health.max;
155 local space = width - frame.health:GetWidth() + 1;
156 local pred = (incoming / max) * width;
157 frame.healpred:SetWidth(min(space, pred));
158 frame.healpred:Show();
160 frame.healpred:Hide();
164 local function updateShield(frame, unit)
165 local shield = UnitGetTotalAbsorbs(unit) or 0;
167 local max = frame.health.max;
168 local space = width - frame.health:GetWidth();
169 shield = (shield / max) * width;
172 frame.shieldhl:Show();
173 elseif space < shield then
174 frame.shield:SetWidth(space);
176 frame.shieldhl:Show();
178 frame.shield:SetWidth(shield);
180 frame.shieldhl:Hide();
184 frame.shieldhl:Hide();
188 local function updateHealAbsorb(frame, unit)
189 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
191 local max = frame.health.max;
192 local space = frame.health:GetWidth();
193 absorb = (absorb / max) * width;
194 frame.healabsorb:SetWidth(min(space, absorb));
195 frame.healabsorb:Show();
197 frame.healabsorb:Hide();
201 local function updateAuras(frame, unit)
202 updateAuraFrames(frame, unit);
205 local function updateAggro(frame, unit)
206 local status = UnitThreatSituation(unit);
207 if status and status > 0 then
208 frame.base:SetVertexColor(GetThreatStatusColor(status));
210 frame.base:SetVertexColor(unpack(baseColor));
214 local function updateVehicle(frame)
215 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
216 if shouldTargetVehicle then
217 if not frame.inVehicle then
218 frame.inVehicle = true;
219 frame.displayed = frame.vehicle;
220 registerEvents(frame);
222 elseif frame.inVehicle then
223 frame.inVehicle = false;
224 frame.displayed = frame.unit;
225 registerEvents(frame);
229 local function updateRole(frame, unit)
230 local role = UnitGroupRolesAssigned(unit);
231 if role == "HEALER" or role == "TANK" or role == "DAMAGER" then
232 frame.role:SetTexCoord(GetTexCoordsForRoleSmallCircle(role));
239 local function updateLevelText(frame, unit, levelup)
242 frame.level:SetText(levelup);
244 local level = UnitLevel(unit);
245 local class = UnitClassification(unit);
246 local leveltext, classtext;
248 if class == "worldboss" then
256 if class == "rareelite" then
257 classtext = " Rare Elite";
258 elseif class == "elite" then
259 classtext = " Elite";
260 elseif class == "rare" then
265 frame.level:SetFormattedText("%s%s", leveltext, classtext);
269 local function updateStatus(frame, unit)
270 -- coords from PlayerFrame
271 if frame.inCombat or UnitAffectingCombat(unit) then
272 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
274 elseif unit == "player" and IsResting() then
275 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
282 local function updatePVP(frame, unit)
283 if UnitIsPVPFreeForAll(unit) then
284 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
286 elseif UnitIsPVP(unit) then
287 local faction = UnitFactionGroup(unit);
288 if faction and faction ~= "Neutral" then
289 -- from PlayerFrame, mercenary checks
290 if UnitIsMercenary(unit) then
291 if faction == "Horde" then
292 faction = "Alliance";
293 elseif faction == "Alliance" then
297 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
307 local function updateLeaderIcon(frame, unit)
308 if UnitIsGroupLeader(frame.unit) then
309 if HasLFGRestrictions() then
310 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
311 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
313 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
314 frame.leader:SetTexCoord(0, 1, 0, 1);
317 elseif UnitIsGroupAssistant(frame.unit) then
318 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
319 frame.leader:SetTexCoord(0, 1, 0, 1);
326 local function updateHealthColor(frame, unit)
327 if not UnitPlayerControlled(unit) and UnitIsTapDenied(unit) then
328 frame.health:SetVertexColor(0.5, 0.5, 0.5);
329 elseif UnitIsPlayer(unit) then
330 local _, class = UnitClass(unit);
331 local color = RAID_CLASS_COLORS[class];
333 frame.health:SetVertexColor(color.r, color.g, color.b)
335 frame.health:SetVertexColor(unpack(healthColor))
337 elseif UnitPlayerControlled(unit) then
338 frame.health:SetVertexColor(0, 1, 0);
340 frame.health:SetVertexColor(UnitSelectionColor(unit));
345 ["UNIT_HEALTH"] = function(frame)
346 updateHealth(frame, frame.displayed);
347 updateHealthText(frame, frame.displayed);
348 updateShield(frame, frame.displayed);
349 updateHealAbsorb(frame, frame.displayed);
350 -- no heal prediction update, that doesn't overflow too much
352 ["UNIT_POWER"] = function(frame)
353 updatePower(frame, frame.displayed);
354 updatePowerText(frame, frame.displayed);
356 ["UNIT_AURA"] = function(frame)
357 updateAuras(frame, frame.displayed);
359 ["UNIT_HEAL_PREDICTION"] = function(frame)
360 updateHealPred(frame, frame.displayed);
362 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
363 updateShield(frame, frame.displayed);
365 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
366 updateHealAbsorb(frame, frame.displayed);
368 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
369 updateAggro(frame, frame.displayed);
371 ["UNIT_MAXHEALTH"] = function(frame)
372 updateMaxHealth(frame, frame.displayed);
373 updateHealth(frame, frame.displayed);
374 updateHealthText(frame, frame.displayed);
375 updateShield(frame, frame.displayed);
376 updateHealAbsorb(frame, frame.displayed);
378 ["UNIT_MAXPOWER"] = function(frame)
379 updateMaxPower(frame, frame.displayed);
380 updatePower(frame, frame.displayed);
381 updatePowerText(frame, frame.displayed);
383 ["UNIT_DISPLAYPOWER"] = function(frame)
384 updatePowerColor(frame, frame.displayed);
385 updateMaxPower(frame, frame.displayed);
386 updatePower(frame, frame.displayed);
387 updatePowerText(frame, frame.displayed);
389 ["UNIT_NAME_UPDATE"] = function(frame)
390 updateName(frame, frame.displayed);
391 updateHealthColor(frame, frame.unit);
393 ["UNIT_CONNECTION"] = function(frame)
394 updateHealthText(frame, frame.displayed);
395 updatePowerText(frame, frame.displayed);
397 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
398 updateRole(frame, frame.unit);
400 ["UNIT_LEVEL"] = function(frame)
401 updateLevelText(frame, frame.unit);
403 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
404 updateLevelText(frame, frame.unit, arg1);
406 ["PLAYER_UPDATE_RESTING"] = function(frame)
407 updateStatus(frame, frame.unit);
409 ["PLAYER_REGEN_DISABLED"] = function(frame)
410 frame.inCombat = true;
411 updateStatus(frame, frame.unit);
413 ["PLAYER_REGEN_ENABLED"] = function(frame)
414 frame.inCombat = false;
415 updateStatus(frame, frame.unit);
417 ["UNIT_FACTION"] = function(frame)
418 updatePVP(frame, frame.unit);
419 updateHealthColor(frame, frame.unit);
421 ["PARTY_LEADER_CHANGED"] = function(frame)
422 updateLeaderIcon(frame, frame.unit);
424 ["UPDATE_ALL_BARS"] = function(frame)
425 updateVehicle(frame);
426 updateMaxHealth(frame, frame.displayed);
427 updateMaxPower(frame, frame.displayed);
428 updateHealth(frame, frame.displayed);
429 updateHealthText(frame, frame.displayed);
430 updatePower(frame, frame.displayed);
431 updatePowerText(frame, frame.displayed);
432 updateAuras(frame, frame.displayed);
433 updateShield(frame, frame.displayed);
434 updateHealPred(frame, frame.displayed);
435 updateHealAbsorb(frame, frame.displayed);
436 updatePowerColor(frame, frame.displayed);
437 updateAggro(frame, frame.displayed);
438 updateName(frame, frame.displayed);
439 updateRole(frame, frame.unit);
440 updateLevelText(frame, frame.unit);
441 updateStatus(frame, frame.unit);
442 updatePVP(frame, frame.unit);
443 updateLeaderIcon(frame, frame.unit);
444 updateHealthColor(frame, frame.unit);
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"];
457 function M.UnitEvent(self, event, arg1)
458 eventFuncs[event](self, arg1);