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