Compare commits

...

10 Commits

Author SHA1 Message Date
ff9d8b2289 Add/change monk and priest keybinds and auras 2023-11-05 19:20:16 +01:00
24c571658c Apply auto formatting to all source files 2023-09-10 12:37:25 +02:00
e20887d46b Implement fade and flash behavior for square indicators 2023-07-28 14:15:50 +02:00
877560cb58 Rework profiler for 10.1.0
Since GetFunctionCPUUsage was removed in 10.1.0 the entire profler
stopped working. This has been replaced by wrapping the functions in a
closure that runs GetTimePreciseSec before and after and keeps track of
the total runtime per function.
2023-07-27 15:29:08 +02:00
b201ef789a Partially fix unicode name truncation.
This fix ensures that name truncation always happens on codepoint
boundaries and that a name has exactly 5 visible codepoints. This should
cover all possible cases unless names can have grapheme clusters, afaik
this is not the case.
2023-07-26 03:15:13 +02:00
30d8248832 Expand spell ids for default AuraList statuses 2023-05-12 16:51:39 +02:00
5668a5b4db Fix a bug where AuraList wasn't processing a full update
This fixes issue #8
2023-05-12 15:50:34 +02:00
263b3f1330 Update default configuration indicators/keybinds/layout 2023-05-12 15:45:54 +02:00
45129a8635 Square- and BorderIndicator now use trigger data for changing color
If the field color is supplied from trigger data, these indicators will
now change their color. Currently this change is permanent and not bound to the
trigger.
2023-04-14 15:40:39 +02:00
1f95899781 Make Trigger responsible for default data
Trigger now has a new method Trigger:SetData and two new fields
Trigger.defaultData and Trigger.data

Whenever SetData is used it ensures that all the keys and values from
defaultData are present in the new data.

The data argument from Trigger:SetState has been removed and it will now
always use the Trigger.Data field for notifying indicators
2023-04-14 15:37:57 +02:00
17 changed files with 727 additions and 272 deletions

View File

@@ -17,10 +17,17 @@
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)

View File

@@ -19,7 +19,7 @@ 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
@@ -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)

View File

@@ -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
})

View File

@@ -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

View File

@@ -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

View File

@@ -36,4 +36,3 @@ end
--- Hide the indicator
function Indicator:Hide()
end

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
@@ -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
]]--

View File

@@ -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