4 local ssub = string.sub;
6 local UnitName, UnitClass, UnitExists = UnitName, UnitClass, UnitExists;
7 local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed;
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 UnitHasIncomingResurrection = UnitHasIncomingResurrection;
14 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
15 local UnitHasVehicleUI, UnitTargetsVehicleInRaidUI = UnitHasVehicleUI, UnitTargetsVehicleInRaidUI;
16 local GetReadyCheckTimeLeft, GetReadyCheckStatus = GetReadyCheckTimeLeft, GetReadyCheckStatus;
17 local UnitGroupRolesAssigned = UnitGroupRolesAssigned;
18 local RAID_CLASS_COLORS = RAID_CLASS_COLORS;
19 local READY_CHECK_READY_TEXTURE = READY_CHECK_READY_TEXTURE;
20 local READY_CHECK_NOT_READY_TEXTURE = READY_CHECK_NOT_READY_TEXTURE;
21 local READY_CHECK_WAITING_TEXTURE = READY_CHECK_WAITING_TEXTURE;
23 local checkIndicators = OmaRFIndicators.CheckIndicators;
25 local Settings = OmaRFSettings;
26 local baseColor = Settings.BaseColor;
27 local overlayColorDispel = Settings.OverlayColorDispel;
28 local overlayColorCharm = Settings.OverlayColorCharm;
29 local overlayColorAlert = Settings.OverlayColorAlert;
30 local powerColors = Settings.PowerColors;
35 function M.RegisterEvents(frame)
36 -- events are taken from FrameXML/CompactUnitFrame.lua
37 -- TODO raid marker support,
38 -- player flags support (/afk, /dnd)
39 local displayed = frame.unit ~= frame.displayed and frame.displayed or nil;
40 frame:RegisterUnitEvent("UNIT_HEALTH", frame.unit, displayed);
41 frame:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", frame.unit, displayed);
42 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_NAME_UPDATE", frame.unit, displayed);
47 frame:RegisterUnitEvent("UNIT_AURA", frame.unit, displayed);
48 frame:RegisterUnitEvent("UNIT_HEAL_PREDICTION", frame.unit, displayed);
49 frame:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
50 frame:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", frame.unit, displayed);
51 frame:RegisterUnitEvent("UNIT_THREAT_SITUATION_UPDATE", frame.unit, displayed);
52 frame:RegisterUnitEvent("UNIT_CONNECTION", frame.unit, displayed);
53 frame:RegisterUnitEvent("INCOMING_RESURRECT_CHANGED", frame.unit, displayed);
55 local registerEvents = M.RegisterEvents;
57 local function updateHealth(frame, unit)
58 local current, max = UnitHealth(unit), frame.health.max;
60 -- sanity check, occasionally UnitHealthMax gives zero
62 -- somehow current health has gone over the maximum (missed maxhealth event)
63 frame.health.max = UnitHealthMax(unit);
64 max = frame.health.max;
66 -- error state, still over maximum
67 frame.health:SetWidth(width);
71 frame.health:SetWidth(current/frame.health.max*width);
73 frame.health:SetWidth(width);
77 if UnitIsDeadOrGhost(unit) then
82 local function updateText(frame, unit)
83 local current, max = UnitHealth(unit), frame.health.max;
84 local healthLost = max - current;
85 if UnitIsDeadOrGhost(unit) then
86 frame.text:SetText("Dead");
88 elseif not UnitIsConnected(unit) then
89 frame.text:SetText("DC");
91 elseif healthLost > 0 then
92 if healthLost > 1200000000 then -- 1.2B
93 frame.text:SetFormattedText("-%.1fB", healthLost / 1000000000);
94 elseif healthLost > 1200000 then -- 1.2M
95 frame.text:SetFormattedText("-%.1fM", healthLost / 1000000);
96 elseif healthLost > 1000 then -- 1K
97 frame.text:SetFormattedText("-%dK", healthLost / 1000);
99 frame.text:SetFormattedText("-%d", healthLost)
107 local function updateIncomingRes(frame, unit)
108 if UnitHasIncomingResurrection(unit) then
115 local function updateMaxHealth(frame, unit)
116 frame.health.max = UnitHealthMax(unit);
119 local function updatePower(frame, unit)
120 local current, max = UnitPower(unit), frame.mana.max;
121 -- sanity check, occasionally UnitPowerMax gives zero
122 if current > max then
123 frame.mana.max = UnitPowerMax(unit);
124 max = frame.mana.max;
125 if current > max then
127 frame.mana:SetWidth(width);
131 frame.mana:SetWidth(UnitPower(unit)/max*width);
133 frame.mana:SetWidth(width);
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, 6));
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;
174 if space < shield then
175 frame.shield:SetWidth(space);
176 frame.shieldhl:Show();
178 frame.shield:SetWidth(shield);
179 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 checkIndicators(frame, unit);
203 if UnitDebuff(unit, 1, "RAID") ~= nil then
204 -- something dispellable
205 if frame.overlay.color ~= overlayColorDispel then
206 frame.overlay:SetVertexColor(unpack(overlayColorDispel));
207 frame.overlay:Show();
208 frame.overlay.color = overlayColorDispel;
210 -- don't overlay charmed when in vehicle
211 elseif UnitIsCharmed(unit) and unit == frame.unit then
212 if frame.overlay.color ~= overlayColorCharm then
213 frame.overlay:SetVertexColor(unpack(overlayColorCharm));
214 frame.overlay:Show();
215 frame.overlay.color = overlayColorCharm;
218 if frame.overlay.color ~= nil then
219 frame.overlay:Hide();
220 frame.overlay.color = nil;
225 local function updateAggro(frame, unit)
226 local status = UnitThreatSituation(unit);
227 if status and status > 0 then
228 frame.base:SetVertexColor(GetThreatStatusColor(status));
230 frame.base:SetVertexColor(unpack(baseColor));
234 local function updateVehicle(frame)
235 local shouldTargetVehicle = UnitHasVehicleUI(frame.unit) and UnitTargetsVehicleInRaidUI(frame.unit) and UnitExists(frame.vehicle);
236 if shouldTargetVehicle then
237 if not frame.inVehicle then
238 frame.inVehicle = true;
239 frame.displayed = frame.vehicle;
240 registerEvents(frame);
242 elseif frame.inVehicle then
243 frame.inVehicle = false;
244 frame.displayed = frame.unit;
245 registerEvents(frame);
249 local function updateRole(frame, unit)
250 local role = UnitGroupRolesAssigned(unit);
251 if role == "HEALER" then
252 frame.role:SetTexCoord(0.75, 1, 0, 1);
254 elseif role == "TANK" then
255 frame.role:SetTexCoord(0.5, 0.75, 0, 1);
262 local function updateReadyCheck(frame, unit)
263 local status = GetReadyCheckStatus(unit);
264 if status == "ready" then
265 frame.ready:SetTexture(READY_CHECK_READY_TEXTURE);
267 elseif status == "notready" then
268 frame.ready:SetTexture(READY_CHECK_NOT_READY_TEXTURE);
270 elseif status == "waiting" then
271 frame.ready:SetTexture(READY_CHECK_WAITING_TEXTURE);
279 ["UNIT_HEALTH"] = function(frame)
280 updateHealth(frame, frame.displayed);
281 updateText(frame, frame.displayed);
282 updateShield(frame, frame.displayed);
283 updateHealAbsorb(frame, frame.displayed);
284 -- no heal prediction update, that doesn't overflow too much
286 ["UNIT_POWER"] = function(frame)
287 updatePower(frame, frame.displayed);
289 ["UNIT_AURA"] = function(frame)
290 updateAuras(frame, frame.displayed);
292 ["UNIT_HEAL_PREDICTION"] = function(frame)
293 updateHealPred(frame, frame.displayed);
295 ["UNIT_ABSORB_AMOUNT_CHANGED"] = function(frame)
296 updateShield(frame, frame.displayed);
298 ["UNIT_HEAL_ABSORB_AMOUNT_CHANGED"] = function(frame)
299 updateHealAbsorb(frame, frame.displayed);
301 ["UNIT_THREAT_SITUATION_UPDATE"] = function(frame)
302 updateAggro(frame, frame.displayed);
304 ["UNIT_MAXHEALTH"] = function(frame)
305 updateMaxHealth(frame, frame.displayed);
306 updateHealth(frame, frame.displayed);
307 updateText(frame, frame.displayed);
308 updateShield(frame, frame.displayed);
309 updateHealAbsorb(frame, frame.displayed);
311 ["UNIT_MAXPOWER"] = function(frame)
312 updateMaxPower(frame, frame.displayed);
313 updatePower(frame, frame.displayed);
315 ["UNIT_DISPLAYPOWER"] = function(frame)
316 updatePowerColor(frame, frame.displayed);
318 ["UNIT_NAME_UPDATE"] = function(frame)
319 updateName(frame, frame.displayed);
321 ["UNIT_CONNECTION"] = function(frame)
322 updateText(frame, frame.displayed);
324 ["INCOMING_RESURRECT_CHANGED"] = function(frame)
325 updateIncomingRes(frame, frame.unit);
327 ["PARTY_MEMBER_ENABLE"] = function(frame)
328 -- new power info possibly (FrameXML/CompactUnitFrame.lua)
329 updateMaxPower(frame, frame.displayed);
330 updatePowerColor(frame, frame.displayed);
332 ["PLAYER_ROLES_ASSIGNED"] = function(frame)
333 updateRole(frame, frame.unit);
335 ["READY_CHECK"] = function(frame)
336 updateReadyCheck(frame, frame.unit);
338 ["UPDATE_ALL_BARS"] = function(frame)
339 updateVehicle(frame);
340 updateMaxHealth(frame, frame.displayed);
341 updateMaxPower(frame, frame.displayed);
342 updateHealth(frame, frame.displayed);
343 updateText(frame, frame.displayed);
344 updatePower(frame, frame.displayed);
345 updateAuras(frame, frame.displayed);
346 updateShield(frame, frame.displayed);
347 updateHealPred(frame, frame.displayed);
348 updateHealAbsorb(frame, frame.displayed);
349 updatePowerColor(frame, frame.displayed);
350 updateIncomingRes(frame, frame.unit);
351 updateReadyCheck(frame, frame.unit);
352 updateAggro(frame, frame.displayed);
353 updateName(frame, frame.displayed);
354 updateRole(frame, frame.unit);
357 eventFuncs["UNIT_HEALTH_FREQUENT"] = eventFuncs["UNIT_HEALTH"];
358 eventFuncs["PARTY_MEMBER_DISABLE"] = eventFuncs["PARTY_MEMBER_ENABLE"];
359 eventFuncs["READY_CHECK_CONFIRM"] = eventFuncs["READY_CHECK"];
360 eventFuncs["READY_CHECK_FINISHED"] = eventFuncs["READY_CHECK"];
361 eventFuncs["UNIT_ENTERED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
362 eventFuncs["UNIT_EXITED_VEHICLE"] = eventFuncs["UPDATE_ALL_BARS"];
363 eventFuncs["UNIT_PET"] = eventFuncs["UPDATE_ALL_BARS"];
364 eventFuncs["GROUP_ROSTER_UPDATE"] = eventFuncs["UPDATE_ALL_BARS"];
365 eventFuncs["PLAYER_ENTERING_WORLD"] = eventFuncs["UPDATE_ALL_BARS"];
366 eventFuncs["PLAYER_FOCUS_CHANGED"] = eventFuncs["UPDATE_ALL_BARS"];
368 function M.UnitEvent(self, event)
369 eventFuncs[event](self);
372 function M.LoadChar()
373 width = Settings.Character.Width;