8b1be3a - More auras and stagger tracking
[wowui.git] / kehys / updater.lua
index f51d200..42aedf0 100644 (file)
@@ -5,34 +5,55 @@
 local _, addon = ...;
 local unpack = unpack;
 local min = math.min;
+local format = string.format;
 local UnitDebuff, UnitIsCharmed = UnitDebuff, UnitIsCharmed;
 local UnitHealth, UnitHealthMax = UnitHealth, UnitHealthMax;
+local UnitPower, UnitPowerMax = UnitPower, UnitPowerMax;
 local UnitIsAFK, UnitIsDND = UnitIsAFK, UnitIsDND;
 local UnitGetIncomingHeals, UnitGetTotalAbsorbs = UnitGetIncomingHeals, UnitGetTotalAbsorbs;
 local UnitIsDeadOrGhost, UnitIsConnected = UnitIsDeadOrGhost, UnitIsConnected;
 local UnitGetTotalHealAbsorbs = UnitGetTotalHealAbsorbs;
+local InCombatLockdown, IsResting = InCombatLockdown, IsResting;
+local UnitInRange, UnitInPhase = UnitInRange, UnitInPhase;
 
 local dispelcolor = addon.Colors.OverlayColorDispel;
 local charmcolor = addon.Colors.OverlayColorCharm;
 local majorcolor = addon.Colors.OverlayColorAlert;
 local healcolor = addon.Colors.OverlayColorHeal;
 
-local function updateAuras()
-    -- TODO
-    return false;
-end
+local ignoredAuras = {
+    [315176] = true, -- Grasping Tendrils
+    [313759] = true, -- Cursed Blood (Il'gynoth)
+    [312486] = true, -- Recurring Nightmare (Il'gynoth)
+};
+
+local powerColors = {
+    [Enum.PowerType.Mana] = {0.1, 0.5, 0.9},
+    [Enum.PowerType.Rage] = {1, 0, 0},
+    [Enum.PowerType.Pain] = {1, 0, 0},
+    [Enum.PowerType.Focus] = {1, 0.5, 0},
+    [Enum.PowerType.Energy] = {1, 0.8, 0},
+    [Enum.PowerType.Fury] = {0.8, 0.3, 0.9},
+    [Enum.PowerType.RunicPower] = {0.8, 0, 0.2},
+    [Enum.PowerType.LunarPower] = {0.3, 0.5, 0.9},
+    [Enum.PowerType.Maelstrom] = {0, 0.5, 1},
+    [Enum.PowerType.Insanity] = {0.4, 0, 0.8},
+};
 
 function addon.FrameUpdate(frame)
     assert(type(frame) == "table", "FrameUpdate received invalid frame parameter!");
 
     local unit = frame.displayed;
     local width = frame.barwidth;
-    -- range check (doesn't have an event)
-    local inrange, checked = UnitInRange(unit);
-    if checked and not inrange then
-        frame:SetAlpha(0.55);
-    else
-        frame:SetAlpha(1);
+    -- range check (doesn't have an event) frames can be marked constantly visible
+    if not frame.constant then
+        local inrange, checked = UnitInRange(unit);
+        local inphase = UnitPhaseReason(unit);
+        if (checked and not inrange) or inphase then
+            frame:SetAlpha(0.55);
+        else
+            frame:SetAlpha(1);
+        end
     end
     -- states
     if UnitIsDeadOrGhost(unit) then
@@ -43,7 +64,6 @@ function addon.FrameUpdate(frame)
         if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
         if frame.healpred:IsShown() then frame.healpred:Hide() end
         if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
-        --if frame.auras:IsShown() then frame.auras:Hide() end
         frame.prev.health = nil;
         frame.prev.hmax = nil;
     elseif not UnitIsConnected(unit) then
@@ -54,18 +74,35 @@ function addon.FrameUpdate(frame)
         if frame.shieldhl:IsShown() then frame.shieldhl:Hide() end
         if frame.healpred:IsShown() then frame.healpred:Hide() end
         if frame.healabsorb:IsShown() then frame.healabsorb:Hide() end
-        --if frame.auras:IsShown() then frame.auras:Hide() end
         frame.prev.health = nil;
         frame.prev.hmax = nil;
     else
         if UnitIsAFK(unit) then
+            frame.text.status = true;
+            frame.prev.htext = nil;
             frame.text:SetText("afk");
             if not frame.text:IsShown() then frame.text:Show() end
         elseif UnitIsDND(unit) then
+            frame.text.status = true;
+            frame.prev.htext = nil;
             frame.text:SetText("dnd");
             if not frame.text:IsShown() then frame.text:Show() end
         else
-            if frame.text:IsShown() then frame.text:Hide() end
+            frame.text.status = false;
+            if frame.raid and frame.text:IsShown() then
+                frame.text:Hide();
+            end
+        end
+        if not frame.raid and frame.unit == "player" then
+            if InCombatLockdown() then
+                frame.status:SetTexCoord(0.5, 1, 0, 0.484375);
+                frame.status:Show();
+            elseif IsResting() then
+                frame.status:SetTexCoord(0, 0.5, 0, 0.421875);
+                frame.status:Show();
+            elseif frame.status:IsShown() then
+                frame.status:Hide();
+            end
         end
         -- health
         local current, hmax = UnitHealth(unit), UnitHealthMax(unit);
@@ -85,6 +122,32 @@ function addon.FrameUpdate(frame)
                 if not frame.health:IsShown() then frame.health:Show() end
             end
         end
+        -- health text
+        if not frame.raid and not frame.text.status and frame.prev.htext ~= current then
+            frame.prev.htext = current;
+            if frame.boss then
+                if hmax < current or hmax <= 1 then
+                    frame.text:SetText("100");
+                    if not frame.text:IsShown() then frame.text:Show() end
+                elseif current <= 0 then
+                    if frame.text:IsShown() then frame.text:Hide() end
+                else
+                    frame.text:SetFormattedText("%.1f", current/hmax*100);
+                    if not frame.text:IsShown() then frame.text:Show() end
+                end
+            else
+                if current > 1000000000 then -- 1.0B
+                    frame.text:SetFormattedText("%.2fB", current / 1000000000);
+                elseif current > 1000000 then -- 1.0M
+                    frame.text:SetFormattedText("%.2fM", current / 1000000);
+                elseif current > 1000 then -- 1.0K
+                    frame.text:SetFormattedText("%.1fK", current / 1000);
+                else
+                    frame.text:SetFormattedText("%i", current);
+                end
+                if not frame.text:IsShown() then frame.text:Show() end
+            end
+        end
         -- shield
         local hwidth = frame.health.width;
         current = UnitGetTotalAbsorbs(unit) or 0;
@@ -126,39 +189,145 @@ function addon.FrameUpdate(frame)
         elseif frame.healpred:IsShown() then
             frame.healpred:Hide();
         end
-        -- auras
-        if next(frame.alert) then
-            -- major
-            if frame.overlay.color ~= majorcolor then
-                frame.overlay:SetVertexColor(unpack(majorcolor));
-                frame.overlay.color = majorcolor;
-                if not frame.overlay:IsShown() then frame.overlay:Show() end
+        -- mana, if present
+        if frame.mana ~= nil then
+            local current, max = UnitPower(unit), UnitPowerMax(unit);
+            local ptype = UnitPowerType(unit);
+            if frame.mana.ptype ~= ptype then
+                frame.mana.ptype = ptype;
+                frame.mana:SetVertexColor(unpack(powerColors[ptype]));
             end
-        elseif next(frame.heal) then
-            -- major heals needed
-            if frame.overlay.color ~= healcolor then
-                frame.overlay:SetVertexColor(unpack(healcolor));
-                frame.overlay.color = healcolor;
-                if not frame.overlay:IsShown() then frame.overlay:Show() end
+            if frame.prev.mana ~= current or frame.prev.mmax ~= max then
+                frame.prev.mana = current;
+                frame.prev.mmax = max;
+                if max < 1 then
+                    if frame.mana:IsShown() then frame.mana:Hide() end
+                    if frame.manatext:IsShown() then frame.manatext:Hide() end
+                elseif max < current then
+                    frame.mana:SetWidth(width);
+                    frame.manatext:SetText("100");
+                    if not frame.mana:IsShown() then frame.mana:Show() end
+                    if not frame.manatext:IsShown() then frame.manatext:Show() end
+                elseif current <= 0 then
+                    if frame.mana:IsShown() then frame.mana:Hide() end
+                    if frame.manatext:IsShown() then frame.manatext:Hide() end
+                else
+                    local percent = current/max;
+                    frame.mana:SetWidth(percent*width);
+                    frame.manatext:SetText(format("%d", percent*100+0.5));
+                    if not frame.mana:IsShown() then frame.mana:Show() end
+                    if not frame.manatext:IsShown() then frame.manatext:Show() end
+                end
             end
-        elseif UnitIsCharmed(unit) and frame.unit == frame.displayed then
-            -- charmed
-            if frame.overlay.color ~= charmcolor then
-                frame.overlay:SetVertexColor(unpack(charmcolor));
-                frame.overlay.color = charmcolor;
-                if not frame.overlay:IsShown() then frame.overlay:Show() end
+        end
+        -- forced aura updates
+        if frame.rounds ~= nil then
+            frame.rounds = frame.rounds + 1;
+            if (frame.rounds > 7) then
+                frame.tankcd = {};
+                frame.alert = {};
+                frame.stacks = {};
+                frame.heal = {};
+                frame.buff1 = {};
+                frame.buff2 = {};
+                frame.stagger = {};
+                addon.SetAuras(frame.unit, frame.guid);
+                frame.rounds = 0;
             end
-        elseif UnitDebuff(unit, 1, "RAID") ~= nil then
-            -- dispellable
-            if frame.overlay.color ~= dispelcolor then
-                frame.overlay:SetVertexColor(unpack(dispelcolor));
-                frame.overlay.color = dispelcolor;
-                if not frame.overlay:IsShown() then frame.overlay:Show() end
+        end
+        if frame.raid then
+            -- tank CD marker
+            if next(frame.tankcd) then
+                if not frame.defensive:IsShown() then frame.defensive:Show() end
+            elseif frame.defensive:IsShown() then
+                frame.defensive:Hide();
             end
-        else
-            if frame.overlay.color ~= nil then
-                frame.overlay.color = nil;
-                if frame.overlay:IsShown() then frame.overlay:Hide() end
+            -- aura stacks
+            if next(frame.stacks) then
+                local _, amount = next(frame.stacks);
+                frame.stack:SetText(amount);
+                if not frame.stack:IsShown() then frame.stack:Show() end
+            elseif next(frame.hits) then
+                local _, amount = next(frame.hits);
+                frame.stack:SetText(amount);
+                if not frame.stack:IsShown() then frame.stack:Show() end
+            elseif frame.stack:IsShown() then
+                frame.stack:Hide();
+            end
+            -- custom buff indicator 1
+            if next(frame.buff1) then
+                if not frame.buffind1:IsShown() then frame.buffind1:Show() end
+            elseif frame.buffind1:IsShown() then
+                frame.buffind1:Hide();
+            end
+            -- custom buff indicator 2
+            if next(frame.buff2) then
+                if not frame.buffind2:IsShown() then frame.buffind2:Show() end
+            elseif frame.buffind2:IsShown() then
+                frame.buffind2:Hide();
+            end
+            -- incoming ability
+            if next(frame.incoming) then
+                if not frame.glow:IsShown() then frame.glow:Show() end
+            elseif frame.glow:IsShown() then
+                frame.glow:Hide();
+            end
+            -- DK Death Strike and Monk Stagger tracking
+            if frame.rolename == "TANK" then
+                if frame.classname == "DEATHKNIGHT" then
+                    local power = UnitPower(unit);
+                    if power < 45 then
+                        if not frame.bottomwarn:IsShown() then frame.bottomwarn:Show() end
+                    elseif frame.bottomwarn:IsShown() then
+                        frame.bottomwarn:Hide();
+                    end
+                elseif frame.classname == "MONK" then
+                    if next(frame.stagger) then -- Heavy Stagger
+                        if not frame.bottomwarn:IsShown() then frame.bottomwarn:Show() end
+                    elseif frame.bottomwarn:IsShown() then
+                        frame.bottomwarn:Hide();
+                    end
+                end
+            elseif frame.bottomwarn:IsShown() then
+                frame.bottomwarn:Hide();
+            end
+            -- overlays
+            if next(frame.alert) then
+                -- major
+                if frame.overlay.color ~= majorcolor then
+                    frame.overlay:SetVertexColor(unpack(majorcolor));
+                    frame.overlay.color = majorcolor;
+                    if not frame.overlay:IsShown() then frame.overlay:Show() end
+                end
+            else
+                local _, _, _, _, _, _, _, _, _, spellid = UnitDebuff(unit, 1, "RAID");
+                if UnitIsCharmed(unit) and frame.unit == frame.displayed then
+                    -- charmed
+                    if frame.overlay.color ~= charmcolor then
+                        frame.overlay:SetVertexColor(unpack(charmcolor));
+                        frame.overlay.color = charmcolor;
+                        if not frame.overlay:IsShown() then frame.overlay:Show() end
+                    end
+                elseif spellid ~= nil and not ignoredAuras[spellid] then
+                    -- dispellable
+                    if frame.overlay.color ~= dispelcolor then
+                        frame.overlay:SetVertexColor(unpack(dispelcolor));
+                        frame.overlay.color = dispelcolor;
+                        if not frame.overlay:IsShown() then frame.overlay:Show() end
+                    end
+                elseif next(frame.heal) then
+                    -- major heals needed
+                    if frame.overlay.color ~= healcolor then
+                        frame.overlay:SetVertexColor(unpack(healcolor));
+                        frame.overlay.color = healcolor;
+                        if not frame.overlay:IsShown() then frame.overlay:Show() end
+                    end
+                else
+                    if frame.overlay.color ~= nil then
+                        frame.overlay.color = nil;
+                        if frame.overlay:IsShown() then frame.overlay:Hide() end
+                    end
+                end
             end
         end
     end