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 spec = 3, -- Retribution
107 auras = {"Divine Purpose"},
108 auraFilter = "PLAYER HELPFUL",
116 spec = 2, -- Protection
117 auras = {"Shield of the Righteous"},
118 auraFilter = "PLAYER HELPFUL",
126 auras = {"Divine Shield"},
127 auraFilter = "PLAYER HELPFUL",
137 auras = {"Shadow Word: Pain", "Purge the Wicked"},
138 auraFilter = "PLAYER HARMFUL",
146 auras = {"Power Word: Fortitude"},
147 auraFilter = "HELPFUL",
156 auras = {"Overcharge Mana"},
157 auraFilter = "PLAYER HELPFUL",
166 totems = {1}, -- Efflorescence
176 auras = {"Tidal Waves"},
177 auraFilter = "PLAYER HELPFUL",
185 auras = {"Healing Rain"},
186 auraFilter = "PLAYER HELPFUL",
194 auras = {"Unleash Life"},
195 auraFilter = "PLAYER HELPFUL",
206 -- unit = unitID where to check auras, not required for totem checkers
207 -- spec = player spec index to show frame, if nil show always
208 -- auras = list of auras to track, in priority order
209 -- auraFilter = filter for UnitAura
210 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
211 -- x = x position relative to UIParent bottom left
212 -- y = y position relative to UIParent bottom left
216 -- global frames' settings
220 auras = {"Innervate"},
221 auraFilter = "HELPFUL",
230 "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
231 "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
232 "Time Bomb", "Broken Shard", "Demolished", "Fetid Rot", "Roiling Deceit",
233 "Putrid Blood", "Endemic Virus", "Lingering Infection", "Gigavolt Charge",
234 "Crackling Lightning", "Storm's Wail", "Death's Door", "Deathly Withering",
235 "Chilling Touch", "Volatile Charge", "Liquid Gold", "Drained Soul"
237 auraFilter = "HARMFUL",
246 local units = {}; -- mapping from unitID to frames
247 local totems = {}; -- mapping to frames with totems
249 for i = 1, MAX_BOSS_FRAMES do
250 bosses[i] = "boss"..i;
252 local currentSpec = 0; -- 0 is invalid
254 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
256 local function updateAuraFrame(frame)
257 local unit = frame.unit;
258 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
259 local name, icon, count, duration, expires;
260 local auraFilter = frame.auraFilter;
263 name, icon, count, _, duration, expires = UnitAura(unit, i, auraFilter);
264 if not name then break end
265 -- possible improvement to add spellID as an option
266 if frame.auras[name] and not frame.invert then
268 frame.stack:SetText(count);
274 frame.cd:SetCooldown(expires - duration, duration);
279 frame.icon:SetTexture(icon);
282 elseif frame.auras[name] and frame.invert then
283 frame.icon:SetTexture(icon);
290 frame:Show(); -- not functional without first hiding once to get SetTexture
297 local function updateAuras(unit)
299 for _, i in pairs(units[unit]) do
300 updateAuraFrame(frames[i]);
305 local function updateTotemFrame(frame, slot)
306 local _, name, start, duration, icon = GetTotemInfo(slot);
308 frame.cd:SetCooldown(start, duration);
310 frame.icon:SetTexture(icon);
317 local function updateTotems(slot)
319 for _, i in pairs(totems[slot]) do
320 updateTotemFrame(frames[i], slot);
325 local function createTMW(name, config, parent)
326 local frame = CreateFrame("Frame", name, parent);
327 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
328 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
329 frame.unit = config.unit;
330 frame.spec = config.spec;
333 for _, v in pairs(config.auras) do
334 frame.auras[v] = true;
337 frame.auraFilter = config.auraFilter;
338 frame.totems = config.totems;
339 frame.invert = config.invert;
341 frame.base = frame:CreateTexture(nil, "BACKGROUND");
342 frame.base:SetAllPoints();
343 frame.base:SetColorTexture(0, 0, 0, 0.6);
344 frame.icon = frame:CreateTexture(nil, "ARTWORK");
345 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
346 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
347 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
348 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
349 frame.stack:SetPoint("TOPLEFT");
351 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
352 frame.cd:SetReverse(true);
353 frame.cd:SetAllPoints();
357 local function initialize()
358 Indicators:SetFrameStrata("LOW");
359 Indicators:SetPoint("BOTTOMLEFT");
360 Indicators:SetWidth(1);
361 Indicators:SetHeight(1);
362 currentSpec = GetSpecialization();
363 local name, realm = UnitFullName("player");
364 if chars[realm] and chars[realm][name] then
365 for _, config in pairs(chars[realm][name]) do
366 table.insert(settings, config)
369 for i, config in pairs(settings) do
371 if not units[config.unit] then units[config.unit] = {} end
372 table.insert(units[config.unit], i);
374 if config.totems then
375 for _, slot in pairs(config.totems) do
376 if not totems[slot] then totems[slot] = {} end
377 table.insert(totems[slot], i);
380 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
383 for _, frame in pairs(frames) do
384 if frame.auras then updateAuraFrame(frame) end
386 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
391 Indicators:RegisterEvent("UNIT_AURA");
392 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
393 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
394 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
395 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
396 Indicators:RegisterEvent("PLAYER_LOGIN");
397 Indicators:SetScript("OnEvent", function(self, event, arg1)
398 if event == "UNIT_AURA" then
400 elseif event == "PLAYER_TARGET_CHANGED" then
401 updateAuras("target");
402 elseif event == "PLAYER_TOTEM_UPDATE" then
404 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
405 for _, boss in pairs(bosses) do
408 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
409 currentSpec = GetSpecialization();
410 for _, frame in pairs(frames) do
411 if frame.auras then updateAuraFrame(frame) end
413 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
416 elseif event == "PLAYER_LOGIN" then