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