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