diff --git a/src/frames.lua b/src/frames.lua index bf828e6..aea1f90 100644 --- a/src/frames.lua +++ b/src/frames.lua @@ -1,7 +1,7 @@ -- Copyright 2023 -- -- This file is part of Omicron Frames --- +-- -- Omicron Frames is free software: you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 3 of the License, or (at your option) @@ -13,19 +13,20 @@ -- more details. -- -- You should have received a copy of the GNU General Public License along with --- Omicron Frames. If not, see . +-- Omicron Frames. If not, see . local omif = select(2, ...) local colors = { - cyan = {0.0, 0.8, 0.8}, - white = {1.0, 1.0, 1.0}, - orange = {1.0, 0.5 , 0}, - violet = {1.0, 0, 1.0}, - magic = {0.4, 0.4, 1.0}, - disease = {0.4, 0.2, 0.0}, - poison = {0.0, 0.7, 0.7}, - curse = {0.7, 0.0, 0.7}, - red = {1, 0, 0}, + cyan = { 0.0, 0.8, 0.8 }, + white = { 1.0, 1.0, 1.0 }, + orange = { 1.0, 0.5, 0 }, + violet = { 1.0, 0, 1.0 }, + magic = { 0.4, 0.4, 1.0 }, + disease = { 0.4, 0.2, 0.0 }, + poison = { 0.0, 0.7, 0.7 }, + curse = { 0.7, 0.0, 0.7 }, + red = { 1, 0, 0 }, + blue = { .4, 0.4, 1 }, } local function RangeConfig() @@ -54,156 +55,230 @@ local function MouseConfig() if class == "SHAMAN" then return { -- No modifier - {button="mouse1", mods={}, kind="target"}, - {button="mouse2", mods={}, kind="macro", data="/use [@UNIT,dead,help]Ancestral Vision; [@UNIT,help]Chain Heal"}, - {button="mouse3", mods={}, kind="macro", data="/use [@UNIT,dead,help]Ancestral Spirit; [@UNIT,help]Purify Spirit"}, - {button="wheel-up", mods={}, kind="macro", data="/use [@UNIT,help]Healing Surge"}, - {button="wheel-down", mods={}, kind="macro", data="/use [@UNIT,help]Riptide"}, + { button = "mouse1", mods = {}, kind = "target" }, + { + button = "mouse2", + mods = {}, + kind = "macro", + data = + "/use [@UNIT,dead,help]Ancestral Vision; [@UNIT,help]Chain Heal" + }, + { + button = "mouse3", + mods = {}, + kind = "macro", + data = + "/use [@UNIT,dead,help]Ancestral Spirit; [@UNIT,help]Purify Spirit" + }, + { button = "wheel-up", mods = {}, kind = "macro", data = "/use [@UNIT,help]Healing Surge" }, + { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Riptide" }, -- alt - {button="wheel-up", mods={alt=true}, kind="spell", data="Healing Wave"}, - {button="wheel-down", mods={alt=true}, kind="spell", data="Earth Shield"}, + { button = "wheel-up", mods = { alt = true }, kind = "spell", data = "Healing Wave" }, + { button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Earth Shield" }, -- Shift - {button="mouse2", mods={shift=true}, kind="togglemenu"}, - {button="wheel-up", mods={shift=true}, kind="macro", data="/cast [@UNIT,help]Water Walking;\n/stopspelltarget"}, + { button = "mouse2", mods = { shift = true }, kind = "togglemenu" }, + { + button = "wheel-up", + mods = { shift = true }, + kind = "macro", + data = + "/cast [@UNIT,help]Water Walking;\n/stopspelltarget" + }, } elseif class == "PRIEST" then return { -- No modifier - {button="mouse1", mods={}, kind="target"}, - {button="mouse2", mods={}, kind="macro", data="/use [@UNIT,dead,help]Mass Resurrection; [@UNIT,help]Power Word: Radiance"}, - {button="mouse3", mods={}, kind="macro", data="/use [@UNIT,dead,help]Resurrection; [@UNIT,help]Purify"}, - {button="mouse4", mods={}, kind="spell", data="Shadow Covenant"}, - {button="wheel-up", mods={}, kind="macro", data="/use [@UNIT,help]Flash Heal"}, - {button="wheel-down", mods={}, kind="macro", data="/use [@UNIT,help]Renew"}, + { button = "mouse1", mods = {}, kind = "target" }, + { + button = "mouse2", + mods = {}, + kind = "macro", + data = "/use [@UNIT,dead,help]Mass Resurrection; [@UNIT,help]Power Word: Radiance" + }, + { + button = "mouse3", + mods = {}, + kind = "macro", + data = "/use [@UNIT,dead,help]Resurrection; [@UNIT,help]Purify" + }, + { button = "mouse4", mods = {}, kind = "spell", data = "Shadow Covenant" }, + { button = "wheel-up", mods = {}, kind = "macro", data = "/use [@UNIT,help]Flash Heal" }, + { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Renew" }, -- alt - {button="mouse1", mods={alt=true}, kind="spell", data="Power Word: Life"}, - {button="mouse2", mods={alt=true}, kind="spell", data="Pain Suppression"}, - {button="mouse3", mods={alt=true}, kind="spell", data="Power Infusion"}, - {button="wheel-up", mods={alt=true}, kind="spell", data="Rapture"}, - {button="wheel-down", mods={alt=true}, kind="spell", data="Power Word: Shield"}, + { button = "mouse1", mods = { alt = true }, kind = "spell", data = "Power Word: Life" }, + { button = "mouse2", mods = { alt = true }, kind = "spell", data = "Pain Suppression" }, + { button = "mouse3", mods = { alt = true }, kind = "spell", data = "Power Infusion" }, + { button = "wheel-up", mods = { alt = true }, kind = "spell", data = "Rapture" }, + { button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Power Word: Shield" }, -- Shift - {button="mouse2", mods={shift=true}, kind="togglemenu"}, - {button="wheel-up", mods={shift=true}, kind="macro", data="/cast [@UNIT,help]Levitate;\n/stopspelltarget"}, - {button="wheel-down", mods={shift=true}, kind="macro", data="/cast [@UNIT,help]Leap of Faith;\n/stopspelltarget"}, + { button = "mouse2", mods = { shift = true }, kind = "togglemenu" }, + { + button = "wheel-up", + mods = { shift = true }, + kind = "macro", + data = "/cast [@UNIT,help]Levitate;\n/stopspelltarget" + }, + { + button = "wheel-down", + mods = { shift = true }, + kind = "macro", + data = "/cast [@UNIT,help]Leap of Faith;\n/stopspelltarget" + }, } else return { -- Super basic defaults - {button="mouse1", mods={}, kind="target"}, - {button="mouse2", mods={shift=true}, kind="togglemenu"}, + { button = "mouse1", mods = {}, kind = "target" }, + { button = "mouse2", mods = { shift = true }, kind = "togglemenu" }, } end end -local function TriggerConfig() +local function TriggerClassConfig() local _, class = UnitClass("player") if class == "SHAMAN" then return { { - kind="AuraTrigger", spellId=383648, own=true, -- Second Earth Shield on yourself - indicator={ - kind="SquareIndicator", - size=17, - point="TOPLEFT", - x=3, y=-3, - color=colors.white, - showStacks=true, + kind = "AuraTrigger", + spellId = 383648, + own = true, -- Second Earth Shield on yourself + indicator = { + kind = "SquareIndicator", + size = 17, + point = "TOPLEFT", + x = 3, + y = -3, + color = colors.white, + showStacks = true, } }, { - kind="AuraTrigger", spellId=974, own=true, -- Second Earth Shield on yourself - indicator={ - kind="SquareIndicator", - size=17, - point="TOPLEFT", - x=3, y=-3, - color=colors.white, - showStacks=true, + kind = "AuraTrigger", + spellId = 974, + own = true, -- Second Earth Shield on yourself + indicator = { + kind = "SquareIndicator", + size = 17, + point = "TOPLEFT", + x = 3, + y = -3, + color = colors.white, + showStacks = true, } }, { - kind="AuraTrigger", spellId=61295, own=true, -- Riptide - indicator={ - kind="SquareIndicator", - size=17, - point="BOTTOMLEFT", - x=3, y=3, - color=colors.cyan, + kind = "AuraTrigger", + spellId = 61295, + own = true, -- Riptide + indicator = { + kind = "SquareIndicator", + size = 17, + point = "BOTTOMLEFT", + x = 3, + y = 3, + color = colors.cyan, + fadeTime = 10.0, } }, { - kind="StatusTrigger", status="Burn", invert=false, - indicator={ - kind="BorderIndicator", - thickness=3.0, - color=colors.red, - level=0, + kind = "StatusTrigger", + status = "Burn", + invert = false, + indicator = { + kind = "BorderIndicator", + thickness = 3.0, + color = colors.red, + level = 0, } }, } elseif class == "PRIEST" then return { { - kind="AuraTrigger", spellId=17, own=true, -- Power Word: Shield - indicator={ - kind="SquareIndicator", - size=17, - point="TOPLEFT", - x=3, y=-3, - color=colors.white, + kind = "AuraTrigger", + spellId = 17, + own = true, -- Power Word: Shield + indicator = { + kind = "SquareIndicator", + size = 17, + point = "TOPLEFT", + x = 3, + y = -3, + color = colors.white, + fadeTime = 10.0, } }, { - kind="AuraTrigger", spellId=33206, own=true, -- Pain Suppression - indicator={ - kind="SquareIndicator", - size=17, - point="TOPLEFT", - x=22, y=-3, - color=colors.orange, + kind = "AuraTrigger", + spellId = 33206, + own = true, -- Pain Suppression + indicator = { + kind = "SquareIndicator", + size = 17, + point = "TOPLEFT", + x = 22, + y = -3, + color = colors.orange, + fadeTime = 10.0, + flashTime = 1.3, } }, { - kind="AuraTrigger", spellId=139, own=true, -- Renew - indicator={ - kind="SquareIndicator", - size=17, - point="BOTTOMLEFT", - x=3, y=3, - color=colors.cyan, + kind = "AuraTrigger", + spellId = 139, + own = true, -- Renew + indicator = { + kind = "SquareIndicator", + size = 17, + point = "BOTTOMLEFT", + x = 3, + y = 3, + color = colors.cyan, + fadeTime = 10.0, } }, { - kind="AuraTrigger", spellId=194384, own=true, -- Atonement - indicator={ - kind="SquareIndicator", - size=17, - point="BOTTOMLEFT", - x=22, y=3, - color=colors.white, + kind = "AuraTrigger", + spellId = 194384, + own = true, -- Atonement + indicator = { + kind = "SquareIndicator", + size = 17, + point = "BOTTOMLEFT", + x = 22, + y = 3, + color = colors.white, + fadeTime = 10.0, + flashTime = 1.3, } }, { - kind="AuraTrigger", spellId=10060, own=true, -- Power Infusion - indicator={ - kind="SquareIndicator", - size=17, - point="BOTTOMLEFT", - x=41, y=3, - color=colors.violet, + kind = "AuraTrigger", + spellId = 10060, + own = true, -- Power Infusion + indicator = { + kind = "SquareIndicator", + size = 17, + point = "BOTTOMLEFT", + x = 41, + y = 3, + color = colors.violet, + fadeTime = 10.0, } }, { - kind="StatusTrigger", status="Burn", invert=false, - indicator={ - kind="BorderIndicator", - thickness=3.0, - color=colors.red, - level=0, + kind = "StatusTrigger", + status = "Burn", + invert = false, + indicator = { + kind = "BorderIndicator", + thickness = 3.0, + color = colors.red, + level = 0, } }, --[[{ @@ -227,6 +302,65 @@ local function TriggerConfig() end end +-- Quick helper function to create a config for debuff triggers +local function MakeDebuffTrigger(slot, spellid, color, stacks) + if stacks == nil then + stacks = false + end + return { + kind = "AuraTrigger", + spellId = spellid, + indicator = { + kind = "SquareIndicator", + size = 15, + point = "TOPRIGHT", + x = -17 * slot, + y = -3, + color = color, + showStacks = stacks, + } + } +end + +local function TriggerConfig() + local triggers = TriggerClassConfig() + + -- slot, spellid, color, stacks + local debuffs = { + -- Kezzara, Aberrus + { 1, 406525, colors.orange }, -- Dread Rift + { 2, 402253, colors.red }, -- Ray of Anguish + { 3, 404743, colors.violet, true }, -- Terror Claws + + -- Forgotten Experiment, Aberrus + { 1, 406365, colors.red, true }, -- Rending Charge (p1) + { 1, 407327, colors.cyan, true }, -- Unstable Essence (p2/p3) + { 3, 407313, colors.violet, true }, -- Infused Strikes + + -- Uldaman: Legacy of Tyr + { 1, 377510, colors.cyan, true }, -- Stolen Time + + -- Brackenhide Hollow + { 1, 367521, colors.cyan, true }, -- Bone Bolt + + -- The Underrot + --{1, 273226, colors.green, true}, -- Decaying Spores + + -- Sarkareth, Aberrus + { 3, 401330, colors.violet }, -- Burning Claws (P1 tank) + { 3, 411241, colors.violet }, -- Void Claws (P2 tank) + { 3, 408429, colors.violet }, -- Void Slash (P3 tank) + { 2, 404218, colors.blue }, -- Void Fracture (carry bomb) + { 1, 401951, colors.cyan, true }, -- Oblivion + } + + for _, debuff in ipairs(debuffs) do + table.insert(triggers, MakeDebuffTrigger(debuff[1], debuff[2], debuff[3], debuff[4])) + end + + return triggers +end + local types = omif.GetModule("types") local UnitFrame = types.UnitFrame local UnitGroup = types.UnitGroup @@ -254,9 +388,9 @@ function CreateRaidFrames(left, top, config) local width = config.size.width local height = config.size.height local group = UnitGroup:new(left, top, width, height) - for i=0,5 do - for j=0,4 do - local num = i*5 + j + 1 + for i = 0, 5 do + for j = 0, 4 do + local num = i * 5 + j + 1 local frame = UnitFrame:new("raid" .. num, config) group:AddUnitFrame(frame) end @@ -269,7 +403,7 @@ function CreatePartyFrames(left, top, config) local group = UnitGroup:new(left, top, width, height) local player = UnitFrame:new("player", config) group:AddUnitFrame(player) - for i=1,4 do + for i = 1, 4 do local frame = UnitFrame:new("party" .. i, config) group:AddUnitFrame(frame) end @@ -283,9 +417,9 @@ function CreateTargetFrames(left, top, config) focus:SetPosition(left, top) local target = UnitFrame:new("target", config) target:SetPosition(left, top - height) - for i=1,4 do + for i = 1, 4 do local boss = UnitFrame:new("boss" .. i, config) - boss:SetPosition(left, top-(i+1)*height) + boss:SetPosition(left, top - (i + 1) * height) end end @@ -304,7 +438,8 @@ function CreateFrames() CreatePartyFrames(-0.05, -290.05, config) config.hideInRaid = false CreateRaidFrames(-0.05, -290.05, config) - CreateTargetFrames(110*3+50 -0.05, -245.05, config) + CreateTargetFrames(110 * 3 + 50 - 0.05, -245.05, config) HideBlizzardFrames() end + omif.SetEventHandler("OMICRON_LOADING", CreateFrames) diff --git a/src/types/indicators/squareindicator.lua b/src/types/indicators/squareindicator.lua index 4d47e64..da06658 100644 --- a/src/types/indicators/squareindicator.lua +++ b/src/types/indicators/squareindicator.lua @@ -1,7 +1,7 @@ -- Copyright 2023 -- -- This file is part of Omicron Frames --- +-- -- Omicron Frames is free software: you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 3 of the License, or (at your option) @@ -13,7 +13,7 @@ -- more details. -- -- You should have received a copy of the GNU General Public License along with --- Omicron Frames. If not, see . +-- Omicron Frames. If not, see . local omi = select(2, ...) local types = omi.GetModule("types") @@ -45,7 +45,9 @@ end ---@param y number ---@param color number[] ---@param showStacks boolean -function SquareIndicator:Init(unitframe, size, point, x, y, color, showStacks) +---@param doFade nil|number +---@param doFlash nil|number +function SquareIndicator:Init(unitframe, size, point, x, y, color, showStacks, fadeTime, flashTime) self.unitframe = unitframe self.frameParent = unitframe.overlays self.size = size @@ -54,6 +56,8 @@ function SquareIndicator:Init(unitframe, size, point, x, y, color, showStacks) self.y = y self.color = color self.showStacks = showStacks + self.fadeTime = fadeTime + self.flashTime = flashTime end --- Set the color of the Square Indicator @@ -61,7 +65,7 @@ end function SquareIndicator:SetColor(color) self.color = color local frame = self.frame - if frame then + if frame then frame:SetBackdropColor(unpack(color)) end end @@ -77,6 +81,13 @@ function SquareIndicator:Show(data) stacks:SetText(numStacks) stacks:Show() end + if self.flashTime or self.fadeTime then + self.frame:SetScript("OnUpdate", function(frame, dt) + self:OnUpdate(dt) + end) + self.expirationTime = data.expirationTime + self.updateThrottle = 0 + end if data.color then self:SetColor(data.color) else @@ -93,7 +104,7 @@ function SquareIndicator:GetFrame() bgFile = "Interface\\Addons\\OmicronFrames\\media\\textures\\square_white", edgeFile = "Interface\\Addons\\OmicronFrames\\media\\textures\\pixel_edge", edgeSize = 2, - insets = {left=0, right=0, top=0, bottom=0}, + insets = { left = 0, right = 0, top = 0, bottom = 0 }, } frame:ApplyBackdrop() @@ -108,6 +119,7 @@ function SquareIndicator:GetFrame() frame:SetParent(self.frameParent) frame:SetPoint(self.point, self.x, self.y) frame:SetBackdropBorderColor(0, 0, 0, 1) + frame:SetAlpha(1) stacks = frame.stacks return frame, stacks end @@ -122,6 +134,30 @@ function SquareIndicator:Update(data) self.stacks:SetText(numStacks) self.stacks:Show() end + self.expirationTime = data.expirationTime + self.frame:SetAlpha(1) +end + +function SquareIndicator:OnUpdate(dt) + dt = self.updateThrottle + dt + if dt < 0.04 then + self.updateThrottle = dt + return + else + self.updateThrottle = 0 + end + + local timeLeft = self.expirationTime - GetTime() + local fadeTime = self.fadeTime or 0 + local flashTime = self.flashTime or 0 + + if timeLeft < flashTime then + local alpha = ((timeLeft * 4) % 1) + self.frame:SetAlpha(alpha) + elseif timeLeft < fadeTime then + local alpha = timeLeft / fadeTime + self.frame:SetAlpha(alpha) + end end --- Hide the square indicator. @@ -130,5 +166,6 @@ function SquareIndicator:Hide() self.stacks:Hide() self.frame = nil self.stacks = nil + frame:SetScript("OnUpdate", nil) squarePool:Release(frame) end diff --git a/src/types/triggers/auratrigger.lua b/src/types/triggers/auratrigger.lua index 79ba382..e5636c8 100644 --- a/src/types/triggers/auratrigger.lua +++ b/src/types/triggers/auratrigger.lua @@ -1,7 +1,7 @@ -- Copyright 2023 -- -- This file is part of Omicron Frames --- +-- -- Omicron Frames is free software: you can redistribute it and/or modify it -- under the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 3 of the License, or (at your option) @@ -13,7 +13,7 @@ -- more details. -- -- You should have received a copy of the GNU General Public License along with --- Omicron Frames. If not, see . +-- Omicron Frames. If not, see . local omi = select(2, ...) local types = omi.GetModule("types") ---@class Trigger @@ -92,7 +92,7 @@ function AuraTrigger:AddAura(aura) return end self.count = self.count + 1 - self:SetData({stacks=aura.applications}) + self:SetData({ stacks = aura.applications, duration = aura.duration, expirationTime = aura.expirationTime }) self:SetState(self.count >= self.requiredCount, false) end @@ -100,7 +100,7 @@ end ---@param before UnitAuraInfo ---@param after UnitAuraInfo function AuraTrigger:UpdateAura(before, after) - self:SetData({stacks=after.applications}) + self:SetData({ stacks = after.applications, duration = after.duration, expirationTime = after.expirationTime }) if self.active then self.indicator:Update(self.data) end diff --git a/src/types/unitframe.lua b/src/types/unitframe.lua index f71c201..9c388b6 100644 --- a/src/types/unitframe.lua +++ b/src/types/unitframe.lua @@ -125,7 +125,9 @@ function UnitFrame:CreateIndicator(indicator) indicator.x, indicator.y, indicator.color, - indicator.showStacks + indicator.showStacks, + indicator.fadeTime, + indicator.flashTime ) elseif kind == "BorderIndicator" then return BorderIndicator:new(