4 local GetSpecialization = GetSpecialization;
5 local UnitExists = UnitExists;
6 local UnitAura = UnitAura;
7 local GetTotemInfo = GetTotemInfo;
9 -- character specific frames
10 -- TODO try with auraFilter, remove characters, change to classes
13 ["PLAYER HELPFUL"] = {
16 auras = {["Divine Shield"]=1, ""},
31 ["PLAYER HELPFUL"] = {
34 auras = {["Judgment"]=1},
41 ["PLAYER HARMFUL"] = {
53 spec = 3, -- Retribution
55 auraFilter = "PLAYER HARMFUL",
56 x = 570, -- placed over Innervate frame
63 spec = 3, -- Retribution
64 auras = {"Divine Purpose"},
65 auraFilter = "PLAYER HELPFUL",
73 spec = 2, -- Protection
74 auras = {"Shield of the Righteous"},
75 auraFilter = "PLAYER HELPFUL",
83 auras = {"Divine Shield"},
84 auraFilter = "PLAYER HELPFUL",
96 spec = 3, -- Retribution
98 auraFilter = "PLAYER HARMFUL",
99 x = 570, -- placed over Innervate frame
106 auras = {"Divine Purpose"},
107 auraFilter = "PLAYER HELPFUL",
115 spec = 2, -- Protection
116 auras = {"Shield of the Righteous"},
117 auraFilter = "PLAYER HELPFUL",
125 auras = {"Divine Shield"},
126 auraFilter = "PLAYER HELPFUL",
134 auras = {"Devotion Aura"},
135 auraFilter = "HELPFUL",
146 auras = {"Shadow Word: Pain", "Purge the Wicked"},
147 auraFilter = "PLAYER HARMFUL",
155 auras = {"Power Word: Fortitude"},
156 auraFilter = "HELPFUL",
165 auras = {"Overcharge Mana"},
166 auraFilter = "PLAYER HELPFUL",
175 totems = {1}, -- Efflorescence
185 auras = {"Tidal Waves"},
186 auraFilter = "PLAYER HELPFUL",
194 auras = {"Healing Rain"},
195 auraFilter = "PLAYER HELPFUL",
203 auras = {"Unleash Life"},
204 auraFilter = "PLAYER HELPFUL",
214 auras = {"Tidal Waves"},
215 auraFilter = "PLAYER HELPFUL",
223 auras = {"Healing Rain"},
224 auraFilter = "PLAYER HELPFUL",
232 auras = {"Unleash Life"},
233 auraFilter = "PLAYER HELPFUL",
244 auraFilter = "HELPFUL",
255 -- unit = unitID where to check auras, not required for totem checkers
256 -- spec = player spec index to show frame, if nil show always
257 -- auras = list of auras to track, in priority order
258 -- auraFilter = filter for UnitAura
259 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
260 -- x = x position relative to UIParent bottom left
261 -- y = y position relative to UIParent bottom left
265 -- global frames' settings
269 auras = {"Innervate", "Gift of the Titans", "Power Infusion"},
270 auraFilter = "HELPFUL",
278 auras = {"Ineffable Truth"},
279 auraFilter = "HELPFUL",
288 "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
289 "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
290 "Time Bomb", "Broken Shard", "Demolished", "Fetid Rot", "Roiling Deceit",
291 "Putrid Blood", "Endemic Virus", "Lingering Infection", "Gigavolt Charge",
292 "Crackling Lightning", "Storm's Wail", "Death's Door", "Deathly Withering",
293 "Chilling Touch", "Volatile Charge", "Liquid Gold", "Drained Soul", "Evoke Anguish",
294 "Ancient Curse", "Corrosion", "Debilitating Spit", "Tasty Morsel", "Encroaching Shadows",
295 "Corrupted Existence", "Madness Bomb", "Crimson Chorus", "Essence Sap", "Bloodlight",
296 "Arcane Vulnerability"
298 auraFilter = "HARMFUL",
307 "Adaptive Membrane", "Gluttonous Miasma"
309 auraFilter = "HARMFUL",
318 local units = {}; -- mapping from unitID to frames
319 local totems = {}; -- mapping to frames with totems
321 for i = 1, MAX_BOSS_FRAMES do
322 bosses[i] = "boss"..i;
324 local currentSpec = 0; -- 0 is invalid
326 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
328 local function updateAuraFrame(frame)
329 local unit = frame.unit;
330 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
331 local name, icon, count, duration, expires;
332 local auraFilter = frame.auraFilter;
335 name, icon, count, _, duration, expires = UnitAura(unit, i, auraFilter);
336 if not name then break end
337 -- possible improvement to add spellID as an option
338 if frame.auras[name] and not frame.invert then
340 frame.stack:SetText(count);
346 frame.cd:SetCooldown(expires - duration, duration);
351 frame.icon:SetTexture(icon);
354 elseif frame.auras[name] and frame.invert then
355 frame.icon:SetTexture(icon);
362 frame:Show(); -- not functional without first hiding once to get SetTexture
369 local function updateAuras(unit)
371 for _, i in pairs(units[unit]) do
372 updateAuraFrame(frames[i]);
377 local function updateTotemFrame(frame, slot)
378 local _, name, start, duration, icon = GetTotemInfo(slot);
380 frame.cd:SetCooldown(start, duration);
382 frame.icon:SetTexture(icon);
389 local function updateTotems(slot)
391 for _, i in pairs(totems[slot]) do
392 updateTotemFrame(frames[i], slot);
397 local function createTMW(name, config, parent)
398 local frame = CreateFrame("Frame", name, parent);
399 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
400 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
401 frame.unit = config.unit;
402 frame.spec = config.spec;
405 for _, v in pairs(config.auras) do
406 frame.auras[v] = true;
409 frame.auraFilter = config.auraFilter;
410 frame.totems = config.totems;
411 frame.invert = config.invert;
413 frame.base = frame:CreateTexture(nil, "BACKGROUND");
414 frame.base:SetAllPoints();
415 frame.base:SetColorTexture(0, 0, 0, 0.6);
416 frame.icon = frame:CreateTexture(nil, "ARTWORK");
417 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
418 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
419 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
420 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
421 frame.stack:SetFont(STANDARD_TEXT_FONT, 26, "OUTLINE");
422 frame.stack:SetPoint("TOPLEFT");
424 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
425 frame.cd:SetReverse(true);
426 frame.cd:SetAllPoints();
430 local function initialize()
431 Indicators:SetFrameStrata("LOW");
432 Indicators:SetPoint("BOTTOMLEFT");
433 Indicators:SetWidth(1);
434 Indicators:SetHeight(1);
435 currentSpec = GetSpecialization();
436 local name, realm = UnitFullName("player");
437 if chars[realm] and chars[realm][name] then
438 for _, config in pairs(chars[realm][name]) do
439 table.insert(settings, config)
442 for i, config in pairs(settings) do
444 if not units[config.unit] then units[config.unit] = {} end
445 table.insert(units[config.unit], i);
447 if config.totems then
448 for _, slot in pairs(config.totems) do
449 if not totems[slot] then totems[slot] = {} end
450 table.insert(totems[slot], i);
453 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
456 for _, frame in pairs(frames) do
457 if frame.auras then updateAuraFrame(frame) end
459 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
464 Indicators:RegisterEvent("UNIT_AURA");
465 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
466 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
467 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
468 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
469 Indicators:RegisterEvent("PLAYER_LOGIN");
470 Indicators:SetScript("OnEvent", function(self, event, arg1)
471 if event == "UNIT_AURA" then
473 elseif event == "PLAYER_TARGET_CHANGED" then
474 updateAuras("target");
475 elseif event == "PLAYER_TOTEM_UPDATE" then
477 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
478 for _, boss in pairs(bosses) do
481 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
482 currentSpec = GetSpecialization();
483 for _, frame in pairs(frames) do
484 if frame.auras then updateAuraFrame(frame) end
486 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
489 elseif event == "PLAYER_LOGIN" then