625925f - Remove safeties, possible tainting
[wowui.git] / RaidFrameCustomization / Indicators.lua
1 local media = LibStub:GetLibrary("LibSharedMedia-3.0");
2 local f = RaidFrameCustomization.frames;
3 local positions = RaidFrameCustomization.positions;
4 local pad = 2;
5 local paddings = {
6     TOPLEFT = {pad, -pad},
7     TOPRIGHT = {-pad, -pad},
8     CENTER = {0, 0},
9     BOTTOMLEFT = {pad, pad},
10     BOTTOMRIGHT = {-pad, pad}
11 };
12 local watchedAuras; -- all watched auras
13 local auraFilters = {"HELPFUL", "HARMFUL"};
14 local DEFAULT_ICON = "Interface\\AddOns\\RaidFrameCustomization\\images\\rhomb";
15 local _;
16
17 -- global functions used every update
18 local C_TimerAfter = C_Timer.After
19 local GetTime = GetTime;
20 local UnitAura = UnitAura;
21 local UnitIsPlayer = UnitIsPlayer;
22 local UnitIsConnected = UnitIsConnected;
23 local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
24 local CompactRaidFrameContainer_ApplyToFrames = CompactRaidFrameContainer_ApplyToFrames;
25
26 -- list of important auras TODO try to use spellIDs
27 local centerAuras = {
28     "Power Word: Shield"
29 };
30
31 local function configureIndicators(frame, name)
32     local frameName = name or frame:GetName();
33     if not f[frameName] then return end
34
35     local config = RaidFrameCustomization.db.profile;
36     local font = media and media:Fetch('font', config.indicatorFont) or STANDARD_TEXT_FONT;
37     for pos, ind in pairs(f[frameName]) do
38         ind.text:SetFont(font, config[pos]["textSize"]);
39         ind.text:SetTextColor(unpack(config[pos]["textColor"]));
40         ind.icon:SetWidth(config[pos]["iconSize"]);
41         ind.icon:SetHeight(config[pos]["iconSize"]);
42         ind.icon:SetTexture(DEFAULT_ICON);
43         ind.icon:SetVertexColor(unpack(config[pos]["iconColor"]));
44         if config[pos]["showIcon"] then
45             ind.icon:Show();
46         else
47             ind.icon:Hide();
48         end
49     end
50 end
51
52 -- Create the FontStrings used for indicators
53 local function setupCompactUnitFrame(frame, name)
54     f[name] = {};
55     for _, pos in ipairs(positions) do
56         f[name][pos] = {};
57         f[name][pos].text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall");
58         f[name][pos].text:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
59         f[name][pos].icon = frame:CreateTexture(nil, "OVERLAY");
60         f[name][pos].icon:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
61     end
62     configureIndicators(frame, name);
63 end
64
65 -- Check the indicators on a frame and update the times on them
66 local function updateIndicators(frame)
67     local frameName = frame:GetName();
68     local unit = frame.unit;
69
70     -- Create indicators if needed
71     if not f[frameName] then setupCompactUnitFrame(frame, frameName) end
72     -- Reset current
73     for _, ind in pairs(f[frameName]) do
74         ind.text:SetText("");
75         ind.icon:SetTexture("");
76     end
77     -- Hide if unit is dead/disconnected
78     if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then
79         return;
80     end
81
82     local name, icon, count, debuff, expires, caster, id;
83     local current = GetTime();
84     for _, filter in ipairs(auraFilters) do
85         local i = 1;
86         while true do
87             name, _, icon, count, debuff, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
88             if not id then break end
89             local pos = watchedAuras[name] or watchedAuras[id] or watchedAuras[debuff];
90             if pos then
91                 local config = RaidFrameCustomization.db.profile[pos];
92                 if not config.mine or UnitIsPlayer(caster) then
93                     if config.showIcon and not config.useDefaultIcon then
94                         -- show icon
95                         ind.icon:SetTexture(icon);
96                     end
97                     if config.showText then
98                         -- show text
99                         local text;
100                         local remaining = expires - current;
101                         if remaining > 60 then
102                             text = string.format("%dm", ceil(remaining/60));
103                         else
104                             text = string.format("%d", floor(remaining+0.5));
105                         end
106                         if count > 1 and config.stack then
107                             if text then
108                                 text = count.."-"..text;
109                             else
110                                 text = count;
111                             end
112                         end
113
114                         ind.text:SetText(text);
115                     end
116                 end
117             end
118             i = i + 1;
119         end
120     end
121 end
122
123 -- Update all indicators
124 function RaidFrameCustomization:UpdateAllIndicators()
125     CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", updateIndicators);
126     if self.running then
127         C_TimerAfter(0.15, self:UpdateAllIndicators);
128     end
129 end
130
131 -- Used to update everything that is affected by the configuration
132 function RaidFrameCustomization:RefreshConfig()
133     self:OnDisable(); -- clear everything
134     if self.db.profile.enabled then
135         CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", configureIndicators);
136         -- Format aura strings
137         watchedAuras = {};
138         for _, pos in ipairs(positions) do
139             for _, aura in ipairs(self.db.profile[pos]["auras"]) do
140                 watchedAuras[aura] = pos; -- TODO single aura only in one position
141             end
142         end
143
144         if next(watchedAuras) ~= nil then
145             self.running = true;
146             C_TimerAfter(0.15, self:UpdateAllIndicators);
147         end
148     end
149 end