b7ba1e801b82c8209487f6383746f07c3e3ae28c
[wowui.git] / OmaTMW / TellMeWhen.lua
1 -- TellMeWhen.lua
2 local _;
3 local pairs = pairs;
4 local GetSpecialization = GetSpecialization;
5 local UnitExists = UnitExists;
6 local UnitAura = UnitAura;
7 local GetTotemInfo = GetTotemInfo;
8
9 -- character specific frames
10 local chars = {
11     ["Stormreaver"] = {
12         ["Vildan"] = {
13             {
14                 unit = "target",
15                 spec = 3, -- Retribution
16                 auras = {"Judgment"},
17                 auraFilter = "PLAYER HARMFUL",
18                 x = 570, -- placed over Innervate frame
19                 y = 440,
20                 width = 80,
21                 height = 80,
22             },
23             {
24                 unit = "player",
25                 spec = 3, -- Retribution
26                 auras = {"Divine Purpose"},
27                 auraFilter = "PLAYER HELPFUL",
28                 x = 570,
29                 y = 530,
30                 width = 80,
31                 height = 80,
32             },
33             {
34                 unit = "player",
35                 spec = 2, -- Protection
36                 auras = {"Shield of the Righteous"},
37                 auraFilter = "PLAYER HELPFUL",
38                 x = 570,
39                 y = 440,
40                 width = 80,
41                 height = 80,
42             },
43             {
44                 unit = "player",
45                 auras = {"Divine Shield"},
46                 auraFilter = "PLAYER HELPFUL",
47                 x = 660,
48                 y = 440,
49                 width = 80,
50                 height = 80,
51             },
52         },
53         ["Gedren"] = {
54             {
55                 totems = {1},
56                 x = 570,
57                 y = 440,
58                 width = 80,
59                 height = 80,
60             },
61         },
62     },
63 };
64
65 -- settings entry:
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 -- auraFilter = filter for UnitAura
70 -- totems = list of totem slots to track, in priority order, only checked if auras is nil
71 -- x = x position relative to UIParent bottom left
72 -- y = y position relative to UIParent bottom left
73 -- width = width
74 -- height = height
75
76 -- global frames' settings
77 local settings = {
78     {
79         unit = "player",
80         auras = {"Innervate"},
81         auraFilter = "HELPFUL",
82         x = 570,
83         y = 440,
84         width = 80,
85         height = 80,
86     },
87     {
88         unit = "player",
89         auras = {
90             "Delusions", "Entropic Blast", "Necrotic Embrace", "Flametouched", "Shadowtouched",
91             "Blazing Eruption", "Shattering Scream", "Consuming Hunger", "Unstable Soul",
92             "Time Bomb", "Broken Shard",
93         },
94         auraFilter = "HARMFUL",
95         x = 660,
96         y = 530,
97         width = 80,
98         height = 80,
99     },
100 };
101
102 local frames = {};
103 local units = {}; -- mapping from unitID to frames
104 local totems = {}; -- mapping to frames with totems
105 local bosses = {};
106 for i = 1, MAX_BOSS_FRAMES do
107     bosses[i] = "boss"..i;
108 end
109 local currentSpec = 0; -- 0 is invalid
110
111 local Indicators = CreateFrame("Frame", "OmaTMW", UIParent);
112
113 local function updateAuraFrame(frame)
114     local unit = frame.unit;
115     if UnitExists(unit) and (not frame.spec or frame.spec == currentSpec) then
116         local name, icon, count, duration, expires;
117         for _, aura in pairs(frame.auras) do
118             name, _, icon, count, _, duration, expires =  UnitAura(unit, aura, nil, frame.auraFilter);
119             if name then
120                 if count > 0 then
121                     frame.stack:SetText(count);
122                     frame.stack:Show();
123                 else
124                     frame.stack:Hide();
125                 end
126                 if expires > 0 then
127                     frame.cd:SetCooldown(expires - duration, duration);
128                     frame.cd:Show();
129                 else
130                     frame.cd:Hide();
131                 end
132                 frame.icon:SetTexture(icon);
133                 frame:Show();
134                 return;
135             end
136         end
137     end
138     frame:Hide();
139 end
140
141 local function updateAuras(unit)
142     if units[unit] then
143         for _, i in pairs(units[unit]) do
144             updateAuraFrame(frames[i]);
145         end
146     end
147 end
148
149 local function updateTotemFrame(frame, slot)
150     local _, name, start, duration, icon = GetTotemInfo(slot);
151     if name ~= "" then
152         frame.cd:SetCooldown(start, duration);
153         frame.cd:Show();
154         frame.icon:SetTexture(icon);
155         frame:Show();
156     else
157         frame:Hide();
158     end
159 end
160
161 local function updateTotems(slot)
162     if totems[slot] then
163         for _, i in pairs(totems[slot]) do
164             updateTotemFrame(frames[i], slot);
165         end
166     end
167 end
168
169 local function createTMW(name, config, parent)
170     local frame = CreateFrame("Frame", name, parent);
171     frame:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y+config.height);
172     frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", config.x+config.width, config.y);
173     frame.unit = config.unit;
174     frame.spec = config.spec;
175     frame.auras = config.auras;
176     frame.auraFilter = config.auraFilter;
177     frame.totems = config.totems;
178     frame:Hide();
179     frame.base = frame:CreateTexture(nil, "BACKGROUND");
180     frame.base:SetAllPoints();
181     frame.base:SetColorTexture(0, 0, 0, 0.6);
182     frame.icon = frame:CreateTexture(nil, "ARTWORK");
183     frame.icon:SetPoint("TOPLEFT", frame.base, "TOPLEFT", 1, -1);
184     frame.icon:SetPoint("BOTTOMRIGHT", frame.base, "BOTTOMRIGHT", -1, 1);
185     frame.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
186     frame.stack = frame:CreateFontString(nil, "OVERLAY", "NumberFontNormalLarge");
187     frame.stack:SetPoint("TOPLEFT");
188     frame.stack:Hide();
189     frame.cd = CreateFrame("Cooldown", name.."CD", frame, "CooldownFrameTemplate");
190     frame.cd:SetReverse(true);
191     frame.cd:SetAllPoints();
192     return frame;
193 end
194
195 local function initialize()
196     Indicators:SetFrameStrata("LOW");
197     Indicators:SetPoint("BOTTOMLEFT");
198     Indicators:SetWidth(1);
199     Indicators:SetHeight(1);
200     currentSpec = GetSpecialization();
201     local name, realm = UnitFullName("player");
202     if chars[realm] and chars[realm][name] then
203         for _, config in pairs(chars[realm][name]) do
204             table.insert(settings, config)
205         end
206     end
207     for i, config in pairs(settings) do
208         if config.unit then
209             if not units[config.unit] then units[config.unit] = {} end
210             table.insert(units[config.unit], i);
211         end
212         if config.totems then
213             for _, slot in pairs(config.totems) do
214                 if not totems[slot] then totems[slot] = {} end
215                 table.insert(totems[slot], i);
216             end
217         end
218         frames[i] = createTMW("OmaTMW"..i, config, Indicators);
219     end
220
221     for _, frame in pairs(frames) do
222         if frame.auras then updateAuraFrame(frame) end
223         if frame.totems then
224             for _, slot in pairs(frame.totems) do updateTotemFrame(frame, slot) end
225         end
226     end
227 end
228
229 Indicators:RegisterEvent("UNIT_AURA");
230 Indicators:RegisterEvent("PLAYER_TARGET_CHANGED");
231 Indicators:RegisterEvent("PLAYER_TOTEM_UPDATE");
232 Indicators:RegisterEvent("INSTANCE_ENCOUNTER_ENGAGE_UNIT");
233 Indicators:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
234 Indicators:RegisterEvent("PLAYER_LOGIN");
235 Indicators:SetScript("OnEvent", function(self, event, arg1)
236     if event == "UNIT_AURA" then
237         updateAuras(arg1);
238     elseif event == "PLAYER_TARGET_CHANGED" then
239         updateAuras("target");
240     elseif event == "PLAYER_TOTEM_UPDATE" then
241         updateTotems(arg1);
242     elseif event == "INSTANCE_ENCOUNTER_ENGAGE_UNIT" then
243         for _, boss in pairs(bosses) do
244             updateAuras(boss);
245         end
246     elseif event == "PLAYER_SPECIALIZATION_CHANGED" then
247         currentSpec = GetSpecialization();
248         for _, frame in pairs(frames) do
249             if frame.auras then updateAuraFrame(frame) end
250             if frame.totems then updateTotemFrame(frame) end
251         end
252     elseif event == "PLAYER_LOGIN" then
253         initialize();
254     end
255 end);