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",
136 auras = {"Shadow Word: Pain", "Purge the Wicked"},
137 auraFilter = "PLAYER HARMFUL",
145 auras = {"Power Word: Fortitude"},
146 auraFilter = "HELPFUL",
155 auras = {"Overcharge Mana"},
156 auraFilter = "PLAYER HELPFUL",
165 totems = {1}, -- Efflorescence
175 auras = {"Tidal Waves"},
176 auraFilter = "PLAYER HELPFUL",
184 auras = {"Healing Rain"},
185 auraFilter = "PLAYER HELPFUL",
193 auras = {"Unleash Life"},
194 auraFilter = "PLAYER HELPFUL",
204 auras = {"Tidal Waves"},
205 auraFilter = "PLAYER HELPFUL",
213 auras = {"Healing Rain"},
214 auraFilter = "PLAYER HELPFUL",
222 auras = {"Unleash Life"},
223 auraFilter = "PLAYER HELPFUL",
234 auraFilter = "HELPFUL",
245 -- unit = unitID where to check auras, not required for totem checkers
246 -- spec = player spec index to show frame, if nil show always
247 -- auras = list of auras to track, in priority order
248 -- auraFilter = filter for UnitAura
249 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
250 -- x = x position relative to UIParent bottom left
251 -- y = y position relative to UIParent bottom left
255 -- global frames' settings
259 auras = {"Innervate", "Gift of the Titans"},
260 auraFilter = "HELPFUL",
268 auras = {"Ineffable Truth"},
269 auraFilter = "HELPFUL",
278 "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
279 "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
280 "Time Bomb", "Broken Shard", "Demolished", "Fetid Rot", "Roiling Deceit",
281 "Putrid Blood", "Endemic Virus", "Lingering Infection", "Gigavolt Charge",
282 "Crackling Lightning", "Storm's Wail", "Death's Door", "Deathly Withering",
283 "Chilling Touch", "Volatile Charge", "Liquid Gold", "Drained Soul", "Evoke Anguish",
284 "Ancient Curse", "Corrosion", "Debilitating Spit", "Tasty Morsel", "Encroaching Shadows",
285 "Corrupted Existence", "Madness Bomb"
287 auraFilter = "HARMFUL",
298 auraFilter = "HARMFUL",
307 local units = {}; -- mapping from unitID to frames
308 local totems = {}; -- mapping to frames with totems
310 for i = 1, MAX_BOSS_FRAMES do
311 bosses[i] = "boss"..i;
313 local currentSpec = 0; -- 0 is invalid
315 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
317 local function updateAuraFrame(frame)
318 local unit = frame.unit;
319 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
320 local name, icon, count, duration, expires;
321 local auraFilter = frame.auraFilter;
324 name, icon, count, _, duration, expires = UnitAura(unit, i, auraFilter);
325 if not name then break end
326 -- possible improvement to add spellID as an option
327 if frame.auras[name] and not frame.invert then
329 frame.stack:SetText(count);
335 frame.cd:SetCooldown(expires - duration, duration);
340 frame.icon:SetTexture(icon);
343 elseif frame.auras[name] and frame.invert then
344 frame.icon:SetTexture(icon);
351 frame:Show(); -- not functional without first hiding once to get SetTexture
358 local function updateAuras(unit)
360 for _, i in pairs(units[unit]) do
361 updateAuraFrame(frames[i]);
366 local function updateTotemFrame(frame, slot)
367 local _, name, start, duration, icon = GetTotemInfo(slot);
369 frame.cd:SetCooldown(start, duration);
371 frame.icon:SetTexture(icon);
378 local function updateTotems(slot)
380 for _, i in pairs(totems[slot]) do
381 updateTotemFrame(frames[i], slot);
386 local function createTMW(name, config, parent)
387 local frame = CreateFrame("Frame", name, parent);
388 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
389 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
390 frame.unit = config.unit;
391 frame.spec = config.spec;
394 for _, v in pairs(config.auras) do
395 frame.auras[v] = true;
398 frame.auraFilter = config.auraFilter;
399 frame.totems = config.totems;
400 frame.invert = config.invert;
402 frame.base = frame:CreateTexture(nil, "BACKGROUND");
403 frame.base:SetAllPoints();
404 frame.base:SetColorTexture(0, 0, 0, 0.6);
405 frame.icon = frame:CreateTexture(nil, "ARTWORK");
406 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
407 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
408 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
409 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
410 frame.stack:SetPoint("TOPLEFT");
412 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
413 frame.cd:SetReverse(true);
414 frame.cd:SetAllPoints();
418 local function initialize()
419 Indicators:SetFrameStrata("LOW");
420 Indicators:SetPoint("BOTTOMLEFT");
421 Indicators:SetWidth(1);
422 Indicators:SetHeight(1);
423 currentSpec = GetSpecialization();
424 local name, realm = UnitFullName("player");
425 if chars[realm] and chars[realm][name] then
426 for _, config in pairs(chars[realm][name]) do
427 table.insert(settings, config)
430 for i, config in pairs(settings) do
432 if not units[config.unit] then units[config.unit] = {} end
433 table.insert(units[config.unit], i);
435 if config.totems then
436 for _, slot in pairs(config.totems) do
437 if not totems[slot] then totems[slot] = {} end
438 table.insert(totems[slot], i);
441 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
444 for _, frame in pairs(frames) do
445 if frame.auras then updateAuraFrame(frame) end
447 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
452 Indicators:RegisterEvent("UNIT_AURA");
453 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
454 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
455 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
456 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
457 Indicators:RegisterEvent("PLAYER_LOGIN");
458 Indicators:SetScript("OnEvent", function(self, event, arg1)
459 if event == "UNIT_AURA" then
461 elseif event == "PLAYER_TARGET_CHANGED" then
462 updateAuras("target");
463 elseif event == "PLAYER_TOTEM_UPDATE" then
465 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
466 for _, boss in pairs(bosses) do
469 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
470 currentSpec = GetSpecialization();
471 for _, frame in pairs(frames) do
472 if frame.auras then updateAuraFrame(frame) end
474 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
477 elseif event == "PLAYER_LOGIN" then