a4dcd1d - Fix inspect waiting extra 60 sec
[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 CreateFrame = CreateFrame;
7 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
8 local CTimerAfter = C_Timer.After;
9
10 local Settings = OmaRFSettings;
11 local majorAuras = Settings.MajorAuras;
12 local watchedAuras = {};
13
14 local updaters = {};
15 local updating = {};
16
17 local M = {};
18 OmaRFIndicators = M;
19 M.Class = {};
20
21 function M.SetupIndicators(frame, class)
22     frame.indBase = CreateFrame("Frame", nil, frame);
23     frame.indBase:SetAllPoints();
24     frame.indBase:Hide();
25     if M.Class[class] then
26         watchedAuras = M.Class[class].Auras;
27         frame.inds = M.Class[class].Setup(frame.indBase);
28     else
29         frame.inds = {};
30     end
31
32     frame.majorBase = CreateFrame("Frame", nil, frame);
33     frame.majorBase:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -10);
34     frame.majorBase:SetPoint("BOTTOMRIGHT");
35     frame.majors = {};
36     for i = 1,3 do
37         local tex = frame.majorBase:CreateTexture(nil, "OVERLAY");
38         tex = frame.majorBase:CreateTexture(nil, "OVERLAY");
39         if i == 1 then tex:SetPoint("TOPLEFT", frame.majorBase, "TOPLEFT");
40         else tex:SetPoint("TOPLEFT", frame.majors[i-1], "TOPRIGHT"); end
41         tex:SetWidth(20);
42         tex:SetHeight(20);
43         tex:Hide();
44         tex.text = frame.majorBase:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
45         tex.text:SetPoint("CENTER", tex, "BOTTOMRIGHT", -2, 2);
46         tex.text:Hide();
47         tex.stack = frame.majorBase:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
48         tex.stack:SetPoint("CENTER", tex, "TOPLEFT", 1, 0);
49         tex.stack:Hide();
50         tex.icon = true;
51         frame.majors[i] = tex;
52     end
53 end
54
55 local function remaining(text, expires, current)
56     if expires == 0 then
57         text:SetText("");
58         return false;
59     end
60     local remain = expires - current;
61     if remain > 8 then
62         text:SetText("");
63     else
64         text:SetText(floor(remain+0.5));
65     end
66     return true;
67 end
68
69 local function updateIndicators(frame)
70     local unit = frame.displayed;
71     if not frame:IsShown() or not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then
72         updating[frame] = nil;
73         return;
74     end
75
76     local needUpdate = false;
77     local current = GetTime();
78     for _, ind in pairs(frame.inds) do
79         if ind.text and ind.text.expires ~= nil then
80             needUpdate = remaining(ind.text, ind.text.expires, current) or needUpdate;
81         end
82     end
83     for _, ind in pairs(frame.majors) do
84         if ind.text and ind.text.expires ~= nil then
85             needUpdate = remaining(ind.text, ind.text.expires, current) or needUpdate;
86         end
87     end
88     if needUpdate then
89         CTimerAfter(0.20, updaters[frame]);
90     else
91         updating[frame] = nil;
92     end
93 end
94
95 local function showInd(ind, expires, current, count, icon)
96     local needUpdate = false;
97     if ind.icon then
98         ind:SetTexture(icon);
99     end
100     if ind.text then
101         needUpdate = remaining(ind.text, expires, current);
102         ind.text.expires = expires;
103         ind.text:Show();
104     end
105     if ind.stack and count > 1 then
106         ind.stack:SetText(count);
107         ind.stack:Show();
108     end
109     ind:Show();
110     return needUpdate;
111 end
112
113 local function hideInd(ind)
114     if ind.text then
115         ind.text.expires = nil;
116         ind.text:Hide();
117     end
118     if ind.stack then ind.stack:Hide() end
119     ind:Hide();
120 end
121
122 function M.CheckIndicators(frame, unit)
123     for _, ind in pairs(frame.inds) do
124         hideInd(ind);
125     end
126     for _, ind in pairs(frame.majors) do
127         hideInd(ind);
128     end
129     local name, icon, count, expires, caster, id;
130     local showInds, showMajors, needUpdate = false, false, false;
131     local majorPos = 1;
132     local alert = false; -- color the whole bar
133     local current = GetTime();
134     for spell, pos in pairs(watchedAuras) do
135         name, _, icon, count, _, _, expires = UnitAura(unit, spell, nil, "PLAYER HELPFUL");
136         if name then
137             needUpdate = showInd(frame.inds[pos], expires, current, count, icon) or needUpdate;
138             showInds = true;
139         end
140     end
141
142     local i = 1;
143     while true do
144         name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, "HARMFUL");
145         if not id or majorPos > 3 then break end
146         local major = majorAuras[id] or majorAuras[name];
147         if major then
148             needUpdate = showInd(frame.majors[majorPos], expires, current, count, icon) or needUpdate;
149             if major.bar then alert = true end
150             showMajors = true;
151             majorPos = majorPos + 1;
152         end
153         i = i + 1;
154     end
155
156     if showInds or showMajors then
157         frame.indBase:Show();
158         frame.majorBase:Show();
159         if needUpdate and not updating[frame] then
160             updating[frame] = true; -- race?
161             -- create a function for updating the indicator
162             local func = updaters[frame];
163             if not func then
164                 func = function() updateIndicators(frame) end;
165                 updaters[frame] = func;
166             end
167             CTimerAfter(0.20, func);
168         end
169     else
170         frame.indBase:Hide();
171         frame.majorBase:Hide();
172     end
173
174     return alert;
175 end