4 local GetSpecialization = GetSpecialization;
5 local UnitExists = UnitExists;
6 local UnitAura = UnitAura;
7 local GetTotemInfo = GetTotemInfo;
9 -- character specific frames
15 spec = 3, -- Retribution
17 auraFilter = "PLAYER HARMFUL",
18 x = 570, -- placed over Innervate frame
25 spec = 3, -- Retribution
26 auras = {"Divine Purpose"},
27 auraFilter = "PLAYER HELPFUL",
35 spec = 2, -- Protection
36 auras = {"Shield of the Righteous"},
37 auraFilter = "PLAYER HELPFUL",
45 auras = {"Divine Shield"},
46 auraFilter = "PLAYER HELPFUL",
55 totems = {1}, -- Efflorescence
66 -- unit = unitID where to check auras, not required for totem checkers
67 -- spec = player spec index to show frame, if nil show always
68 -- auras = list of auras to track, in priority order
69 -- iterateAuras = iterate over UnitAura() instead of auras list
70 -- auraFilter = filter for UnitAura
71 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
72 -- x = x position relative to UIParent bottom left
73 -- y = y position relative to UIParent bottom left
77 -- global frames' settings
81 auras = {"Innervate"},
82 auraFilter = "HELPFUL",
91 "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
92 "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
93 "Time Bomb", "Broken Shard",
95 iterateAuras = true, -- typically fewer debuffs on player than this list
96 auraFilter = "HARMFUL",
105 local units = {}; -- mapping from unitID to frames
106 local totems = {}; -- mapping to frames with totems
108 for i = 1, MAX_BOSS_FRAMES do
109 bosses[i] = "boss"..i;
111 local currentSpec = 0; -- 0 is invalid
113 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
115 local function updateAuraFrame(frame)
116 local unit = frame.unit;
117 if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
118 local name, icon, count, duration, expires;
119 local auraFilter = frame.auraFilter;
120 if frame.iterateAuras then
123 name, _, icon, count, _, duration, expires = UnitAura(unit, i, auraFilter);
124 if not name then break end
125 -- possible improvement to add spellID as an option
126 if frame.auras[name] then
128 frame.stack:SetText(count);
134 frame.cd:SetCooldown(expires - duration, duration);
139 frame.icon:SetTexture(icon);
146 for _, aura in pairs(frame.auras) do
147 name, _, icon, count, _, duration, expires = UnitAura(unit, aura, nil, auraFilter);
150 frame.stack:SetText(count);
156 frame.cd:SetCooldown(expires - duration, duration);
161 frame.icon:SetTexture(icon);
171 local function updateAuras(unit)
173 for _, i in pairs(units[unit]) do
174 updateAuraFrame(frames[i]);
179 local function updateTotemFrame(frame, slot)
180 local _, name, start, duration, icon = GetTotemInfo(slot);
182 frame.cd:SetCooldown(start, duration);
184 frame.icon:SetTexture(icon);
191 local function updateTotems(slot)
193 for _, i in pairs(totems[slot]) do
194 updateTotemFrame(frames[i], slot);
199 local function createTMW(name, config, parent)
200 local frame = CreateFrame("Frame", name, parent);
201 frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
202 frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
203 frame.unit = config.unit;
204 frame.spec = config.spec;
205 frame.iterateAuras = config.iterateAuras;
206 if frame.iterateAuras then
208 for _, v in pairs(config.auras) do
209 frame.auras[v] = true;
212 frame.auras = config.auras;
214 frame.auraFilter = config.auraFilter;
215 frame.totems = config.totems;
217 frame.base = frame:CreateTexture(nil, "BACKGROUND");
218 frame.base:SetAllPoints();
219 frame.base:SetColorTexture(0, 0, 0, 0.6);
220 frame.icon = frame:CreateTexture(nil, "ARTWORK");
221 frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
222 frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
223 frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
224 frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
225 frame.stack:SetPoint("TOPLEFT");
227 frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
228 frame.cd:SetReverse(true);
229 frame.cd:SetAllPoints();
233 local function initialize()
234 Indicators:SetFrameStrata("LOW");
235 Indicators:SetPoint("BOTTOMLEFT");
236 Indicators:SetWidth(1);
237 Indicators:SetHeight(1);
238 currentSpec = GetSpecialization();
239 local name, realm = UnitFullName("player");
240 if chars[realm] and chars[realm][name] then
241 for _, config in pairs(chars[realm][name]) do
242 table.insert(settings, config)
245 for i, config in pairs(settings) do
247 if not units[config.unit] then units[config.unit] = {} end
248 table.insert(units[config.unit], i);
250 if config.totems then
251 for _, slot in pairs(config.totems) do
252 if not totems[slot] then totems[slot] = {} end
253 table.insert(totems[slot], i);
256 frames[i] = createTMW("OmaTMW"..i, config, Indicators);
259 for _, frame in pairs(frames) do
260 if frame.auras then updateAuraFrame(frame) end
262 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
267 Indicators:RegisterEvent("UNIT_AURA");
268 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
269 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
270 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
271 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
272 Indicators:RegisterEvent("PLAYER_LOGIN");
273 Indicators:SetScript("OnEvent", function(self, event, arg1)
274 if event == "UNIT_AURA" then
276 elseif event == "PLAYER_TARGET_CHANGED" then
277 updateAuras("target");
278 elseif event == "PLAYER_TOTEM_UPDATE" then
280 elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
281 for _, boss in pairs(bosses) do
284 elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
285 currentSpec = GetSpecialization();
286 for _, frame in pairs(frames) do
287 if frame.auras then updateAuraFrame(frame) end
289 for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
292 elseif event == "PLAYER_LOGIN" then