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 overlayColorDispel = Settings.OverlayColorDispel;
26 local overlayColorCharm = Settings.OverlayColorCharm;
27 local overlayColorAlert = Settings.OverlayColorAlert;
28 local powerColors = Settings.PowerColors;
33 function M.RegisterEvents(frame)
34 -- events are taken from FrameXML/CompactUnitFrame.lua
35 -- TODO raid marker support,
36 -- player flags support (/afk, /dnd)
37 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
38 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
39 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
40 frame:RegisterUnitEvent("UNIT_MAXHEALTH", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_POWER", frame.unit, displayed);
42 frame:RegisterUnitEvent("UNIT_MAXPOWER", frame.unit, displayed);
43 frame:RegisterUnitEvent("UNIT_DISPLAYPOWER", 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));
150 local _, class = UnitClass(unit);
151 local color = RAID_CLASS_COLORS[class];
152 if color then frame.name:SetVertexColor(color.r, color.g, color.b) end
155 local function updateHealPred(frame, unit)
156 local incoming = UnitGetIncomingHeals(unit) or 0;
158 local max = frame.health.max;
159 local space = width - frame.health:GetWidth() + 1;
160 local pred = (incoming / max) * width;
161 frame.healpred:SetWidth(min(space, pred));
162 frame.healpred:Show();
164 frame.healpred:Hide();
168 local function updateShield(frame, unit)
169 local shield = UnitGetTotalAbsorbs(unit) or 0;
171 local max = frame.health.max;
172 local space = width - frame.health:GetWidth();
173 shield = (shield / max) * width;
176 frame.shieldhl:Show();
177 elseif space < shield then
178 frame.shield:SetWidth(space);
180 frame.shieldhl:Show();
182 frame.shield:SetWidth(shield);
184 frame.shieldhl:Hide();
188 frame.shieldhl:Hide();
192 local function updateHealAbsorb(frame, unit)
193 local absorb = UnitGetTotalHealAbsorbs(unit) or 0;
195 local max = frame.health.max;
196 local space = frame.health:GetWidth();
197 absorb = (absorb / max) * width;
198 frame.healabsorb:SetWidth(min(space, absorb));
199 frame.healabsorb:Show();
201 frame.healabsorb:Hide();
205 local function updateAuras(frame, unit)
206 updateAuraFrames(frame, unit);
207 if UnitIsFriend("player", unit) and UnitDebuff(unit, 1, "RAID") ~= nil then
208 -- something dispellable
209 if frame.overlay.color ~= overlayColorDispel then
210 frame.overlay:SetVertexColor(unpack(overlayColorDispel));
211 frame.overlay:Show();
212 frame.overlay.color = overlayColorDispel;
214 -- don't overlay charmed when in vehicle
215 elseif UnitIsCharmed(unit) and unit == frame.unit then
216 if frame.overlay.color ~= overlayColorCharm then
217 frame.overlay:SetVertexColor(unpack(overlayColorCharm));
218 frame.overlay:Show();
219 frame.overlay.color = overlayColorCharm;
222 if frame.overlay.color ~= nil then
223 frame.overlay:Hide();
224 frame.overlay.color = nil;
229 local function updateAggro(frame, unit)
230 local status = UnitThreatSituation(unit);
231 if status and status > 0 then
232 frame.base:SetVertexColor(GetThreatStatusColor(status));
234 frame.base:SetVertexColor(unpack(baseColor));
238 local function updateVehicle(frame)
239 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
240 if shouldTargetVehicle then
241 if not frame.inVehicle then
242 frame.inVehicle = true;
243 frame.displayed = frame.vehicle;
244 registerEvents(frame);
246 elseif frame.inVehicle then
247 frame.inVehicle = false;
248 frame.displayed = frame.unit;
249 registerEvents(frame);
253 local function updateRole(frame, unit)
254 local role = UnitGroupRolesAssigned(unit);
255 if role == "HEALER" or role == "TANK" or role == "DAMAGER" then
256 frame.role:SetTexCoord(GetTexCoordsForRoleSmallCircle(role));
263 local function updateLevelText(frame, unit, levelup)
266 frame.level:SetText(levelup);
268 local level = UnitLevel(unit);
269 local class = UnitClassification(unit);
270 local leveltext, classtext;
272 if class == "worldboss" then
280 if class == "rareelite" then
281 classtext = " Rare Elite";
282 elseif class == "elite" then
283 classtext = " Elite";
284 elseif class == "rare" then
289 frame.level:SetFormattedText("%s%s", leveltext, classtext);
293 local function updateStatus(frame, unit)
294 -- coords from PlayerFrame
295 if frame.inCombat or UnitAffectingCombat(unit) then
296 frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
298 elseif unit == "player" and IsResting() then
299 frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
306 local function updatePVP(frame, unit)
307 if UnitIsPVPFreeForAll(unit) then
308 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-FFA");
310 elseif UnitIsPVP(unit) then
311 local faction = UnitFactionGroup(unit);
312 if faction and faction ~= "Neutral" then
313 -- from PlayerFrame, mercenary checks
314 if UnitIsMercenary(unit) then
315 if faction == "Horde" then
316 faction = "Alliance";
317 elseif faction == "Alliance" then
321 frame.pvp:SetTexture("Interface\\TARGETINGFRAME\\UI-PVP-"..faction);
331 local function updateLeaderIcon(frame, unit)
332 if UnitIsGroupLeader(frame.unit) then
333 if HasLFGRestrictions() then
334 frame.leader:SetTexture("Interface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES");
335 frame.leader:SetTexCoord(0, 0.296875, 0.015625, 0.3125);
337 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-LeaderIcon");
338 frame.leader:SetTexCoord(0, 1, 0, 1);
341 elseif UnitIsGroupAssistant(frame.unit) then
342 frame.leader:SetTexture("Interface\\GROUPFRAME\\UI-Group-AssistantIcon");
343 frame.leader:SetTexCoord(0, 1, 0, 1);
351 ["UNIT_HEALTH"] = function(frame)
352 updateHealth(frame, frame.displayed);
353 updateHealthText(frame, frame.displayed);
354 updateShield(frame, frame.displayed);
355 updateHealAbsorb(frame, frame.displayed);
356 -- no heal prediction update, that doesn't overflow too much
358 ["UNIT_POWER"] = function(frame)
359 updatePower(frame, frame.displayed);
360 updatePowerText(frame, frame.displayed);
362 ["UNIT_AURA"] = function(frame)
363 updateAuras(frame, frame.displayed);
365 ["UNIT_HEAL_PREDICTION"] = function(frame)
366 updateHealPred(frame, frame.displayed);
368 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
369 updateShield(frame, frame.displayed);
371 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
372 updateHealAbsorb(frame, frame.displayed);
374 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
375 updateAggro(frame, frame.displayed);
377 ["UNIT_MAXHEALTH"] = function(frame)
378 updateMaxHealth(frame, frame.displayed);
379 updateHealth(frame, frame.displayed);
380 updateHealthText(frame, frame.displayed);
381 updateShield(frame, frame.displayed);
382 updateHealAbsorb(frame, frame.displayed);
384 ["UNIT_MAXPOWER"] = function(frame)
385 updateMaxPower(frame, frame.displayed);
386 updatePower(frame, frame.displayed);
387 updatePowerText(frame, frame.displayed);
389 ["UNIT_DISPLAYPOWER"] = function(frame)
390 updatePowerColor(frame, frame.displayed);
392 ["UNIT_NAME_UPDATE"] = function(frame)
393 updateName(frame, frame.displayed);
395 ["UNIT_CONNECTION"] = function(frame)
396 updateHealthText(frame, frame.displayed);
397 updatePowerText(frame, frame.displayed);
399 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
400 updateRole(frame, frame.unit);
402 ["UNIT_LEVEL"] = function(frame)
403 updateLevelText(frame, frame.unit);
405 ["PLAYER_LEVEL_UP"] = function(frame, arg1)
406 updateLevelText(frame, frame.unit, arg1);
408 ["PLAYER_UPDATE_RESTING"] = function(frame)
409 updateStatus(frame, frame.unit);
411 ["PLAYER_REGEN_DISABLED"] = function(frame)
412 frame.inCombat = true;
413 updateStatus(frame, frame.unit);
415 ["PLAYER_REGEN_ENABLED"] = function(frame)
416 frame.inCombat = false;
417 updateStatus(frame, frame.unit);
419 ["UNIT_FACTION"] = function(frame)
420 updatePVP(frame, frame.unit);
422 ["PARTY_LEADER_CHANGED"] = function(frame)
423 updateLeaderIcon(frame, frame.unit);
425 ["UPDATE_ALL_BARS"] = function(frame)
426 updateVehicle(frame);
427 updateMaxHealth(frame, frame.displayed);
428 updateMaxPower(frame, frame.displayed);
429 updateHealth(frame, frame.displayed);
430 updateHealthText(frame, frame.displayed);
431 updatePower(frame, frame.displayed);
432 updatePowerText(frame, frame.displayed);
433 updateAuras(frame, frame.displayed);
434 updateShield(frame, frame.displayed);
435 updateHealPred(frame, frame.displayed);
436 updateHealAbsorb(frame, frame.displayed);
437 updatePowerColor(frame, frame.displayed);
438 updateAggro(frame, frame.displayed);
439 updateName(frame, frame.displayed);
440 updateRole(frame, frame.unit);
441 updateLevelText(frame, frame.unit);
442 updateStatus(frame, frame.unit);
443 updatePVP(frame, frame.unit);
444 updateLeaderIcon(frame, frame.unit);
447 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
448 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
449 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
450 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
451 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
452 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
453 eventFuncs["PLAYER_TARGET_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
455 function M.UnitEvent(self, event, arg1)
456 eventFuncs[event](self, arg1);
459 function M.LoadChar()
460 width = Settings.Character.Width;