d9a8d3f - Fix small issues, use StateDrivers instead of reimplementing
[wowui.git] / OmaRF / Indicators.lua
1 -- Indicators.lua
2 local pairs, ipairs = pairs, ipairs;
3 local floor = math.floor;
4 local GetTime = GetTime;
5 local UnitAura = UnitAura;
6 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
7 local CTimerAfter = C_Timer.After;
8
9 local Frames = OmaFrames;
10 local positions = Frames.Positions;
11
12 local watchedAuras = {
13     [53563] = "TOPRIGHT",
14     [156910] = "TOPRIGHT",
15     [200025] = "TOPRIGHT",
16     [200654] = "BOTTOMLEFT",
17 };
18 local majorAuras = {
19     ["Psychic Assault"] = true,
20     ["Everburning Flames"] = true,
21     ["Corrupt"] = true,
22     ["Sleep Canister"] = true,
23     ["Misery"] = true,
24     ["Necrotic Embrace"] = true,
25     ["Fulminating Pulse"] = true,
26     ["Chilled Blood"] = true,
27     ["Soulblight"] = true,
28     ["Soulburst"] = true,
29     ["Soulbomb"] = true,
30     ["Aqua Bomb"] = true,
31 };
32
33 local updaters = {};
34 local updating = {};
35 local auraFilters = {"HELPFUL", "HARMFUL"};
36
37 local M = {};
38 OmaIndicators = M;
39
40 local function remaining(text, expires, current)
41     if expires == 0 then
42         text:SetText("");
43         return false;
44     end
45     local remain = expires - current;
46     if remain > 8 then
47         text:SetText("");
48     else
49         text:SetText(floor(remain+0.5));
50     end
51     return true;
52 end
53
54 local function updateIndicators(frame, unit)
55     if not frame:IsShown() or not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then
56         updating[frame] = nil;
57         return;
58     end
59
60     local needUpdate = false;
61     local current = GetTime();
62     for _, pos in pairs(positions) do
63         local ind = frame.inds[pos];
64         if ind.expires ~= nil then
65             needUpdate = remaining(ind.text, ind.expires, current) or needUpdate;
66         end
67     end
68     for i = 1,3 do
69         local ind = frame.major[i];
70         if ind.expires ~= nil then
71             needUpdate = remaining(ind.text, ind.expires, current) or needUpdate;
72         end
73     end
74     if needUpdate then
75         CTimerAfter(0.16, updaters[frame]);
76     else
77         updating[frame] = nil;
78     end
79 end
80
81 function M.CheckIndicators(frame, unit)
82     for _, pos in pairs(positions) do
83         frame.inds[pos].expires = nil;
84         frame.inds[pos]:Hide();
85         frame.inds[pos].text:Hide();
86     end
87     for i = 1,3 do
88         frame.major[i].expires = nil;
89         frame.major[i]:Hide();
90         frame.major[i].text:Hide();
91         frame.major[i].stack:Hide();
92     end
93     local name, icon, count, expires, caster, id;
94     local showInds, showMajors, needUpdate = false, false, false;
95     local majorPos = 1;
96     local current = GetTime();
97     for _, filter in ipairs(auraFilters) do
98         local i = 1;
99         while true do
100             name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
101             if not id then break end
102             local pos = watchedAuras[id] or watchedAuras[name];
103             if pos and caster == "player" then
104                 needUpdate = remaining(frame.inds[pos].text, expires, current);
105                 frame.inds[pos].expires = expires;
106                 frame.inds[pos]:Show();
107                 frame.inds[pos].text:Show();
108                 showInds = true;
109             end
110             if (majorAuras[id] or majorAuras[name]) and majorPos <= 3 then
111                 needUpdate = remaining(frame.major[majorPos].text, expires, current);
112                 frame.major[majorPos].expires = expires;
113                 frame.major[majorPos]:SetTexture(icon);
114                 frame.major[majorPos]:Show();
115                 frame.major[majorPos].text:Show();
116                 if count > 1 then
117                     frame.major[majorPos].stack:SetText(count);
118                     frame.major[majorPos].stack:Show();
119                 end
120                 showMajors = true;
121                 majorPos = majorPos + 1;
122             end
123             i = i + 1;
124         end
125     end
126     if showInds or showMajors then
127         frame.inds:Show();
128         frame.major:Show();
129         if needUpdate and not updating[frame] then
130             updating[frame] = true; -- race?
131             -- create a function for updating the indicator
132             local func = updaters[frame];
133             if not func then
134                 func = function() updateIndicators(frame, unit) end;
135                 updaters[frame] = func;
136             end
137             CTimerAfter(0.16, func);
138         end
139     else
140         frame.inds:Hide();
141         frame.major:Hide();
142     end
143 end