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"},
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"
297 auraFilter = "HARMFUL",
308 auraFilter = "HARMFUL",
317 local units = {}; -- mapping from unitID to frames
318 local totems = {}; -- mapping to frames with totems
320 for i = 1, MAX_BOSS_FRAMES do
321 bosses[i] = "boss"..i;
323 local currentSpec = 0; -- 0 is invalid
325 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
327 local function updateAuraFrame(frame)
328 local unit = frame.unit;
329 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
330 local name, icon, count, duration, expires;
331 local auraFilter = frame.auraFilter;
334 name, icon, count, _, duration, expires = UnitAura(unit, i, auraFilter);
335 if not name then break end
336 -- possible improvement to add spellID as an option
337 if frame.auras[name] and not frame.invert then
339 frame.stack:SetText(count);
345 frame.cd:SetCooldown(expires - duration, duration);
350 frame.icon:SetTexture(icon);
353 elseif frame.auras[name] and frame.invert then
354 frame.icon:SetTexture(icon);
361 frame:Show(); -- not functional without first hiding once to get SetTexture
368 local function updateAuras(unit)
370 for _, i in pairs(units[unit]) do
371 updateAuraFrame(frames[i]);
376 local function updateTotemFrame(frame, slot)
377 local _, name, start, duration, icon = GetTotemInfo(slot);
379 frame.cd:SetCooldown(start, duration);
381 frame.icon:SetTexture(icon);
388 local function updateTotems(slot)
390 for _, i in pairs(totems[slot]) do
391 updateTotemFrame(frames[i], slot);
396 local function createTMW(name, config, parent)
397 local frame = CreateFrame("Frame", name, parent);
398 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
399 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
400 frame.unit = config.unit;
401 frame.spec = config.spec;
404 for _, v in pairs(config.auras) do
405 frame.auras[v] = true;
408 frame.auraFilter = config.auraFilter;
409 frame.totems = config.totems;
410 frame.invert = config.invert;
412 frame.base = frame:CreateTexture(nil, "BACKGROUND");
413 frame.base:SetAllPoints();
414 frame.base:SetColorTexture(0, 0, 0, 0.6);
415 frame.icon = frame:CreateTexture(nil, "ARTWORK");
416 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
417 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
418 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
419 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
420 frame.stack:SetPoint("TOPLEFT");
422 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
423 frame.cd:SetReverse(true);
424 frame.cd:SetAllPoints();
428 local function initialize()
429 Indicators:SetFrameStrata("LOW");
430 Indicators:SetPoint("BOTTOMLEFT");
431 Indicators:SetWidth(1);
432 Indicators:SetHeight(1);
433 currentSpec = GetSpecialization();
434 local name, realm = UnitFullName("player");
435 if chars[realm] and chars[realm][name] then
436 for _, config in pairs(chars[realm][name]) do
437 table.insert(settings, config)
440 for i, config in pairs(settings) do
442 if not units[config.unit] then units[config.unit] = {} end
443 table.insert(units[config.unit], i);
445 if config.totems then
446 for _, slot in pairs(config.totems) do
447 if not totems[slot] then totems[slot] = {} end
448 table.insert(totems[slot], i);
451 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
454 for _, frame in pairs(frames) do
455 if frame.auras then updateAuraFrame(frame) end
457 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
462 Indicators:RegisterEvent("UNIT_AURA");
463 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
464 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
465 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
466 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
467 Indicators:RegisterEvent("PLAYER_LOGIN");
468 Indicators:SetScript("OnEvent", function(self, event, arg1)
469 if event == "UNIT_AURA" then
471 elseif event == "PLAYER_TARGET_CHANGED" then
472 updateAuras("target");
473 elseif event == "PLAYER_TOTEM_UPDATE" then
475 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
476 for _, boss in pairs(bosses) do
479 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
480 currentSpec = GetSpecialization();
481 for _, frame in pairs(frames) do
482 if frame.auras then updateAuraFrame(frame) end
484 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
487 elseif event == "PLAYER_LOGIN" then