---@alias Color {r: number, g: number, b: number} ---@class Colorer ---@field colors table ---@field breakpoints table aura_env.Colorer = { --- Make sure colors and breakpoints always have the same number of entries! VERY IMPORTANT! ---@type table colors = { { r = 0.62, g = 0.62, b = 0.62 }, -- Grey -- { r = 1, g = 1, b = 1 }, -- White { r = 0.12, g = 1, b = 0 }, -- Green { r = 0, g = 0.44, b = 0.87 }, -- Blue { r = 0.64, g = 0.21, b = 0.93 }, -- Purple { r = 1, g = 0.5, b = 0 }, -- Orange { r = 0.9, g = 0.8, b = 0.5 }, -- Light Gold { r = 0, g = 0.8, b = 1.0 }, -- Blizzard Blue }, breakpoints = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1000.0 }, ---@param value number ---@return Color, nil|string Interpolate = function(value) local color = { r = 0, g = 0, b = 0 } ---@type table> local bracket = { { 0, 0 }, { 1, 1 } } for i = 1, #aura_env.Colorer.breakpoints do if value < aura_env.Colorer.breakpoints[i] then bracket[2] = { i, aura_env.Colorer.breakpoints[i] } break end bracket[1] = { i, aura_env.Colorer.breakpoints[i] } end ---@type Color local startColor = aura_env.Colorer.colors[bracket[1][1]] ---@type Color local endColor = aura_env.Colorer.colors[bracket[2][1]] if startColor == nil or endColor == nil then return color, "Color not found" end local fraction = (value - bracket[1][2]) / (bracket[2][2] - bracket[1][2]) for k, v in pairs(startColor) do color[k] = aura_env.Colorer.lerp(v, endColor[k], fraction) end return color, nil end, ---@param a number ---@param b number ---@param t number ---@return number lerp = function(a, b, t) return a * (1 - t) + b * t end, } setmetatable(aura_env.Colorer, { __index = aura_env.Colorer }) ---@class ShieldBuffer ---@field records table ---@field recordsToKeep number ---@field pointer number aura_env.ShieldBuffer = { ---@param recordsToKeep number ---@return ShieldBuffer new = function(recordsToKeep) local self = setmetatable({}, { __index = aura_env.ShieldBuffer, }) self.recordsToKeep = recordsToKeep self.records = {} self.pointer = 1 for i = 1, recordsToKeep do self.records[i] = 0 end return self end, ---@param self ShieldBuffer ---@param shieldValue number ---@return nil Append = function(self, shieldValue) self.records[self.pointer] = shieldValue self.pointer = (self.pointer % self.recordsToKeep) + 1 end, ---@param self ShieldBuffer ---@return number GetMax = function(self) local max = 0 for _, value in pairs(self.records) do if value > max then max = value end end if max == nil then return 0 end return max end, ---@param self ShieldBuffer ---@return number GetCurrent = function(self) local val = self.records[(self.pointer + self.recordsToKeep - 2) % self.recordsToKeep + 1] if val == nil then return 0 end return val end, } ---@class Shield ---@field name string ---@field value number ---@field buffer ShieldBuffer aura_env.Shield = { ---@param name string ---@return Shield new = function(name) local self = setmetatable({}, { __index = aura_env.Shield, }) self.name = name self.value = 0 self.buffer = aura_env.ShieldBuffer.new(30) return self end, ---@param self Shield ---@return nil, nil|string Update = function(self) local shieldValue = select(17, UnitAura("player", self.name)) if shieldValue then self.value = shieldValue else self.value = 0 end self.buffer:Append(self.value) end, } ---@class ShieldManager aura_env.ShieldManager = { ---@return number GetMax = function() local value = 0 for _, shield in pairs(aura_env.Shields) do value = value + shield.buffer:GetMax() end return value end, ---@return number GetCurrent = function() local value = 0 for _, shield in pairs(aura_env.Shields) do value = value + shield.buffer:GetCurrent() end return value end, ---@return number current ---@return number max GetStats = function() local max = 0 local current = 0 for _, shield in pairs(aura_env.Shields) do max = max + shield.buffer:GetMax() current = current + shield.buffer:GetCurrent() end return current, max end, ---@return string current ---@return string max ---@return number current (raw) ---@return number max (raw) GetStatsNice = function() local current, max = aura_env.ShieldManager.GetStats() if max > 1e6 or current > 1e6 then return string.format("%.1fM", current / 1e6), string.format("%.1fM", max / 1e6), current, max end return string.format("%.0fk", current / 1000), string.format("%.0fk", max / 1000), current, max end, } ---@class Display ---@field current number ---@field max number ---@field currentRaw number ---@field maxRaw number ---@field ofHp string ---@field ofHpRaw number ---@field ofHpRawFraction number ---@field color Color aura_env.Display = { Update = function() local current, max, currentRaw, maxRaw = aura_env.ShieldManager.GetStatsNice() local hp = UnitHealthMax("player") aura_env.Display.current = current aura_env.Display.max = max aura_env.Display.currentRaw = currentRaw aura_env.Display.maxRaw = maxRaw aura_env.Display.ofHpRaw = currentRaw / hp * 100 aura_env.Display.ofHpRawFraction = aura_env.Display.ofHpRaw / 100 aura_env.Display.ofHp = string.format("%.0f%%", aura_env.Display.ofHpRaw) aura_env.Display.color = aura_env.Colorer.Interpolate(aura_env.Display.ofHpRawFraction) return nil end, } ---@type table aura_env.Shields = { [108366] = aura_env.Shield.new("Soul Leech"), [108416] = aura_env.Shield.new("Dark Pact"), [207472] = aura_env.Shield.new("Xavaric's Magnum Opus"), [252208] = aura_env.Shield.new("Refractive Shell"), }