3ddb182 - Fix insecure boss frames
[wowui.git] / OmaRF / Indicators.lua
index c408815..6fd7b23 100644 (file)
 -- Indicators.lua
 local pairs, ipairs = pairs, ipairs;
+local floor = math.floor;
 local GetTime = GetTime;
 local UnitAura = UnitAura;
-local UnitIsPlayer = UnitIsPlayer;
+local CreateFrame = CreateFrame;
+local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
 local CTimerAfter = C_Timer.After;
 
-local watchedAuras = {
-    [53563] = "TOPRIGHT",
-    [156910] = "TOPRIGHT",
-    [200025] = "TOPRIGHT",
-    [200654] = "BOTTOMLEFT",
-};
-local majorAuras = {
-    ["Psychic Assault"] = true,
-    ["Everburning Flames"] = true,
-    ["Corrupt"] = true,
-    ["Sleep Canister"] = true,
-    ["Misery"] = true,
-    ["Necrotic Embrace"] = true,
-    ["Fulminating Pulse"] = true,
-    ["Chilled Blood"] = true,
-    ["Soulblight"] = true,
-    ["Soulburst"] = true,
-    ["Soulbomb"] = true,
-    ["Aqua Bomb"] = true,
-};
+local Settings = OmaRFSettings;
+local majorAuras = Settings.MajorAuras;
+local watchedAuras = {};
 
 local updaters = {};
-local positions = {"TOPRIGHT", "BOTTOMLEFT"};
+local updating = {};
 local auraFilters = {"HELPFUL", "HARMFUL"};
 
--- TODO text
---[[local function remaining(expires, current)
-    if expires == 0 then return "" end
+local M = {};
+OmaRFIndicators = M;
+M.Class = {};
+
+function M.SetupIndicators(frame, class)
+    frame.indBase = CreateFrame("Frame", nil, frame);
+    frame.indBase:SetAllPoints();
+    frame.indBase:Hide();
+    if M.Class[class] then
+        watchedAuras = M.Class[class].Auras;
+        frame.inds = M.Class[class].Setup(frame.indBase);
+    else
+        frame.inds = {};
+    end
+
+    frame.majorBase = CreateFrame("Frame", nil, frame);
+    frame.majorBase:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -10);
+    frame.majorBase:SetPoint("BOTTOMRIGHT");
+    frame.majors = {};
+    for i = 1,3 do
+        local tex = frame.majorBase:CreateTexture(nil, "OVERLAY");
+        tex = frame.majorBase:CreateTexture(nil, "OVERLAY");
+        if i == 1 then tex:SetPoint("TOPLEFT", frame.majorBase, "TOPLEFT");
+        else tex:SetPoint("TOPLEFT", frame.majors[i-1], "TOPRIGHT"); end
+        tex:SetWidth(20);
+        tex:SetHeight(20);
+        tex:Hide();
+        tex.text = frame.majorBase:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
+        tex.text:SetPoint("CENTER", tex, "BOTTOMRIGHT", -2, 2);
+        tex.text:Hide();
+        tex.stack = frame.majorBase:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
+        tex.stack:SetPoint("CENTER", tex, "TOPLEFT", 1, 0);
+        tex.stack:Hide();
+        tex.icon = true;
+        frame.majors[i] = tex;
+    end
+end
+
+local function remaining(text, expires, current)
+    if expires == 0 then
+        text:SetText("");
+        return false;
+    end
     local remain = expires - current;
-    if remain > 60 then
-        return format("%dm", ceil(remain/60));
+    if remain > 8 then
+        text:SetText("");
+    else
+        text:SetText(floor(remain+0.5));
     end
-    return floor(remain+0.5);
-end]]
+    return true;
+end
 
---[[local function updateIndicators(frame, unit)
-    if not frame:IsShown() then
-        return;
-    elseif not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then
-        if frame.inds:IsShown() then frame.inds:Hide() end
+local function updateIndicators(frame)
+    local unit = frame.displayed;
+    if not frame:IsShown() or not UnitIsConnected(unit) or UnitIsDeadOrGhost(unit) then
+        updating[frame] = nil;
         return;
-    elseif not frame.inds:IsShown() then
-        frame.inds:Show();
     end
 
+    local needUpdate = false;
     local current = GetTime();
-    for pos, ind in pairs(frame.inds) do
-        if ind.expires ~= nil then
-            if OmaRF.db.profile.indicators[pos].showText then
-                ind.text:SetText(remaining(ind.expires, current));
-            end
-        else
-            if ind.icon:IsShown() then ind.icon:Hide() end
-            if ind.text:IsShown() then ind.text:Hide() end
+    for _, ind in pairs(frame.inds) do
+        if ind.text and ind.text.expires ~= nil then
+            needUpdate = remaining(ind.text, ind.text.expires, current) or needUpdate;
         end
     end
-    for _, ind in ipairs(frame.majorInds) do
-        if ind.expires ~= nil then
-            ind.expireText:SetText(remaining(ind.expires, current));
-        else
-            if ind.icon:IsShown() then ind.icon:Hide() end
-            if ind.expireText:IsShown() then ind.expireText:Hide() end
-            if ind.stackText:IsShown() then ind.stackText:Hide() end
+    for _, ind in pairs(frame.majors) do
+        if ind.text and ind.text.expires ~= nil then
+            needUpdate = remaining(ind.text, ind.text.expires, current) or needUpdate;
         end
     end
-end]]
-
---local function showIndicator(ind, caster, expires, current, config)
-local function showIndicator(ind, caster)
-    --if not config.mine or UnitIsPlayer(caster) then
-    if UnitIsPlayer(caster) then
-        --if config.showIcon and not ind:IsShown() then
-        if not ind:IsShown() then
-            ind:Show();
-        end
-        --ind.expires = expires;
-        --[[if config.showText then
-            ind.text:SetText(remaining(expires, current));
-            if not ind.text:IsShown() then ind.text:Show() end
-        end]]
+    if needUpdate then
+        CTimerAfter(0.16, updaters[frame]);
+    else
+        updating[frame] = nil;
     end
 end
 
-function OmaCheckIndicators(frame, unit)
-    for _, pos in pairs(positions) do
-        --ind.expires = nil;
-        if frame.inds[pos]:IsShown() then frame.inds[pos]:Hide() end
+local function showInd(ind, expires, current, count, icon)
+    local needUpdate = false;
+    if ind.icon then
+        ind:SetTexture(icon);
     end
-    for i = 1,3 do
-        --ind.expires = nil;
-        if frame.major[1]:IsShown() then frame.major[1]:Hide() end
+    if ind.text then
+        needUpdate = remaining(ind.text, expires, current);
+        ind.text.expires = expires;
+        ind.text:Show();
+    end
+    if ind.stack and count > 1 then
+        ind.stack:SetText(count);
+        ind.stack:Show();
+    end
+    ind:Show();
+    return needUpdate;
+end
+
+local function hideInd(ind)
+    if ind.text then
+        ind.text.expires = nil;
+        ind.text:Hide();
     end
-    frame.showInds = false;
-    frame.showMajors = false;
+    if ind.stack then ind.stack:Hide() end
+    ind:Hide();
+end
 
+function M.CheckIndicators(frame, unit)
+    for _, ind in pairs(frame.inds) do
+        hideInd(ind);
+    end
+    for _, ind in pairs(frame.majors) do
+        hideInd(ind);
+    end
     local name, icon, count, expires, caster, id;
+    local showInds, showMajors, needUpdate = false, false, false;
     local majorPos = 1;
+    local alert = false; -- color the whole bar
     local current = GetTime();
     for _, filter in ipairs(auraFilters) do
         local i = 1;
@@ -109,37 +138,37 @@ function OmaCheckIndicators(frame, unit)
             name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
             if not id then break end
             local pos = watchedAuras[id] or watchedAuras[name];
-            if pos then
-                frame.showInds = true;
-                if UnitIsPlayer(caster) and not frame.inds[pos]:IsShown() then
-                    frame.inds[pos]:Show();
-                end
+            if pos and caster == "player" then
+                needUpdate = showInd(frame.inds[pos], expires, current, count, icon) or needUpdate;
+                showInds = true;
             end
-            if (majorAuras[id] or majorAuras[name]) and majorPos <= 3 then
-                frame.major[majorPos]:SetTexture(icon);
-                frame.major[majorPos]:Show();
-                frame.showMajors = true;
+            local major = majorAuras[id] or majorAuras[name];
+            if major and majorPos <= 3 then
+                needUpdate = showInd(frame.majors[majorPos], expires, current, count, icon) or needUpdate;
+                if major.bar then alert = true end
+                showMajors = true;
                 majorPos = majorPos + 1;
             end
             i = i + 1;
         end
     end
-    if frame.showInds then
-        if not frame.inds:IsShown() then frame.inds:Show() end
-        -- create a function for updating the indicator each second
-        --[[local func = updaters[frame];
-        if not func then
-            func = function() updateIndicators(frame, unit) end;
-            updaters[frame] = func;
+    if showInds or showMajors then
+        frame.indBase:Show();
+        frame.majorBase:Show();
+        if needUpdate and not updating[frame] then
+            updating[frame] = true; -- race?
+            -- create a function for updating the indicator
+            local func = updaters[frame];
+            if not func then
+                func = function() updateIndicators(frame) end;
+                updaters[frame] = func;
+            end
+            CTimerAfter(0.16, func);
         end
-        CTimerAfter(1, func);]]
-    elseif frame.inds:IsShown() then
-        frame.inds:Hide();
+    else
+        frame.indBase:Hide();
+        frame.majorBase:Hide();
     end
-    if frame.showMajors then
-        if not frame.major:IsShown() then frame.major:Show() end
-    elseif frame.major:IsShown() then
-        frame.major:Hide();
-    end
-end
 
+    return alert;
+end