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 auras = {"Bursting With Pride"},
97 auraFilter = "HELPFUL",
98 x = 570, -- placed over Innervate frame
105 auras = {"Divine Purpose"},
106 auraFilter = "PLAYER HELPFUL",
114 spec = 2, -- Protection
115 auras = {"Shield of the Righteous"},
116 auraFilter = "PLAYER HELPFUL",
124 spec = 2, -- Protection
125 auras = {"Shining Light"},
126 auraFilter = "PLAYER HELPFUL",
134 auras = {"Seraphim", "Righteous Verdict"},
135 auraFilter = "PLAYER HELPFUL",
143 auras = {"Divine Shield"},
144 auraFilter = "PLAYER HELPFUL",
152 auras = {"Devotion Aura"},
153 auraFilter = "HELPFUL",
164 auras = {"Shadow Word: Pain", "Purge the Wicked"},
165 auraFilter = "PLAYER HARMFUL",
173 auras = {"Power Word: Fortitude"},
174 auraFilter = "HELPFUL",
183 auras = {"Overcharge Mana"},
184 auraFilter = "PLAYER HELPFUL",
193 totems = {1}, -- Efflorescence
203 auras = {"Tidal Waves"},
204 auraFilter = "PLAYER HELPFUL",
212 auras = {"Healing Rain"},
213 auraFilter = "PLAYER HELPFUL",
221 auras = {"Unleash Life"},
222 auraFilter = "PLAYER HELPFUL",
232 auras = {"Tidal Waves"},
233 auraFilter = "PLAYER HELPFUL",
241 auras = {"Healing Rain"},
242 auraFilter = "PLAYER HELPFUL",
250 auras = {"Unleash Life"},
251 auraFilter = "PLAYER HELPFUL",
262 auraFilter = "HELPFUL",
272 auras = {"Arcane Intellect"},
273 auraFilter = "HELPFUL",
282 auras = {"Rune of Power"},
283 auraFilter = "PLAYER HELPFUL",
292 auras = {"Winter's Chill"},
293 auraFilter = "PLAYER HARMFUL",
302 auras = {"Sun King's Blessing"},
303 auraFilter = "PLAYER HELPFUL",
312 auras = {"Icy Veins"},
313 auraFilter = "PLAYER HELPFUL",
322 auras = {"Combustion"},
323 auraFilter = "PLAYER HELPFUL",
332 auras = {"Infernal Cascade"},
333 auraFilter = "PLAYER HELPFUL",
341 auras = {"Alter Time"},
342 auraFilter = "PLAYER HELPFUL",
353 -- unit = unitID where to check auras, not required for totem checkers
354 -- spec = player spec index to show frame, if nil show always
355 -- auras = list of auras to track, in priority order
356 -- auraFilter = filter for UnitAura
357 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
358 -- x = x position relative to UIParent bottom left
359 -- y = y position relative to UIParent bottom left
363 -- global frames' settings
367 auras = {"Innervate", "Gift of the Titans", "Power Infusion"},
368 auraFilter = "HELPFUL",
376 auras = {"Ineffable Truth"},
377 auraFilter = "HELPFUL",
386 "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
387 "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
388 "Time Bomb", "Broken Shard", "Demolished", "Fetid Rot", "Roiling Deceit",
389 "Putrid Blood", "Endemic Virus", "Lingering Infection", "Gigavolt Charge",
390 "Crackling Lightning", "Storm's Wail", "Death's Door", "Deathly Withering",
391 "Chilling Touch", "Volatile Charge", "Liquid Gold", "Drained Soul", "Evoke Anguish",
392 "Ancient Curse", "Corrosion", "Debilitating Spit", "Tasty Morsel", "Encroaching Shadows",
393 "Corrupted Existence", "Madness Bomb", "Crimson Chorus", "Essence Sap", "Bloodlight",
394 "Arcane Vulnerability", "Wicked Laceration", "Withering Touch", "Fragment of Destiny",
395 "Flameclasp Eruption", "Wailing Arrow", "Frozen Destruction",
396 "Remnant: Mort'regar's Echoes", "Barbed Arrow", "Scorn", "Ire", "Song of Dissolution",
397 "Grim Portent", "Exposed Threads of Fate", "Despair"
399 auraFilter = "HARMFUL",
408 "Adaptive Membrane", "Gluttonous Miasma", "Remnant: Soulforge Heat"
410 auraFilter = "HARMFUL",
419 local units = {}; -- mapping from unitID to frames
420 local totems = {}; -- mapping to frames with totems
422 for i = 1, MAX_BOSS_FRAMES do
423 bosses[i] = "boss"..i;
425 local currentSpec = 0; -- 0 is invalid
427 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
429 local function updateAuraFrame(frame)
430 local unit = frame.unit;
431 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
432 local name, icon, count, duration, expires, id;
433 local auraFilter = frame.auraFilter;
436 name, icon, count, _, duration, expires, _, _, _, id = UnitAura(unit, i, auraFilter);
437 if not name then break end
438 -- possible improvement to add spellID as an option
439 if frame.auras[name] and not frame.invert then
441 frame.stack:SetText(count);
447 frame.cd:SetCooldown(expires - duration, duration);
452 frame.icon:SetTexture(icon);
455 elseif frame.auras[name] and frame.invert then
456 frame.icon:SetTexture(icon);
463 frame:Show(); -- not functional without first hiding once to get SetTexture
470 local function updateAuras(unit)
472 for _, i in pairs(units[unit]) do
473 updateAuraFrame(frames[i]);
478 local function updateTotemFrame(frame, slot)
479 local _, name, start, duration, icon = GetTotemInfo(slot);
481 frame.cd:SetCooldown(start, duration);
483 frame.icon:SetTexture(icon);
490 local function updateTotems(slot)
492 for _, i in pairs(totems[slot]) do
493 updateTotemFrame(frames[i], slot);
498 local function createTMW(name, config, parent)
499 local frame = CreateFrame("Frame", name, parent);
500 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
501 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
502 frame.unit = config.unit;
503 frame.spec = config.spec;
506 for _, v in pairs(config.auras) do
507 frame.auras[v] = true;
510 frame.auraFilter = config.auraFilter;
511 frame.totems = config.totems;
512 frame.invert = config.invert;
514 frame.base = frame:CreateTexture(nil, "BACKGROUND");
515 frame.base:SetAllPoints();
516 frame.base:SetColorTexture(0, 0, 0, 0.6);
517 frame.icon = frame:CreateTexture(nil, "ARTWORK");
518 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
519 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
520 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
521 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
522 frame.stack:SetFont(STANDARD_TEXT_FONT, 26, "OUTLINE");
523 frame.stack:SetPoint("TOPLEFT");
525 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
526 frame.cd:SetReverse(true);
527 frame.cd:SetAllPoints();
531 local function initialize()
532 Indicators:SetFrameStrata("LOW");
533 Indicators:SetPoint("BOTTOMLEFT");
534 Indicators:SetWidth(1);
535 Indicators:SetHeight(1);
536 currentSpec = GetSpecialization();
537 local name, realm = UnitFullName("player");
538 if chars[realm] and chars[realm][name] then
539 for _, config in pairs(chars[realm][name]) do
540 table.insert(settings, config)
543 for i, config in pairs(settings) do
545 if not units[config.unit] then units[config.unit] = {} end
546 table.insert(units[config.unit], i);
548 if config.totems then
549 for _, slot in pairs(config.totems) do
550 if not totems[slot] then totems[slot] = {} end
551 table.insert(totems[slot], i);
554 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
557 for _, frame in pairs(frames) do
558 if frame.auras then updateAuraFrame(frame) end
560 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
565 Indicators:RegisterEvent("UNIT_AURA");
566 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
567 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
568 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
569 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
570 Indicators:RegisterEvent("PLAYER_LOGIN");
571 Indicators:SetScript("OnEvent", function(self, event, arg1)
572 if event == "UNIT_AURA" then
574 elseif event == "PLAYER_TARGET_CHANGED" then
575 updateAuras("target");
576 elseif event == "PLAYER_TOTEM_UPDATE" then
578 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
579 for _, boss in pairs(bosses) do
582 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
583 currentSpec = GetSpecialization();
584 for _, frame in pairs(frames) do
585 if frame.auras then updateAuraFrame(frame) end
587 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
590 elseif event == "PLAYER_LOGIN" then