Compare commits
	
		
			10 Commits
		
	
	
		
			3a1cc35a1e
			...
			ff9d8b2289
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ff9d8b2289 | |||
| 24c571658c | |||
| e20887d46b | |||
| 877560cb58 | |||
| b201ef789a | |||
| 30d8248832 | |||
| 5668a5b4db | |||
| 263b3f1330 | |||
| 45129a8635 | |||
| 1f95899781 | 
							
								
								
									
										452
									
								
								src/frames.lua
									
									
									
									
									
								
							
							
						
						
									
										452
									
								
								src/frames.lua
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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,14 +13,21 @@ | ||||
| -- more details. | ||||
| -- | ||||
| -- You should have received a copy of the GNU General Public License along with | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| 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}, | ||||
|     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 }, | ||||
|     light_blue = { .7, .7, 1 }, | ||||
| } | ||||
|  | ||||
| local function RangeConfig() | ||||
| @@ -49,142 +56,370 @@ 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 = "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="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" | ||||
|             }, | ||||
|         } | ||||
|     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" | ||||
|             }, | ||||
|         } | ||||
|     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=14, | ||||
|                     point="TOPLEFT", | ||||
|                     x=2, y=-2, | ||||
|                     color=colors.white, | ||||
|                 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=14, | ||||
|                     point="TOPLEFT", | ||||
|                     x=2, y=-2, | ||||
|                     color=colors.white, | ||||
|                 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=14, | ||||
|                     point="BOTTOMLEFT", | ||||
|                     x=2, y=2, | ||||
|                     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, | ||||
|                 } | ||||
|             }, | ||||
|         } | ||||
|     elseif class == "PRIEST" then | ||||
|         return { | ||||
|             { | ||||
|                 kind="AuraTrigger", spellId=17, own=true, -- Power Word: Shield | ||||
|                 indicator={ | ||||
|                 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, | ||||
|                     fadeTime = 10.0, | ||||
|                     flashTime = 1.3, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind = "AuraTrigger", | ||||
|                 spellId = 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", | ||||
|                 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, | ||||
|                     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, | ||||
|                     fadeTime = 10.0, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind = "StatusTrigger", | ||||
|                 status = "Burn", | ||||
|                 invert = false, | ||||
|                 indicator = { | ||||
|                     kind = "BorderIndicator", | ||||
|                     thickness = 3.0, | ||||
|                     color = colors.red, | ||||
|                     level = 0, | ||||
|                 } | ||||
|             }, | ||||
|             --[[{ | ||||
|                 kind="MultiTrigger", invert=false, | ||||
|                 children = { | ||||
|                     {kind="StatusTrigger", status="Immune", defaultData={color=colors.violet}}, -- Renew | ||||
|                     {kind="AuraTrigger", spellId=139, own=true, defaultData={color=colors.cyan}}, -- Renew | ||||
|                     {kind="AuraTrigger", spellId=21562, own=true, defaultData={color=colors.white}}, -- pw:f | ||||
|                 }, | ||||
|                 indicator = { | ||||
|                     kind="SquareIndicator", | ||||
|                     size=14, | ||||
|                     point="TOPLEFT", | ||||
|                     x=2, y=-2, | ||||
|                     size=17, | ||||
|                     point="TOPRIGHT", | ||||
|                     x=-3, y=-3, | ||||
|                     color=colors.white, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind="AuraTrigger", spellId=33206, own=true, -- Pain Suppression | ||||
|                 indicator={ | ||||
|                     kind="SquareIndicator", | ||||
|                     size=14, | ||||
|                     point="TOPLEFT", | ||||
|                     x=18, y=-2, | ||||
|                     color=colors.orange, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind="AuraTrigger", spellId=139, own=true, -- Renew | ||||
|                 indicator={ | ||||
|                     kind="SquareIndicator", | ||||
|                     size=14, | ||||
|                     point="BOTTOMLEFT", | ||||
|                     x=2, y=2, | ||||
|                     color=colors.cyan, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind="AuraTrigger", spellId=194384, own=true, -- Renew | ||||
|                 indicator={ | ||||
|                     kind="SquareIndicator", | ||||
|                     size=14, | ||||
|                     point="BOTTOMLEFT", | ||||
|                     x=18, y=2, | ||||
|                     color=colors.white, | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 kind="AuraTrigger", spellId=10060, own=true, -- Renew | ||||
|                 indicator={ | ||||
|                     kind="SquareIndicator", | ||||
|                     size=14, | ||||
|                     point="BOTTOMLEFT", | ||||
|                     x=34, y=2, | ||||
|                     color=colors.violet, | ||||
|                 } | ||||
|             }, | ||||
|             }--]] | ||||
|         } | ||||
|     else | ||||
|         return {} | ||||
|     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 | ||||
| @@ -212,9 +447,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 | ||||
| @@ -227,7 +462,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 | ||||
| @@ -241,16 +476,16 @@ 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 | ||||
|  | ||||
| function CreateFrames() | ||||
|     config = { | ||||
|     local config = { | ||||
|         size = { | ||||
|             width = 110, | ||||
|             width = 111, | ||||
|             height = 45, | ||||
|         }, | ||||
|         range = RangeConfig(), | ||||
| @@ -259,10 +494,11 @@ function CreateFrames() | ||||
|         triggers = TriggerConfig(), | ||||
|     } | ||||
|  | ||||
|     CreatePartyFrames(0, -290, config) | ||||
|     CreatePartyFrames(-0.05, -290.05, config) | ||||
|     config.hideInRaid = false | ||||
|     CreateRaidFrames(0, -290, config) | ||||
|     CreateTargetFrames(110*3+50, -245, config) | ||||
|     CreateRaidFrames(-0.05, -290.05, config) | ||||
|     CreateTargetFrames(110 * 3 + 50 - 0.05, -245.05, config) | ||||
|     HideBlizzardFrames() | ||||
| end | ||||
|  | ||||
| omif.SetEventHandler("OMICRON_LOADING", CreateFrames) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omif = select(2, ...) | ||||
|  | ||||
| -- Run all functions that start with Setup | ||||
|   | ||||
							
								
								
									
										10
									
								
								src/main.lua
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.lua
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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,13 +13,13 @@ | ||||
| -- more details. | ||||
| -- | ||||
| -- You should have received a copy of the GNU General Public License along with | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local AddonName, omif = ... | ||||
| omif.events = {} -- event (str) to list of handlers | ||||
| omif.db = nil | ||||
|  | ||||
| OmicronFrames = {} | ||||
| omif.modules = {public=OmicronFrames} | ||||
| omif.modules = { public = OmicronFrames } | ||||
| -- Simple function that creates or returns a local module table | ||||
| function omif.GetModule(name) | ||||
|     if omif.modules[name] == nil then | ||||
| @@ -29,7 +29,7 @@ function omif.GetModule(name) | ||||
| end | ||||
|  | ||||
| -- Adds a given function to the event handler list for a given event | ||||
| -- This will later in the addon  | ||||
| -- This will later in the addon | ||||
| function omif.SetEventHandler(event, fn) | ||||
|     if omif.events[event] == nil then | ||||
|         omif.events[event] = {} | ||||
| @@ -66,6 +66,7 @@ function omif.OnAddonLoaded(name) | ||||
|     omif.MainEventHandler(nil, "OMICRON_LOADING") | ||||
|     print("Loaded", AddonName) | ||||
| end | ||||
|  | ||||
| omif.SetEventHandler("ADDON_LOADED", omif.OnAddonLoaded) | ||||
|  | ||||
| -- Fire custom event OMICRON_FULLY_LOADED. This event is fired when the player | ||||
| @@ -75,6 +76,7 @@ function omif.FireFullyLoadedEvent(initialLogin, reloadUI) | ||||
|         omif.MainEventHandler(nil, "OMICRON_FULLY_LOADED") | ||||
|     end | ||||
| end | ||||
|  | ||||
| omif.SetEventHandler("PLAYER_ENTERING_WORLD", omif.FireFullyLoadedEvent) | ||||
|  | ||||
| function omif.SlashCommand(args) | ||||
|   | ||||
							
								
								
									
										133
									
								
								src/profiler.lua
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								src/profiler.lua
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local addonName, omi = ... | ||||
|  | ||||
| -- Profiler is only active if the optional Commander dependency is included | ||||
| @@ -26,56 +26,115 @@ local Printf = Commander.Printf | ||||
|  | ||||
| local types = omi.GetModule("types") | ||||
| local data = {} | ||||
| local startTime | ||||
| local stopTime | ||||
| local functionTimers = {} | ||||
| local functionNames = {} | ||||
|  | ||||
| -- Permanently wrap all functions to do profiling | ||||
| local function EnableFunctionProfiler() | ||||
|     if #functionTimers ~= 0 then | ||||
|         return | ||||
|     end | ||||
|     local GetTimePreciseSec = GetTimePreciseSec | ||||
|     local counter = 1 | ||||
|     for typeName, T in pairs(types) do | ||||
|         if type(T) == "table" then | ||||
|             PrintLn("Type:", typeName, T) | ||||
|             for fnName, fn in pairs(T) do | ||||
|                 if type(fn) == "function" then | ||||
|                     local fnIdx = counter | ||||
|                     counter = counter + 1 | ||||
|                     local name = string.format("%s:%s", typeName, fnName) | ||||
|                     functionTimers[fnIdx] = 0 | ||||
|                     functionNames[fnIdx] = name | ||||
|                     local wrapped = function(...) | ||||
|                         local start = GetTimePreciseSec() | ||||
|                         local a, b, c, d, e, f, g, h = fn(...) | ||||
|                         local elapsed = GetTimePreciseSec() - start | ||||
|                         functionTimers[fnIdx] = functionTimers[fnIdx] + elapsed | ||||
|                         return a, b, c, d, e, f, g, h | ||||
|                     end | ||||
|                     T[fnName] = wrapped | ||||
|                 end | ||||
|             end | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| -- Set all function timers back to 0 | ||||
| local function ResetFunctionProfiler() | ||||
|     for i, _ in ipairs(functionTimers) do | ||||
|         functionTimers[i] = 0 | ||||
|     end | ||||
| end | ||||
|  | ||||
| Commander.RegisterCommand("omi-pstart", { | ||||
|     description="Start/reset the OmicronFrames profiler", | ||||
|     command=function() | ||||
|     description = "Start/reset the OmicronFrames profiler", | ||||
|     command = function() | ||||
|         local profiler = C_CVar.GetCVar("scriptProfile") | ||||
|         if profiler ~= "1" then | ||||
|             PrintLn("scriptProfiler is off") | ||||
|             PrintLn("set it to on with `/console scriptProfile 1`, then reload the UI.") | ||||
|         PrintLn("OmicronFrames: start profiling") | ||||
|         EnableFunctionProfiler() | ||||
|         ResetFunctionProfiler() | ||||
|         startTime = GetTimePreciseSec() | ||||
|         stopTime = nil | ||||
|         if profiler == "1" then | ||||
|             ResetCPUUsage() | ||||
|         else | ||||
|             PrintLn("WoW scriptProfiler is off. Addon totals will not be shown,") | ||||
|             PrintLn("only individual functions.The profiler will not show total") | ||||
|             PrintLn("addon time, only function profiler.") | ||||
|             PrintLn("") | ||||
|             PrintLn("To enable the script profiler run `/console scriptProfile 1`, then reload the UI.") | ||||
|             return | ||||
|         end | ||||
|         PrintLn("OmicronFrames: start profiling") | ||||
|         ResetCPUUsage() | ||||
|     end | ||||
| }) | ||||
|  | ||||
| Commander.RegisterCommand("omi-pstop", { | ||||
|     description="Stop the OmicronFrames profiler", | ||||
|     command=function() | ||||
|         PrintLn("OmicronFrames: stop profiling") | ||||
|         UpdateAddOnCPUUsage() | ||||
|         local total = GetAddOnCPUUsage(addonName) | ||||
|         data = {{ | ||||
|             name = "Total OmicronFrames time", | ||||
|             time = total, | ||||
|             pct = 1.0 | ||||
|         }} | ||||
|  | ||||
|         for typeName, T in pairs(types) do | ||||
|             if type(T) == "table" then | ||||
|                 for fnName, fn in pairs(T) do | ||||
|                     if type(fn) == "function" then | ||||
|                         local time = GetFunctionCPUUsage(fn, true) | ||||
|                         table.insert(data, { | ||||
|                             name = string.format("%s:%s", typeName, fnName), | ||||
|                             time = time, | ||||
|                             pct = time/total | ||||
|                         }) | ||||
|                     end | ||||
|                 end | ||||
|             end | ||||
|     description = "Stop the OmicronFrames profiler", | ||||
|     command = function() | ||||
|         if not startTime then | ||||
|             PrintLn("Profiling not started. Run omi-pstart first.") | ||||
|             return | ||||
|         end | ||||
|         table.sort(data, function(a, b) return a.time > b.time end) | ||||
|         PrintLn("OmicronFrames: stop profiling") | ||||
|         local profiler = C_CVar.GetCVar("scriptProfile") == "1" | ||||
|         data = {} | ||||
|         stopTime = GetTimePreciseSec() | ||||
|         if profiler then | ||||
|             UpdateAddOnCPUUsage() | ||||
|             local total = GetAddOnCPUUsage(addonName) | ||||
|             table.insert(data, { | ||||
|                 name = "Total OmicronFrames time", | ||||
|                 time = total, | ||||
|             }) | ||||
|         end | ||||
|         for i, time in ipairs(functionTimers) do | ||||
|             local name = functionNames[i] | ||||
|             table.insert(data, { | ||||
|                 name = name, | ||||
|                 time = time * 1000, | ||||
|             }) | ||||
|         end | ||||
|         table.sort(data, function(a, b) return a.time < b.time end) | ||||
|     end, | ||||
| }) | ||||
|  | ||||
| Commander.RegisterCommand("omi-pprint", { | ||||
|     description="Print the collected OmicronFrames profiling data", | ||||
|     command=function() | ||||
|     description = "Print the collected OmicronFrames profiling data", | ||||
|     command = function() | ||||
|         if not stopTime then | ||||
|             PrintLn("Profiling data not collected yet. Run omi-pstop first.") | ||||
|             return | ||||
|         end | ||||
|         local top = data[#data].time | ||||
|         local total = stopTime - startTime | ||||
|         for _, item in ipairs(data) do | ||||
|             Printf("% 5.1f%%   % 5fms %s\n", item.pct*100, item.time, item.name) | ||||
|             local time = item.time | ||||
|             local pct = time / top * 100 | ||||
|             local ms_per_sec = time / total | ||||
|             Printf("% 6.1f%%   % 7.2fms   %7.2fms/s %s\n", pct, time, ms_per_sec, item.name) | ||||
|         end | ||||
|     end | ||||
| }) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
|  | ||||
| @@ -24,19 +24,87 @@ types.AuraList = AuraList | ||||
|  | ||||
| local statusLists = { | ||||
|     Immune = { | ||||
|         [642] = true,       -- Divine Shield, Paladin | ||||
|         [186265] = true     -- Aspect of the Turtle, Hunter | ||||
|         [642] = true,    -- Divine Shield, Paladin | ||||
|         [186265] = true, -- Aspect of the Turtle, Hunter | ||||
|         [45438] = true,  -- Ice Block | ||||
|         [31224] = true,  -- Cloak of Shadows | ||||
|         [196555] = true, -- Netherwalk | ||||
|     }, | ||||
|     Bomb = { | ||||
|         [642] = true,       -- Divine Shield, Paladin | ||||
|         [186265] = true,    -- Aspect of the Turtle, Hunter | ||||
|         [381615] = true,    -- Raszageth, Static Charge | ||||
|         [377467] = true     -- Raszageth, Fulminating Charge | ||||
|         [381615] = true, -- Raszageth, Static Charge | ||||
|         [377467] = true, -- Raszageth, Fulminating Charge | ||||
|         [399713] = true, -- Raszageth, Magnetic Charge | ||||
|         [397797] = true, -- Corrupted Vortex, Jade Serpent Temple | ||||
|         [387843] = true, -- Astral Bomb, Algeth'ar Academy | ||||
|         [386181] = true, -- Mana Bomb, Algeth'ar Academy | ||||
|         [401330] = true, -- Sarkareth, Burning Claws (p1 tank) | ||||
|         [411241] = true, -- Sarkareth, Void Claws (p2 tank) | ||||
|         [408429] = true, -- Sarkareth, Void Slash (p3 tank) | ||||
|         [404218] = true, -- Sarkareth, Void fracture (bombs) | ||||
|     }, | ||||
|     Burn = { | ||||
|         [642] = true,       -- Divine Shield, Paladin | ||||
|         [186265] = true     -- Aspect of the Turtle, Hunter | ||||
|     } | ||||
|         -- Jade Serpent Temple | ||||
|         [114803] = true, -- Throw Torch | ||||
|         [397914] = true, -- Defiling Mist | ||||
|         [106114] = true, -- Touch of Nothingness | ||||
|  | ||||
|         -- Shadow moon Burial Ground | ||||
|         [152819] = true, -- Shadow Word: Frailty | ||||
|         [153524] = true, -- Plague Spit | ||||
|  | ||||
|         -- Court of Stars | ||||
|         [397907] = true, -- Impending Doom | ||||
|         [209516] = true, -- Mana Fang | ||||
|         [207980] = true, -- Disintegration Beam | ||||
|         [211464] = true, -- Fel Detonation | ||||
|  | ||||
|         -- Algeth'ar Academy | ||||
|         [376997] = true, -- Savage Peck, Algeth'ar Academy | ||||
|         [388912] = true, -- Severing Slash, Algeth'ar Academy | ||||
|         [388866] = true, -- Mana Void, Algeth'ar Academy | ||||
|  | ||||
|         -- Vault of the Incarnates | ||||
|         [390911] = true, -- Raszageth, Lingering Charge | ||||
|  | ||||
|         -- Atal'Dazar | ||||
|         [255582] = true, -- Priestess Alun'za, Molten Gold | ||||
|  | ||||
|         -- The MOTHERLODE!! | ||||
|         [259853] = true, -- Rixxa Fluxflame, Chemical Burn | ||||
|  | ||||
|         -- Halls of Infusion | ||||
|  | ||||
|         -- Uldaman: Legacy of Tyr | ||||
|         [372718] = true, -- Earthen Shards | ||||
|  | ||||
|         -- Brackenhide Hollow | ||||
|         [367521] = true, -- Bone Bolt | ||||
|         [367484] = true, -- Vicious Clawmangle | ||||
|         [378020] = true, -- Gash Frenzy | ||||
|         [385058] = true, -- Withering Poison | ||||
|         [384575] = true, -- Crippling Bite | ||||
|  | ||||
|         -- Neltharus | ||||
|         [373735] = true, -- Dragon Strike | ||||
|         [372224] = true, -- Draogonbone Axe | ||||
|         [377018] = true, -- Molten Gold | ||||
|         [372570] = true, -- Bold Ambush | ||||
|  | ||||
|         -- Neltharion's Lair | ||||
|         -- Freehold | ||||
|         [413131] = true, -- Whirling Dagger | ||||
|  | ||||
|         -- The Underrot | ||||
|         [265019] = true, -- Savage Cleave | ||||
|         [265568] = true, -- Dark Omen | ||||
|         [273226] = true, -- Decaying Spores | ||||
|  | ||||
|         -- Vortex Pinnacle | ||||
|  | ||||
|         -- Aberrus | ||||
|         [404010] = true, -- Zkarn, ??? | ||||
|         [405462] = true, -- Zkarn, ??? | ||||
|     }, | ||||
| } | ||||
|  | ||||
| -- helper function that goes over several aura slots for a unit. Runs a | ||||
| @@ -44,7 +112,7 @@ local statusLists = { | ||||
| local function ForEachAuraSlots(unit, fn, continuationToken, ...) | ||||
|     local GetAuraDataBySlot = C_UnitAuras.GetAuraDataBySlot | ||||
|     local n = select('#', ...) | ||||
|     for i=1, n do | ||||
|     for i = 1, n do | ||||
|         local slot = select(i, ...) | ||||
|         fn(GetAuraDataBySlot(unit, slot)) | ||||
|     end | ||||
| @@ -213,8 +281,15 @@ function AuraList:RemoveAura(iid) | ||||
|     return statusChanged | ||||
| end | ||||
|  | ||||
| -- FIXME: param wrong | ||||
| ---@param info UnitAuraInfo | ||||
| function AuraList:Update(info) | ||||
|     if info.isFullUpdate then | ||||
|         self:Reset() | ||||
|         -- FIXME: return value might not reflect truth but true is the more prudent choice | ||||
|         return true | ||||
|     end | ||||
|  | ||||
|     local GetAuraDataByAuraInstanceID = C_UnitAuras.GetAuraDataByAuraInstanceID | ||||
|     local statusChanged = false | ||||
|     for _, aura in ipairs(info.addedAuras or {}) do | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
|  | ||||
| @@ -70,17 +70,26 @@ end | ||||
| --- Show the square indicator. | ||||
| ---@param data table | ||||
| function BorderIndicator:Show(data) | ||||
|     if data.color then | ||||
|         self.color = data.color | ||||
|     end | ||||
|     local frame, stacks = self:GetFrame() | ||||
|     frame:Show() | ||||
| end | ||||
|  | ||||
| function BorderIndicator:Update(data) | ||||
|     if data.color then | ||||
|         self:SetColor(data.color) | ||||
|     end | ||||
| end | ||||
|  | ||||
| function BorderIndicator:GetFrame() | ||||
|     local frame, new = borderPool:Acquire() | ||||
|     if new then | ||||
|         frame.backdropInfo = { | ||||
|             edgeFile = "Interface\\Addons\\OmicronFrames\\media\\textures\\pixel_edge", | ||||
|             edgeSize = 1, | ||||
|             insets = {left=0, right=0, top=0, bottom=0}, | ||||
|             insets = { left = 0, right = 0, top = 0, bottom = 0 }, | ||||
|         } | ||||
|     end | ||||
|  | ||||
| @@ -99,4 +108,3 @@ function BorderIndicator:Hide() | ||||
|     self.frame = nil | ||||
|     borderPool:Release(frame) | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
| local AuraTrigger = types.AuraTrigger | ||||
| @@ -36,4 +36,3 @@ end | ||||
| --- Hide the indicator | ||||
| function Indicator:Hide() | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| 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,7 +81,18 @@ function SquareIndicator:Show(data) | ||||
|         stacks:SetText(numStacks) | ||||
|         stacks:Show() | ||||
|     end | ||||
|     frame:SetBackdropColor(unpack(self.color)) | ||||
|     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 | ||||
|         frame:SetBackdropColor(unpack(self.color)) | ||||
|     end | ||||
|     frame:Show() | ||||
| end | ||||
|  | ||||
| @@ -89,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() | ||||
|  | ||||
| @@ -104,17 +119,45 @@ 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 | ||||
|  | ||||
| ---@param data table | ||||
| function SquareIndicator:Update(data) | ||||
|     if data.color then | ||||
|         self:SetColor(data.color) | ||||
|     end | ||||
|     local numStacks = data.stacks or 0 | ||||
|     if numStacks > 0 then | ||||
|         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. | ||||
| @@ -123,5 +166,6 @@ function SquareIndicator:Hide() | ||||
|     self.stacks:Hide() | ||||
|     self.frame = nil | ||||
|     self.stacks = nil | ||||
|     frame:SetScript("OnUpdate", nil) | ||||
|     squarePool:Release(frame) | ||||
| end | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
|  | ||||
| ---@class Object | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
|  | ||||
| @@ -30,7 +30,7 @@ function StatusBar:Init(parent, width, height, level, top) | ||||
|     local bar = CreateFrame("StatusBar", nil, parentFrame) | ||||
|     bar:SetFrameStrata("MEDIUM") | ||||
|     bar:SetFrameLevel(level) | ||||
|      | ||||
|  | ||||
|     if top then | ||||
|         bar:SetPoint("TOPLEFT", parentFrame, "TOPLEFT", 0, 0) | ||||
|     else | ||||
| @@ -42,12 +42,12 @@ function StatusBar:Init(parent, width, height, level, top) | ||||
|     bar:GetStatusBarTexture():SetHorizTile(false) | ||||
|     bar:GetStatusBarTexture():SetVertTile(false) | ||||
|     self.bar = bar | ||||
|      | ||||
|  | ||||
|     local bg = bar:CreateTexture(nil, "BACKGROUND") | ||||
|     bg:SetTexture("Interface\\Addons\\OmicronFrames\\media\\textures\\bar_subtle_diagonal") | ||||
|     bg:SetAllPoints(true) | ||||
|     self.bg = bg | ||||
|      | ||||
|  | ||||
|     self:SetRange(0, 1) | ||||
|     self:SetValue(1) | ||||
|     bar:Show() | ||||
| @@ -70,13 +70,13 @@ function StatusBar:Hide() | ||||
| end | ||||
|  | ||||
| function StatusBar:SetInterpolatedColor(start, stop, progress) | ||||
|     local r = start[1] + (stop[1] - start[1])*progress | ||||
|     local g = start[2] + (stop[2] - start[2])*progress | ||||
|     local b = start[3] + (stop[3] - start[3])*progress | ||||
|     local r = start[1] + (stop[1] - start[1]) * progress | ||||
|     local g = start[2] + (stop[2] - start[2]) * progress | ||||
|     local b = start[3] + (stop[3] - start[3]) * progress | ||||
|     self:SetColor(r, g, b) | ||||
| end | ||||
|  | ||||
| function StatusBar:SetColor(r, g, b) | ||||
|     self.bar:SetStatusBarColor(r, g, b) | ||||
|     self.bg:SetVertexColor(0.2*r, 0.2*g, 0.2*b) | ||||
|     self.bg:SetVertexColor(0.2 * r, 0.2 * g, 0.2 * b) | ||||
| end | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
| ---@class Trigger | ||||
| @@ -38,7 +38,8 @@ function AuraTrigger.CreateFromConfig(unit, config) | ||||
|         config.spellId, | ||||
|         config.own, | ||||
|         config.requiredCount, | ||||
|         config.invert | ||||
|         config.invert, | ||||
|         config.defaultData | ||||
|     ) | ||||
|     unit.auras:AddTrigger(trigger) | ||||
|     return trigger | ||||
| @@ -57,8 +58,9 @@ end | ||||
| ---@param own boolean | ||||
| ---@param requiredCount number | nil | ||||
| ---@param invert boolean | nil | ||||
| function AuraTrigger:Init(spellId, own, requiredCount, invert) | ||||
|     Trigger.Init(self, invert) | ||||
| ---@param defaultData table | nil | ||||
| function AuraTrigger:Init(spellId, own, requiredCount, invert, defaultData) | ||||
|     Trigger.Init(self, invert, defaultData) | ||||
|     self.spellId = spellId | ||||
|     self.requiredCount = requiredCount or 1 | ||||
|     self.own = own | ||||
| @@ -68,7 +70,7 @@ end | ||||
| --- Reset the AuraTrigger to the default state | ||||
| function AuraTrigger:Reset() | ||||
|     self.count = 0 | ||||
|     self:SetState(self.count >= self.requiredCount, nil, false) | ||||
|     self:SetState(self.count >= self.requiredCount, false) | ||||
| end | ||||
|  | ||||
| ---Check if a given aura matches this AuraTrigger | ||||
| @@ -90,15 +92,17 @@ function AuraTrigger:AddAura(aura) | ||||
|         return | ||||
|     end | ||||
|     self.count = self.count + 1 | ||||
|     self:SetState(self.count >= self.requiredCount, {stacks=aura.applications}, false) | ||||
|     self:SetData({ stacks = aura.applications, duration = aura.duration, expirationTime = aura.expirationTime }) | ||||
|     self:SetState(self.count >= self.requiredCount, false) | ||||
| end | ||||
|  | ||||
| ---Inform the trigger about an updated aura | ||||
| ---@param before UnitAuraInfo | ||||
| ---@param after UnitAuraInfo | ||||
| function AuraTrigger:UpdateAura(before, after) | ||||
|     self:SetData({ stacks = after.applications, duration = after.duration, expirationTime = after.expirationTime }) | ||||
|     if self.active then | ||||
|         self.indicator:Update({stacks=after.applications}) | ||||
|         self.indicator:Update(self.data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -109,5 +113,6 @@ function AuraTrigger:RemoveAura(aura) | ||||
|         return | ||||
|     end | ||||
|     self.count = self.count - 1 | ||||
|     self:SetState(self.count >= self.requiredCount, nil, false) | ||||
|     self:SetData({}) | ||||
|     self:SetState(self.count >= self.requiredCount, false) | ||||
| end | ||||
|   | ||||
| @@ -92,7 +92,8 @@ function MultiTrigger:OnChildActivate(idx, trigger, data) | ||||
|     table.sort(activeChildren) | ||||
|     -- The highest priority active trigger has changed | ||||
|     if activeChild ~= activeChildren[1] then | ||||
|         self:SetState(true, data) | ||||
|         self:SetData(data) | ||||
|         self:SetState(true, true) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -113,8 +114,15 @@ function MultiTrigger:OnChildDeactivate(idx, trigger, data) | ||||
|         end | ||||
|     end | ||||
|     table.remove(activeChildren, found) | ||||
|     if activeChild ~= activeChildren[1] then | ||||
|         self:SetState(activeChildren[1] ~= nil, childrenData[1], true) | ||||
|     local newActiveChild = activeChildren[1] | ||||
|     if activeChild ~= newActiveChild then | ||||
|         if activeChildren[1] ~= nil then | ||||
|             self:SetData(childrenData[newActiveChild]) | ||||
|             self:SetState(true, true) | ||||
|         else | ||||
|             self:SetData({}) | ||||
|             self:SetState(false, false) | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ types.StatusTrigger = StatusTrigger | ||||
| ---@param config table | ||||
| function StatusTrigger.CreateFromConfig(unit, config) | ||||
|     local trigger = StatusTrigger:new(config.status, config.requiredCount, | ||||
|         config.invert) | ||||
|         config.invert, config.defaultData) | ||||
|     unit.auras:AddTrigger(trigger) | ||||
|     return trigger | ||||
| end | ||||
| @@ -47,8 +47,8 @@ end | ||||
| ---@param status string The kind of status to trigger on | ||||
| ---@param requiredCount number | nil  | ||||
| ---@param invert boolean | nil | ||||
| function StatusTrigger:Init(status, requiredCount, invert) | ||||
|     Trigger.Init(self, invert) | ||||
| function StatusTrigger:Init(status, requiredCount, invert, defaultData) | ||||
|     Trigger.Init(self, invert, defaultData) | ||||
|     self.status = status | ||||
|     self.requiredCount = requiredCount or 1 | ||||
|     self.invert = invert or false | ||||
| @@ -59,5 +59,5 @@ end | ||||
| -- status: | ||||
| --      Must be a valid UnitAuraInfo | ||||
| function StatusTrigger:UpdateStatus(count) | ||||
|     self:SetState(count >= self.requiredCount, nil, false) | ||||
|     self:SetState(count >= self.requiredCount, false) | ||||
| end | ||||
|   | ||||
| @@ -23,6 +23,8 @@ local types = omi.GetModule("types") | ||||
| ---@class Trigger: Object | ||||
| ---@field active boolean | ||||
| ---@field invert boolean  | ||||
| ---@field indicator Indicator | ||||
| ---@field data table The most recent data updated by the data source | ||||
| local Trigger = types.CreateClass("Trigger") | ||||
| types.Trigger = Trigger | ||||
|  | ||||
| @@ -36,10 +38,25 @@ end | ||||
|  | ||||
| --- Initialize a new Trigger object | ||||
| ---@param invert boolean|nil | ||||
| function Trigger:Init(invert) | ||||
| ---@param defaultData table|nil default data that is always present when this trigger updates an indicator | ||||
| function Trigger:Init(invert, defaultData) | ||||
|     invert = invert or false | ||||
|     self.invert = invert | ||||
|     self.active = invert | ||||
|     self.defaultData = defaultData | ||||
|     self:SetData({}) | ||||
| end | ||||
|  | ||||
| ---Save new data from the datasource into the trigger. This method will make | ||||
| ---sure the default data is always present | ||||
| ---@param data table | ||||
| function Trigger:SetData(data) | ||||
|     if self.defaultData then | ||||
|         for k, v in pairs(self.defaultData) do | ||||
|             data[k] = v | ||||
|         end | ||||
|     end | ||||
|     self.data = data | ||||
| end | ||||
|  | ||||
| --- Set the target of the Trigger. | ||||
| @@ -49,30 +66,29 @@ end | ||||
| function Trigger:SetTarget(target) | ||||
|     self.indicator = target | ||||
|     if self.active then | ||||
|         target:Show() | ||||
|         target:Show(self.data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| ---Set the state of the trigger. Will activate the indicator if needed. | ||||
| ---@param data table<string,any> | nil | ||||
| ---@param state boolean | ||||
| function Trigger:SetState(state, data, doUpdate) | ||||
| function Trigger:SetState(state, doUpdate) | ||||
|     state = state ~= self.invert -- state xor inverted | ||||
|     if self.active ~= state then | ||||
|         if state then | ||||
|             self.indicator:Show(data) | ||||
|             self.indicator:Show(self.data) | ||||
|         else | ||||
|             self.indicator:Hide() | ||||
|         end | ||||
|         self.active = state | ||||
|     elseif doUpdate and self.active then | ||||
|         self.indicator:Update(data) | ||||
|         self.indicator:Update(self.data) | ||||
|     end | ||||
| end | ||||
|  | ||||
| -- Reset the trigger to the default state. If this changes the activation of the | ||||
| -- trigger then the target will be notified. | ||||
| function Trigger:Reset() | ||||
|     self:SetState(false, nil, false) | ||||
|     self:SetState(false, false) | ||||
| end | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omif = select(2, ...) | ||||
|  | ||||
| local types = omif.GetModule("types") | ||||
| @@ -48,6 +48,7 @@ function types.IsDerivedFrom(a, b) | ||||
|             return true | ||||
|         end | ||||
|         current = current.__typeInfo.parent | ||||
|     until current == nil; | ||||
|     until current == nil | ||||
|     ; | ||||
|     return false | ||||
| end | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omif = select(2, ...) | ||||
| local types = omif.GetModule("types") | ||||
|  | ||||
| @@ -35,24 +35,39 @@ types.UnitFrame = UnitFrame | ||||
|  | ||||
|  | ||||
| local colors = { | ||||
|     hostile = {0.5, 0.0, 0.0}, | ||||
|     neutral = {0.7, 0.7, 0.0}, | ||||
|     healthy = {0, 0.1, 0}, | ||||
|     high = {0, 1.0, 0}, | ||||
|     mid = {1.0, 1.0, 0}, | ||||
|     low = {1.0, 0.0, 0}, | ||||
|     offline = {0.7, 0.7, 0.7}, | ||||
|     dead = {0.7, 0.7, 0.7}, | ||||
|     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}, | ||||
|     immune = {0.0, 0.2, 0.4}, | ||||
|     bomb = {1.0, 0.7, 0.7}, | ||||
|     cyan = {0.0, 0.8, 0.8}, | ||||
|     white = {1.0, 1.0, 1.0} | ||||
|     hostile = { 0.5, 0.0, 0.0 }, | ||||
|     neutral = { 0.7, 0.7, 0.0 }, | ||||
|     healthy = { 0, 0.1, 0 }, | ||||
|     high = { 0, 1.0, 0 }, | ||||
|     mid = { 1.0, 1.0, 0 }, | ||||
|     low = { 1.0, 0.0, 0 }, | ||||
|     offline = { 0.7, 0.7, 0.7 }, | ||||
|     dead = { 0.7, 0.7, 0.7 }, | ||||
|     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 }, | ||||
|     immune = { 0.0, 0.2, 0.4 }, | ||||
|     bomb = { 1.0, 0.7, 0.7 }, | ||||
|     cyan = { 0.0, 0.8, 0.8 }, | ||||
|     white = { 1.0, 1.0, 1.0 } | ||||
| } | ||||
|  | ||||
| -- This trucates _codepoints_ not graphemes. If combination codepoints are | ||||
| -- contained in the string, it will not properly truncate and may return | ||||
| -- incorrect graphemes | ||||
| local function utf8_truncate(s, n) | ||||
|     local init = 0 | ||||
|     for _ = 1, n do | ||||
|         local _, last = string.find(s, ".[\128-\191]*", init + 1) | ||||
|         if not last then | ||||
|             return s | ||||
|         end | ||||
|         init = last | ||||
|     end | ||||
|     return string.sub(s, 1, init) | ||||
| end | ||||
|  | ||||
| ---@param unit string | ||||
| ---@param config table | ||||
| function UnitFrame:Init(unit, config) | ||||
| @@ -110,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( | ||||
| @@ -127,7 +144,7 @@ function UnitFrame:StartRangeTicker() | ||||
|     if self.rangeTicker then | ||||
|         return | ||||
|     end | ||||
|     local delta = 0.45 + (fastrandom(0, 100)/1000) | ||||
|     local delta = 0.45 + (fastrandom(0, 100) / 1000) | ||||
|     self.rangeTicker = C_Timer.NewTicker(delta, function() | ||||
|         self:UpdateRange() | ||||
|     end) | ||||
| @@ -157,7 +174,7 @@ end | ||||
| -- Returns | ||||
| --  true if the unit is in range | ||||
| --  false if the unit is not in range | ||||
| --  nil if it could not be determined  | ||||
| --  nil if it could not be determined | ||||
| function UnitFrame:IsInRange() | ||||
|     local unit = self.unit | ||||
|     local friendlySpell = self.rangeFriendly | ||||
| @@ -169,8 +186,8 @@ function UnitFrame:IsInRange() | ||||
|     elseif enemySpell and UnitCanAttack("player", unit) then | ||||
|         return IsSpellInRange(enemySpell, unit) == 1 | ||||
|     end | ||||
|      | ||||
|     -- Fall back to raid/party only range check  | ||||
|  | ||||
|     -- Fall back to raid/party only range check | ||||
|     local inRange, checkedRange = UnitInRange(unit) | ||||
|     if checkedRange then | ||||
|         return inRange | ||||
| @@ -181,7 +198,7 @@ end | ||||
|  | ||||
| function UnitFrame:UpdateRange() | ||||
|     local unit = self.unit | ||||
|      | ||||
|  | ||||
|     if UnitIsDeadOrGhost(unit) then | ||||
|         self.secureFrame:SetAlpha(1.0) | ||||
|         return | ||||
| @@ -235,7 +252,7 @@ function UnitFrame:PrepareWheelBinds(bindings) | ||||
|     -- scroll wheel to the current unit frame button when the mouse enters and | ||||
|     -- to unbind it when the mouse leaves. When the keybind is triggered the | ||||
|     -- button will receive a click with a custom button name | ||||
|      | ||||
|  | ||||
|     -- Build a table with all lines of the scroll wheel + modifier combinations | ||||
|     -- we want to bind, then concat it with newlines into a full script | ||||
|     local unit = self.unit | ||||
| @@ -247,13 +264,13 @@ function UnitFrame:PrepareWheelBinds(bindings) | ||||
|             local prefix = ModifiersToPrefix(bind.mods) | ||||
|             local button = bind.button == "wheel-up" and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" | ||||
|             table.insert(bindScript, | ||||
|                 string.format([[self:SetBindingClick(false, "%s%s", "OmicronSecureFrame%s", "%s%s")]],  | ||||
|                 string.format([[self:SetBindingClick(false, "%s%s", "OmicronSecureFrame%s", "%s%s")]], | ||||
|                     prefix, button, unit, prefix, bind.button | ||||
|                 )  | ||||
|                 ) | ||||
|             ) | ||||
|         end | ||||
|     end | ||||
|      | ||||
|  | ||||
|     local secure = self.secureFrame | ||||
|     local bindScript = table.concat(bindScript, "\n") | ||||
|  | ||||
| @@ -272,7 +289,7 @@ function UnitFrame:SetMouseBinds(binds) | ||||
|  | ||||
|     secure:RegisterForClicks("AnyDown") | ||||
|     self:PrepareWheelBinds(binds) | ||||
|      | ||||
|  | ||||
|     for _, bind in ipairs(binds) do | ||||
|         local prefix = ModifiersToPrefix(bind.mods) | ||||
|         local button | ||||
| @@ -295,7 +312,7 @@ function UnitFrame:SetMouseBinds(binds) | ||||
|         if bind.kind == "macro" then | ||||
|             self:SetMacroAction(button, bind.data) | ||||
|         elseif bind.kind == "spell" then | ||||
|             self:SetSpellAction(button, bind.data)  | ||||
|             self:SetSpellAction(button, bind.data) | ||||
|         else | ||||
|             secure:SetAttribute(button, bind.kind) | ||||
|         end | ||||
| @@ -455,7 +472,7 @@ end | ||||
|  | ||||
| function UnitFrame:ROLE_CHANGED_INFORM(name, changer, old, new) | ||||
|     if UnitName(self.unit) == name then | ||||
|          self:UpdateRole(new) | ||||
|         self:UpdateRole(new) | ||||
|     end | ||||
| end | ||||
|  | ||||
| @@ -563,7 +580,7 @@ function UnitFrame:UpdateHealthColor() | ||||
|     elseif isFriend and pct >= 0.90 then | ||||
|         self.hp:SetColor(unpack(colors.healthy)) | ||||
|     elseif isFriend and pct >= 0.75 then | ||||
|         local progress = (pct - 0.75) / (0.90-0.75) | ||||
|         local progress = (pct - 0.75) / (0.90 - 0.75) | ||||
|         self.hp:SetInterpolatedColor(colors.mid, colors.high, progress) | ||||
|     else | ||||
|         local progress = pct / 0.75 | ||||
| @@ -580,25 +597,10 @@ function UnitFrame:UpdateName() | ||||
|         -- TODO: UnitClass can return Unknown and the color can be nil. Having | ||||
|         -- the unit exist but not fully loaded is possibly a state we want to | ||||
|         -- handle more generally | ||||
|         local color = RAID_CLASS_COLORS[class] or {r=1, g=1, b=1} | ||||
|         local color = RAID_CLASS_COLORS[class] or { r = 1, g = 1, b = 1 } | ||||
|         self.name:SetTextColor(color.r, color.g, color.b) | ||||
|     else | ||||
|         self.name:SetTextColor(1, 1, 1) | ||||
|     end | ||||
|     self.name:SetText(UnitName(self.unit):sub(1, 5)) | ||||
|     self.name:SetText(utf8_truncate((UnitName(self.unit)), 5)) | ||||
| end | ||||
|  | ||||
| --[[ | ||||
|     -- UNIT_AURA | ||||
|     -- UNIT_CLASSIFICATION_CHANGED | ||||
|     -- UNIT_COMBAT | ||||
|     -- UNIT_CONNECTION | ||||
|     -- UNIT_DISPLAYPOWER | ||||
|     -- UNIT_FACTION | ||||
|     -- UNIT_FLAGS | ||||
|     -- UNIT_LEVEL | ||||
|     -- UNIT_MANA | ||||
|     -- UNIT_HEALTH_PREDICTION | ||||
|     -- UNIT_PHASE | ||||
| ]]-- | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| -- Copyright 2023 <omicron.me@protonmail.com> | ||||
| -- | ||||
| -- 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 <https://www.gnu.org/licenses/>.  | ||||
| -- Omicron Frames. If not, see <https://www.gnu.org/licenses/>. | ||||
| local omi = select(2, ...) | ||||
| local types = omi.GetModule("types") | ||||
| local UnitGroup = types.CreateClass("UnitGroup") | ||||
| @@ -38,7 +38,7 @@ local function UnitFrameDefaultCompare(lhs, rhs) | ||||
|     end | ||||
|  | ||||
|     local lunit, runit = lhs.unit, rhs.unit | ||||
|      | ||||
|  | ||||
|     -- players < non-players | ||||
|     local player = UnitIsPlayer(lunit) | ||||
|     if UnitIsPlayer(lunit) ~= UnitIsPlayer(runit) then | ||||
| @@ -50,16 +50,16 @@ local function UnitFrameDefaultCompare(lhs, rhs) | ||||
|         if UnitIsUnit(lunit, "player") ~= UnitIsUnit(runit, "player") then | ||||
|             return UnitIsUnit(lunit, "player") | ||||
|         end | ||||
|      | ||||
|  | ||||
|         -- tank < healer < damage < ? | ||||
|         local lrole = RoleValue(UnitGroupRolesAssigned(lunit)) | ||||
|         local rrole = RoleValue(UnitGroupRolesAssigned(runit)) | ||||
|          | ||||
|  | ||||
|         if lrole ~= rrole then | ||||
|             return lrole < rrole | ||||
|         end | ||||
|     end | ||||
|      | ||||
|  | ||||
|     return lunit < runit | ||||
| end | ||||
|  | ||||
| @@ -121,14 +121,14 @@ function UnitGroup:Sort() | ||||
|     table.sort(self.units, UnitFrameDefaultCompare) | ||||
|     local left, top, width, height = self.left, self.top, self.width, self.height | ||||
|     local maxFrameIndex = #self.units | ||||
|     for y=0,5 do | ||||
|         for x=0,4 do | ||||
|             local num = y*5 + x + 1 | ||||
|     for y = 0, 5 do | ||||
|         for x = 0, 4 do | ||||
|             local num = y * 5 + x + 1 | ||||
|             if num > maxFrameIndex then | ||||
|                 return | ||||
|             end | ||||
|             local frame = self.units[num] | ||||
|             frame:SetPosition(left + (x-2)*width, top - y*height) | ||||
|             frame:SetPosition(left + (x - 2) * width, top - y * height) | ||||
|         end | ||||
|     end | ||||
| end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user