-- 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) -- any later version. -- -- Omicron Frames is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- 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 }, yellow = { 1.0, 1.0, 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 = { 0.4, 0.4, 1 }, light_blue = { 0.7, 0.7, 1 }, } ---@param list number[] ---@return table local function set(list) local s = {} for _, v in ipairs(list) do s[v] = true end return s end local AURAS_PRIEST_RENEW = set({ 139, 6074, 6075, 6076, 6077, 6078, 10927, 10928, 10929, 25315, 25221, 25222 }) local AURAS_PRIEST_PWS = set({ 17, 592, 600, 3747, 6065, 6066, 10898, 10899, 10900, 10901, 25217, 25218 }) local function RangeConfig() local _, class = UnitClass("player") if class == "SHAMAN" then return { friendly = "Healing Wave", enemy = "Lightning Bolt", fade = 0.2, } elseif class == "PRIEST" then return { friendly = "Heal", enemy = "Smite", fade = 0.2, } else return { fade = 0.2, } end end local function MouseConfig() local _, class = UnitClass("player") if class == "SHAMAN" then return { -- No modifier { button = "mouse1", mods = {}, kind = "target" }, { button = "mouse2", mods = {}, kind = "macro", data = "/use [@UNIT,dead,help]Ancestral Spirit; [@UNIT,help]Chain Heal", }, { button = "mouse3", mods = {}, kind = "macro", data = "/use [@UNIT,help]Cure Poison", }, { button = "wheel-up", mods = {}, kind = "macro", data = "/use [@UNIT,help]Lesser Healing Wave", }, { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Healing Wave", }, -- alt { button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Earth Shield" }, { button = "wheel-up", mods = { alt = true }, kind = "macro", data = "/use [@UNIT,help,nodead]Nature's Swiftness\n/use [@UNIT,help]Healing Wave", }, { button = "mouse3", mods = { alt = true }, kind = "macro", data = "/use [@UNIT,help]Cure Disease", }, -- 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 = "wheel-down", mods = { shift = true }, kind = "macro", data = "/use [@UNIT,help]Healing Wave(rank 1)", }, } 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]Lesser Heal", }, { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Heal" }, -- 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 = "Renew" }, { 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", }, } elseif class == "MONK" then return { -- No modifier { button = "mouse1", mods = {}, kind = "target" }, { button = "mouse2", mods = {}, kind = "macro", data = ( "/use [@UNIT,known:Reawaken,dead,help]Reawaken; " .. "[@UNIT,dead,help]Resuscitate; " .. "[@UNIT,help]Tiger's Lust" ), }, { button = "mouse3", mods = {}, kind = "macro", data = "/use [@UNIT,dead,help]Resuscitate; [@UNIT,help]Detox", }, { button = "mouse4", mods = {}, kind = "spell", data = "Shadow Covenant" }, { button = "wheel-up", mods = {}, kind = "macro", data = "/use [@UNIT,help]Vivify" }, { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help]Soothing Mist", }, -- 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" }, -- 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", }, } elseif class == "PALADIN" then return { -- No modifier { button = "mouse1", mods = {}, kind = "target" }, { button = "mouse2", mods = {}, kind = "macro", data = ( "/use [@UNIT,combat,dead,help]Intercession; " .. "[@UNIT,known:Absolution,dead,help]Absolution; " .. "[@UNIT,dead,help]Redemption; " .. "[@UNIT,help]Blessing of Freedom" ), }, { button = "mouse3", mods = {}, kind = "macro", data = "/use [@UNIT,dead,help]Redemption; [@UNIT,help]Cleanse Toxins", }, { button = "mouse4", mods = {}, kind = "spell", data = "Word of Glory", }, { button = "mouse5", mods = {}, kind = "spell", data = "Blessing of Summer", }, { button = "wheel-up", mods = {}, kind = "macro", data = "/use [@UNIT,help]Flash of Light", }, { button = "wheel-down", mods = {}, kind = "macro", data = "/use [@UNIT,help,known:Holy Shock]Holy Shock; [@UNIT,help]Word of Glory", }, -- Shift { button = "mouse2", mods = { shift = true }, kind = "togglemenu" }, -- alt { button = "mouse1", mods = { alt = true }, kind = "spell", data = "Blessing of Sacrifice" }, { button = "mouse2", mods = { alt = true }, kind = "spell", data = "Blessing of Protection" }, { button = "mouse3", mods = { alt = true }, kind = "spell", data = "Blessing of Spellwarding" }, { button = "wheel-up", mods = { alt = true }, kind = "spell", data = "Holy Light" }, { button = "wheel-down", mods = { alt = true }, kind = "spell", data = "Lay on Hands" }, } else return { -- Super basic defaults { button = "mouse1", mods = {}, kind = "target" }, { button = "mouse2", mods = { shift = true }, kind = "togglemenu" }, } end end local function TriggerClassConfig() local _, class = UnitClass("player") if class == "SHAMAN" then return { { kind = "AuraTrigger", spellIds = set({ 32594 }), 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", spellIds = set({ 29203 }), own = true, -- Healing Way indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 20, y = -3, color = colors.yellow, showStacks = true, }, }, { kind = "AuraTrigger", spellIds = set({ 16237 }), own = true, -- Ancestral Fortitude indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 40, y = -3, color = colors.orange, showStacks = false, }, }, { kind = "StatusTrigger", status = "Burn", invert = false, indicator = { kind = "BorderIndicator", thickness = 3.0, color = colors.red, level = 0, }, }, } elseif class == "PRIEST" then return { { kind = "AuraTrigger", spellIds = AURAS_PRIEST_PWS, own = true, -- Power Word: Shield indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 3, y = -3, color = colors.white, fadeTime = 10.0, }, }, { kind = "AuraTrigger", spellIds = set({ 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", spellIds = set({ 41635 }), own = true, -- Prayer of Mending indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 41, y = -3, color = { 0.7, 0.9, 1 }, showStacks = true, }, }, { kind = "AuraTrigger", spellIds = AURAS_PRIEST_RENEW, own = true, -- Renew indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMLEFT", x = 3, y = 3, color = colors.cyan, fadeTime = 10.0, }, }, { kind = "AuraTrigger", spellIds = set({ 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", spellIds = set({ 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, }, }, } elseif class == "PALADIN" then return { { kind = "AuraTrigger", spellIds = set({ 287280 }), -- Glimmer of Light own = true, indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 3, y = -3, color = colors.white, fadeTime = 10.0, flashTime = 1.3, }, }, { kind = "AuraTrigger", spellIds = set({ 25771 }), -- Forbearance indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 22, y = -3, color = colors.red, fadeTime = 10.0, flashTime = 1.3, }, }, { kind = "AuraTrigger", spellIds = set({ 53563 }), -- Beacon of Light own = true, indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 41, y = -3, color = colors.white, }, }, { kind = "AuraTrigger", spellIds = set({ 156910 }), -- Beacon of Faith own = true, indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 41, y = -3, color = colors.light_blue, }, }, { kind = "AuraTrigger", spellIds = set({ 200025 }), -- Beacon of Virtue own = true, indicator = { kind = "SquareIndicator", size = 17, point = "TOPLEFT", x = 41, y = -3, color = colors.white, }, }, { kind = "AuraTrigger", spellIds = set({ 1044 }), -- Blessing of Freedom own = true, indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMLEFT", x = 3, y = 3, color = colors.orange, flashTime = 1.3, }, }, { kind = "AuraTrigger", spellIds = set({ 1111 }), -- Blessing of Spellwarding own = true, indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMLEFT", x = 41, y = 3, color = colors.cyan, flashTime = 1.3, }, }, { kind = "AuraTrigger", spellIds = set({ 1022 }), -- Blessing of Protection own = true, indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMLEFT", x = 41, y = 3, color = colors.cyan, flashTime = 1.3, }, }, { kind = "AuraTrigger", spellIds = set({ 6940 }), -- Blessing of Saccrifice own = true, indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMLEFT", x = 61, y = 3, color = colors.red, flashTime = 1.3, }, }, { kind = "StatusTrigger", status = "Burn", invert = false, indicator = { kind = "BorderIndicator", thickness = 3.0, color = colors.red, level = 0, }, }, } else return { { kind = "StatusTrigger", status = "Burn", invert = false, indicator = { kind = "BorderIndicator", thickness = 3.0, color = colors.red, level = 0, }, }, } 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", spellIds = set({ spellid }), indicator = { kind = "SquareIndicator", size = 15, point = "TOPRIGHT", x = -17 * slot, y = -3, color = color, showStacks = stacks, }, } end local function TriggerConfig() local triggers = TriggerClassConfig() print("Class triggers:", #triggers) -- 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 -- Darkheart Thicket { 3, 225484, colors.violet }, -- Grievous Rip { 3, 196376, colors.violet }, -- Grievous Tear -- Throne of the Tides { 1, 426660, colors.red, true }, -- Razor Jaws -- Nymue, Amirdrassil { 1, 429785, colors.red }, -- Loom (line stun) { 1, 417807, colors.red, true }, -- Fyrakk -- Algeth'ar Academy { 1, 389033, colors.poison, true }, { 1, 388912, colors.red, true }, { 2, 391977, colors.cyan, true }, { 2, 389011, colors.cyan, true }, -- Nokhud Offensive { 1, 381692, colors.red, true }, -- Tazavesh { 1, 1240102, colors.orange, true }, -- Priory of the Sacred Flame { 1, 424414, colors.violet, true }, } for _, debuff in ipairs(debuffs) do table.insert(triggers, MakeDebuffTrigger(debuff[1], debuff[2], debuff[3], debuff[4])) end print("All triggers:", #triggers) -- Some more debuffs in the bottom row table.insert(triggers, { kind = "AuraTrigger", spellIds = set({ 240443 }), -- Bursting indicator = { kind = "SquareIndicator", size = 17, point = "BOTTOMRIGHT", x = -3, y = 3, color = colors.red, fadeTime = 3.0, showStacks = true, }, }) return triggers end local types = omif.GetModule("types") local UnitFrame = types.UnitFrame local UnitGroup = types.UnitGroup -- re-parent all blizzard frames and then hide the new parent function HideBlizzardFrames() local toggleFrame = CreateFrame("Frame", nil, UIParent) blizzardFrames = { PlayerFrame, TargetFrame, FocusFrame, PartyFrame, CompactRaidFrameContainer, } for _, frame in ipairs(blizzardFrames) do frame:SetParent(toggleFrame) end toggleFrame:Hide() end 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 local frame = UnitFrame:new("raid" .. num, config) group:AddUnitFrame(frame) local raidpet = UnitFrame:new("raidpet" .. num, config) group:AddUnitFrame(raidpet) end end end function CreatePartyFrames(left, top, config) local width = config.size.width local height = config.size.height local group = UnitGroup:new(left, top, width, height) local player = UnitFrame:new("player", config) group:AddUnitFrame(player) local pet = UnitFrame:new("pet", config) group:AddUnitFrame(pet) for i = 1, 4 do local frame = UnitFrame:new("party" .. i, config) group:AddUnitFrame(frame) local partypet = UnitFrame:new("partypet" .. i, config) group:AddUnitFrame(partypet) end group:Sort() end function CreateTargetFrames(left, top, config) local width = config.size.width local height = config.size.height local focus = UnitFrame:new("focus", config) focus:SetPosition(left, top) local target = UnitFrame:new("target", config) target:SetPosition(left, top - height) for i = 1, 4 do local boss = UnitFrame:new("boss" .. i, config) boss:SetPosition(left, top - (i + 1) * height) end end function CreateFrames() local config = { size = { width = 111, height = 45, }, range = RangeConfig(), mouse = MouseConfig(), hideInRaid = true, triggers = TriggerConfig(), } CreatePartyFrames(-0.05, -240.05, config) config.hideInRaid = false CreateRaidFrames(-0.05, -240.05, config) CreateTargetFrames(110 * 3 + 50 - 0.05, -240.05, config) HideBlizzardFrames() end omif.SetEventHandler("OMICRON_LOADING", CreateFrames)