local _G = getfenv(0) local gratuity = AceLibrary("Gratuity-2.0") local Dewdrop = AceLibrary("Dewdrop-2.0") local LSM3 = LibStub("LibSharedMedia-3.0") local tablet = AceLibrary("Tablet-2.0") local ipairs = _G.ipairs local next = _G.next local pairs = _G.pairs local select = _G.select local tonumber = _G.tonumber local tostring = _G.tostring local type = _G.type local unpack = _G.unpack local GetInventoryItemLink = _G.GetInventoryItemLink local GetInventoryItemTexture = _G.GetInventoryItemTexture local GetInventorySlotInfo = _G.GetInventorySlotInfo local GetItemInfo = _G.GetItemInfo local GetPlayerBuff = _G.GetPlayerBuff local GetPlayerBuffApplications = _G.GetPlayerBuffApplications local GetPlayerBuffName = _G.GetPlayerBuffName local GetPlayerBuffTexture = _G.GetPlayerBuffTexture local GetPlayerBuffTimeLeft = _G.GetPlayerBuffTimeLeft local GetPlayerBuffDispelType = _G.GetPlayerBuffDispelType local GetWeaponEnchantInfo = _G.GetWeaponEnchantInfo local GetTrackingTexture = _G.GetTrackingTexture local UnitBuff = _G.UnitBuff local UnitDebuff = _G.UnitDebuff local math_abs = _G.math.abs local strgmatch = _G.string.gmatch local strgsub = _G.string.gsub local strmatch = _G.string.match local strtrim = _G.string.trim local strutf8sub = _G.string.utf8sub local table_insert = _G.table.insert local table_remove = _G.table.remove local table_sort = _G.table.sort local RANK = _G.RANK local L = setmetatable({}, {__index = function(self, key) return key end}) ElkBuffBars = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceDB-2.0", "AceEvent-2.0", "FuBarPlugin-2.0") -- ElkBuffBars = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceDB-2.0", "AceEvent-2.0", "AceDebug-2.0", "FuBarPlugin-2.0") local ElkBuffBars = ElkBuffBars local EBB_Bar = _G.EBB_Bar local EBB_BarGroup = _G.EBB_BarGroup -- ElkBuffBars.debugFrame = ChatFrame4 -- ElkBuffBars:SetDebugging(true) ElkBuffBars.revision = tonumber(string.sub("$Revision: 63558 $", 12, -3)) or 1 ElkBuffBars:RegisterDB("ElkBuffBarsDB") ElkBuffBars:RegisterDefaults("profile", { bargroups = {}, groupspacing = 10, hidebuffframe = true, hidetenchframe = true, hidetrackingframe = true, shiftannounce = true, anounceoutofparty = true, nameoverride = { BUFF = {}, DEBUFF = {}, TENCH = {}, TRACKING = {}, }, typeoverride = { BUFF = {}, DEBUFF = {}, TENCH = {}, TRACKING = {}, }, }) function ElkBuffBars:AddDefaultBargroups() table_insert(self.db.profile.bargroups, { ["bars"] = { ["barcolor"] = {0.3, 0.5, 1, 0.8}, -- ["barbgcolor"] = {0, 0.5, 1, 0.3}, -- }, ["filter"] = { ["type"] = { ["BUFF"] = true, ["TRACKING"] = true, } }, anchortext = "BUFFS & TRACKING", -- }) table_insert(self.db.profile.bargroups, { ["bars"] = { ["barcolor"] = {1, 0, 0, 0.8}, -- ["barbgcolor"] = {1, 0, 0, 0.3}, -- }, ["filter"] = { ["type"] = { ["DEBUFF"] = true, } }, anchortext = "DEBUFFS", -- anchorshown = false, -- true, false stickto = 1, -- bargroup id stickside = "", -- "LEFT", "RIGHT", "" }) table_insert(self.db.profile.bargroups, { ["bars"] = { ["barcolor"] = {0.5, 0, 0.5, 0.8}, -- ["barbgcolor"] = {0.5, 0, 0.5, 0.3}, -- }, ["filter"] = { ["type"] = { ["TENCH"] = true, } }, anchortext = "TENCH", -- anchorshown = false, -- true, false stickto = 2, -- bargroup id stickside = "", -- "LEFT", "RIGHT", "" }) end local STICKTO_AREA = 25 local INVENTORYSLOT_MAINHAND = GetInventorySlotInfo("MainHandSlot") local INVENTORYSLOT_SECONDARYHAND = GetInventorySlotInfo("SecondaryHandSlot") local updates_disabled = false local scan_happend = {} local old_hasMainHandEnchant, old_mainHandExpiration, old_mainHandCharges, old_mainHandName, old_mainHandRank local old_hasOffHandEnchant, old_offHandExpiration, old_offHandCharges, old_offHandName, old_offHandRank local AO_allopts local AO_buffsettings local AO_groupsettings local LSM3_font = LSM3:List("font") local LSM3_statusbar = LSM3:List("statusbar") ElkBuffBars.ShortName = setmetatable({}, { __index = function(self, key) local name = key local shortname = "" if strmatch(name, "[%(%)]") then name = strtrim(strgsub(strgsub(name, "%b()", ""), " +", " ")) end for word in strgmatch(name, "([^ ]+)") do local alpha, bravo = strutf8sub(word, 1, 1), strutf8sub(word, 2) if strmatch(bravo, ":") then shortname = shortname..alpha .. ":" else shortname = shortname..alpha end end self[key] = shortname return shortname end, }) function ElkBuffBars:OnInitialize() local build = select(2, _G.GetBuildInfo()) if not self.db.account.build or self.db.account.build ~= build or true then self.db.account.build = build self.db.account.maxtimes = nil self.db.account.maxcharges = nil end if not self.db.account.maxtimes then self.db.account.maxtimes = { BUFF = {}, DEBUFF = {}, TENCH = {}, } end if not self.db.account.maxcharges then self.db.account.maxcharges = { BUFF = {}, DEBUFF = {}, TENCH = {}, } end end function ElkBuffBars:OnEnable() self:OnProfileEnable() -- register events self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterBucketEvent("MINIMAP_UPDATE_TRACKING", .2) self:RegisterBucketEvent("PLAYER_AURAS_CHANGED", .2) self:RegisterBucketEvent("PLAYER_FOCUS_CHANGED", .2) self:RegisterBucketEvent("PLAYER_TARGET_CHANGED", .2) self:RegisterBucketEvent("UNIT_PET", .2) self:RegisterBucketEvent("UNIT_AURA", .2) self:ScheduleRepeatingEvent(self.DoUpdates, .5, self) LSM3.RegisterCallback(self, "LibSharedMedia_Registered", "LibSharedMedia_Update") LSM3.RegisterCallback(self, "LibSharedMedia_SetGlobal", "LibSharedMedia_Update") -- self:ScanData_BUFF() self:ScanData_DEBUFF() self:ScanData_TENCH() self:ScanData_TRACKING() --~ --~ self:RegisterEvent("UNIT_INVENTORY_CHANGED") --~ -- hide Blizzard frames self:PLAYER_ENTERING_WORLD() end --~ --~ function ElkBuffBars:UNIT_INVENTORY_CHANGED(...) --~ self:PrintComma("UNIT_INVENTORY_CHANGED", ...) --~ self:PrintComma(string.match(GetInventoryItemLink("player", INVENTORYSLOT_MAINHAND) or "nil", "|H(item:[^|]*)|") or "nil", string.match(GetInventoryItemLink("player", INVENTORYSLOT_SECONDARYHAND) or "nil", "|H(item:[^|]*)|") or "nil") --~ end --~ function ElkBuffBars:OnDisable() self:OnProfileDisable() end function ElkBuffBars:OnProfileEnable() -- add default bargroups if #self.db.profile.bargroups == 0 then self:AddDefaultBargroups() end -- check bargroups self:CheckLayouts() -- update known names self:UpdateKnownNames() -- create bargroups based on stored settings self:CreateBarGroups() end function ElkBuffBars:OnProfileDisable() -- recycle all bargroups self:RemoveBarGroups() end -- refresh layouts when new media is set function ElkBuffBars:LibSharedMedia_Update(callback, type, handle) if type == "font" or type == "statusbar" then for k, v in pairs(self.bargroups) do v:SetLayout() end end end function ElkBuffBars:PLAYER_ENTERING_WORLD() --~ BuffFrame:Hide() --~ TemporaryEnchantFrame:Hide() self:HandleFrame_Blizzard_BuffFrame(self.db.profile.hidebuffframe) self:HandleFrame_Blizzard_TemporaryEnchantFrame(self.db.profile.hidetenchframe) self:HandleFrame_Blizzard_MiniMapTracking(self.db.profile.hidetrackingframe) end local hidden_blizzard_frames = {} function ElkBuffBars:HandleFrame_Blizzard_BuffFrame(hide) if hide then BuffFrame:UnregisterEvent("PLAYER_AURAS_CHANGED") BuffFrame:Hide() hidden_blizzard_frames["BuffFrame"] = true elseif hidden_blizzard_frames["BuffFrame"] then BuffFrame:RegisterEvent("PLAYER_AURAS_CHANGED") BuffFrame:Show() BuffFrame_Update() hidden_blizzard_frames["BuffFrame"] = false end end function ElkBuffBars:HandleFrame_Blizzard_TemporaryEnchantFrame(hide) if hide then BuffFrame:UnregisterEvent("PLAYER_AURAS_CHANGED") TemporaryEnchantFrame:Hide() BuffFrame:SetPoint("TOPRIGHT", "TemporaryEnchantFrame", "TOPRIGHT", 0, 0) hidden_blizzard_frames["TemporaryEnchantFrame"] = true elseif hidden_blizzard_frames["TemporaryEnchantFrame"] then BuffFrame:RegisterEvent("PLAYER_AURAS_CHANGED") TemporaryEnchantFrame:Show() hidden_blizzard_frames["TemporaryEnchantFrame"] = false end end function ElkBuffBars:HandleFrame_Blizzard_MiniMapTracking(hide) if hide then MiniMapTracking:UnregisterEvent("MINIMAP_UPDATE_TRACKING") MiniMapTracking:Hide() hidden_blizzard_frames["MiniMapTracking"] = true elseif hidden_blizzard_frames["MiniMapTracking"] then MiniMapTracking:RegisterEvent("MINIMAP_UPDATE_TRACKING") MiniMapTracking:Show() MiniMapTracking_Update() hidden_blizzard_frames["MiniMapTracking"] = false end end -- ----- -- cache bars -- ----- local barcache = {} function ElkBuffBars:GetBar() if #barcache > 0 then return table_remove(barcache, #barcache) else return EBB_Bar:new() end end function ElkBuffBars:RecycleBar(bar) bar:Reset() table_insert(barcache, bar) end -- ----- -- cache bargroups -- ----- local bargroupcache = {} function ElkBuffBars:GetBarGroup() if #bargroupcache > 0 then return table_remove(bargroupcache, #bargroupcache) else return EBB_BarGroup:new() end end function ElkBuffBars:RecycleBarGroup(bargroup) bargroup:Reset() table_insert(bargroupcache, bargroup) end -- ----- -- cache datatables -- ----- local datatablecache = {} local function GetDataTable() if #datatablecache > 0 then return table_remove(datatablecache, #datatablecache) else return {} end end local function RecycleDataTable(dt) table_insert(datatablecache, dt) end -- ----- -- known names -- ----- ElkBuffBars.knownnames = { BUFF = {}, DEBUFF = {}, TENCH = {}, TRACKING = {}, } local knownnames_validate = { BUFF = {}, DEBUFF = {}, TENCH = {}, TRACKING = {}, } function ElkBuffBars:AddKnownName(type, name) if not self.knownnames[type][name] then self.knownnames[type][name] = true AO_buffsettings.args[type].args[name] = self:GetNameOptions(type, name) table_insert(knownnames_validate[type], name) table_sort(knownnames_validate[type]) end end function ElkBuffBars:UpdateKnownNames() for type, data in pairs(self.db.profile.nameoverride) do for name in pairs(data) do self:AddKnownName(type, name) end end for type, data in pairs(self.db.profile.typeoverride) do for name in pairs(data) do self:AddKnownName(type, name) end end for id, bg in pairs(self.db.profile.bargroups) do if bg.filter.names_include then for type, data in pairs(bg.filter.names_include) do for name in pairs(data) do self:AddKnownName(type, name) end end end if bg.filter.names_exclude then for type, data in pairs(bg.filter.names_exclude) do for name in pairs(data) do self:AddKnownName(type, name) end end end end end -- ----- -- creation/removing of bargroups -- ----- ElkBuffBars.bargroups = {} local function ApplyDefaults(defaults, data) for k, v in pairs(defaults) do if type(v) == "table" then if data[k] == nil or type(data[k]) ~= "table" then data[k] = {} end ApplyDefaults(v, data[k]) else if data[k] == nil then data[k] = v end end end end local DEFAULT_LAYOUT = { ["bars"] = { ["icon"] = "LEFT", -- "LEFT", "RIGHT", false ["iconcount"] = true, -- true, false ["iconcountanchor"] = "CENTER", -- ["iconcountfont"] = "Arial Narrow", -- ["iconcountfontsize"] = 14, -- ["iconcountcolor"] = {1, 1, 1, 1}, -- ["bar"] = true, -- true, false ["bgbar"] = true, -- true, false ["bartexture"] = "Otravi", -- , false ["barright"] = false, -- true, false ["textTL"] = "NAMERANKCOUNT", -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" ["textTLfont"] = "Friz Quadrata TT", -- ["textTLfontsize"] = 14, -- ["textTLcolor"] = {1, 1, 1, 1}, -- ["textTLalign"] = "LEFT", -- left, center, right ["textTR"] = "TIMELEFT", -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" ["textTRfont"] = "Friz Quadrata TT", -- ["textTRfontsize"] = 14, -- ["textTRcolor"] = {1, 1, 1, 1}, -- ["textBL"] = false, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" ["textBLfont"] = "Friz Quadrata TT", -- ["textBLfontsize"] = 14, -- ["textBLcolor"] = {1, 1, 1, 1}, -- ["textBLalign"] = "LEFT", -- left, center, right ["textBR"] = false, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" ["textBRfont"] = "Friz Quadrata TT", -- ["textBRfontsize"] = 14, -- ["textBRcolor"] = {1, 1, 1}, -- ["barcolor"] = {0.3, 0.5, 1, 0.8}, -- ["barbgcolor"] = {0, 0.5, 1, 0.3}, -- ["debufftypecolor"] = true, -- true, false ["timeformat"] = "CONDENSED", -- "DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED" ["width"] = 250, ["height"] = 20, ["tooltipanchor"] = "default", -- , "default" timelessfull = false, -- true, false alpha = 1, -- alpha value padding = 1, -- 0 - 10 abbreviate_name = 0, -- }, ["filter"] = { ["type"] = { } }, sorting = "timeleft", -- timeleft, timemax target = "player", -- player, pet, target growup = false, -- true, false barspacing = 0, -- 0+ anchortext = "unknown bargroup", -- anchorshown = true, -- true, false } -- resets corrupt entries in the given layout to default values; returns a now valid layout function ElkBuffBars:CheckLayout(layout) if not layout or type(layout) ~= "table" then layout = {} end ApplyDefaults(DEFAULT_LAYOUT, layout) return layout end function ElkBuffBars:CheckLayouts() local bglayouts = self.db.profile.bargroups for k, v in ipairs(bglayouts) do self:CheckLayout(v) end end function ElkBuffBars:CreateBarGroups() for k, v in pairs(self.bargroups) do self:RecycleBarGroup(v) self.bargroups[k] = nil end local bglayouts = self.db.profile.bargroups for k, v in ipairs(bglayouts) do self:AddBarGroup(v) end for k, v in ipairs(self.bargroups) do local layout = bglayouts[k] v:SetPosition() v:GetContainer():Show() end end function ElkBuffBars:RemoveBarGroups() for k, v in pairs(self.bargroups) do self:RecycleBarGroup(v) self.bargroups[k] = nil AO_groupsettings[k] = nil end end function ElkBuffBars:AddBarGroup(layout) if not layout then layout = { ["bars"] = { }, ["filter"] = { ["type"] = { ["BUFF"] = true, } }, anchortext = "new bargroup", -- } table_insert(self.db.profile.bargroups, layout) end local bargroup = self:GetBarGroup() table_insert(self.bargroups, bargroup) layout.id = #self.bargroups self:CheckLayout(layout) bargroup:SetLayout(layout) table_insert(AO_groupsettings, self:GetGroupOptions(#self.bargroups)) return bargroup end function ElkBuffBars:RemoveBarGroup(id) local bg = table_remove(self.bargroups, id) table_remove(self.db.profile.bargroups, id) for k, v in pairs(self.bargroups) do local layout = v.layout layout.id = k if layout.stickto then if layout.stickto == id then -- the group we sticked to was removed local container = v:GetContainer() layout.stickto = nil container:ClearAllPoints() container:SetPoint("CENTER", UIParent, "CENTER", layout.x, layout.y) v:ToggleAnchor(true) elseif layout.stickto > id then layout.stickto = layout.stickto - 1 end end end table_remove(AO_groupsettings) self:RecycleBarGroup(bg) end function ElkBuffBars:CopyBarLayout(target, source) if target == source then return end if not source then source = DEFAULT_LAYOUT end target.bars = {} ApplyDefaults(source.bars, target.bars) target.sorting = source.sorting self.bargroups[target.id]:SetLayout() end -- ----- -- buff scanning -- ----- ElkBuffBars.buffdata = { focus = {}, pet = {}, player = {}, target = {}, } ElkBuffBars.debuffdata = { focus = {}, pet = {}, player = {}, target = {}, } ElkBuffBars.tenchdata = {} ElkBuffBars.trackingdata = {} function ElkBuffBars:MINIMAP_UPDATE_TRACKING() self:ScanData_TRACKING() self:DoUpdates() end function ElkBuffBars:PLAYER_AURAS_CHANGED() self:ScanData_BUFF() self:ScanData_DEBUFF() self:DoUpdates() end function ElkBuffBars:PLAYER_FOCUS_CHANGED() self:ScanData_Unit_BUFF("focus") self:ScanData_Unit_DEBUFF("focus") self:DoUpdates() end function ElkBuffBars:PLAYER_TARGET_CHANGED() self:ScanData_Unit_BUFF("target") self:ScanData_Unit_DEBUFF("target") self:DoUpdates() end function ElkBuffBars:UNIT_PET(args) if args["player"] then self:ScanData_Unit_BUFF("pet") self:ScanData_Unit_DEBUFF("pet") self:DoUpdates() end end local watched_unitids = { focus = true, pet = true, target = true } function ElkBuffBars:UNIT_AURA(args) for arg in pairs(args) do if watched_unitids[arg] then self:ScanData_Unit_BUFF(arg) self:ScanData_Unit_DEBUFF(arg) end end self:DoUpdates() end local PATTERN_RANK = RANK.." (%d+)" function ElkBuffBars:ScanData_BUFF() updates_disabled = true local maxtimes = self.db.account.maxtimes.BUFF local maxcharges = self.db.account.maxcharges.BUFF local datatable = self.buffdata.player for k, v in pairs(datatable) do RecycleDataTable(v) datatable[k] = nil end local i = 1 while true do local buffIndex, untilCancelled = GetPlayerBuff(i, "HELPFUL") if buffIndex == 0 then break end local name, rank = GetPlayerBuffName(buffIndex) self:AddKnownName("BUFF", name) local tname = name..(rank and (" "..rank) or "") if rank then rank = strmatch(rank, PATTERN_RANK) end local timeleft = GetPlayerBuffTimeLeft(buffIndex) local timemax = timeleft if maxtimes[tname] and timemax < maxtimes[tname] then timemax = maxtimes[tname] else -- if timeleft > 0 then self:Debug(i, buffIndex, name, ("%.1f"):format(timeleft / 60)) end maxtimes[tname] = timemax end local charges = GetPlayerBuffApplications(buffIndex) or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = buffIndex dt.name = self.db.profile.nameoverride.BUFF[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = self.db.profile.typeoverride.BUFF[name] or "BUFF" dt.realtype = "BUFF" dt.debufftype = nil dt.timeleft = timeleft dt.timemax = timemax dt.untilcancelled = (untilCancelled == 1) and true or nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = GetPlayerBuffTexture(buffIndex) table_insert(datatable, dt) i = i + 1 end scan_happend.player = true updates_disabled = false end function ElkBuffBars:ScanData_DEBUFF() updates_disabled = true local maxtimes = self.db.account.maxtimes.DEBUFF local maxcharges = self.db.account.maxcharges.DEBUFF local datatable = self.debuffdata.player for k, v in pairs(datatable) do RecycleDataTable(v) datatable[k] = nil end local i = 1 while true do local buffIndex, untilCancelled = GetPlayerBuff(i, "HARMFUL") if buffIndex == 0 then break end local name, rank = GetPlayerBuffName(buffIndex) self:AddKnownName("DEBUFF", name) local tname = name..(rank and (" "..rank) or "") if rank then rank = strmatch(rank, PATTERN_RANK) end local timeleft = GetPlayerBuffTimeLeft(buffIndex) local timemax = timeleft if maxtimes[tname] and timemax < maxtimes[tname] then timemax = maxtimes[tname] else -- if timeleft > 0 then self:Debug(i, buffIndex, name, ("%.1f"):format(timeleft / 60)) end maxtimes[tname] = timemax end local charges = GetPlayerBuffApplications(buffIndex) or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = buffIndex dt.name = self.db.profile.nameoverride.DEBUFF[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = self.db.profile.typeoverride.DEBUFF[name] or "DEBUFF" dt.realtype = "DEBUFF" dt.debufftype = GetPlayerBuffDispelType(buffIndex) dt.timeleft = timeleft dt.timemax = timemax dt.untilcancelled = (untilCancelled == 1) and true or nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = GetPlayerBuffTexture(buffIndex) table_insert(datatable, dt) i = i + 1 end scan_happend.player = true updates_disabled = false end function ElkBuffBars:ScanData_TENCH() updates_disabled = true local maxtimes = self.db.account.maxtimes.TENCH local maxcharges = self.db.account.maxcharges.TENCH for k, v in pairs(self.tenchdata) do RecycleDataTable(v) self.tenchdata[k] = nil end local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() if ( hasMainHandEnchant ) then local timeleft = mainHandExpiration / 1000 local timemax = timeleft local id = INVENTORYSLOT_MAINHAND local name, rank = self:GetTempBuffName(id) self:AddKnownName("TENCH", name) local tname = name..(rank and (" "..rank) or "") -- if rank then -- rank = strmatch(rank, PATTERN_RANK) -- end if maxtimes[tname] and timemax < maxtimes[tname] then timemax = maxtimes[tname] else maxtimes[tname] = timemax end local charges = mainHandCharges or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = id dt.name = self.db.profile.nameoverride.TENCH[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = self.db.profile.typeoverride.TENCH[name] or "TENCH" dt.realtype = "TENCH" dt.debufftype = nil dt.timeleft = timeleft dt.timemax = timemax dt.untilcancelled = nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = GetInventoryItemTexture("player", id) table_insert(self.tenchdata, dt) end if ( hasOffHandEnchant ) then local timeleft = offHandExpiration / 1000 local timemax = timeleft local id = INVENTORYSLOT_SECONDARYHAND local name, rank = self:GetTempBuffName(id) local tname = name..(rank and (" "..rank) or "") self:AddKnownName("TENCH", name) -- if rank then -- rank = strmatch(rank, PATTERN_RANK) -- end if maxtimes[tname] and timemax < maxtimes[tname] then timemax = maxtimes[tname] else maxtimes[tname] = timemax end local charges = offHandCharges or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = id dt.name = self.db.profile.nameoverride.TENCH[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = self.db.profile.typeoverride.TENCH[name] or "TENCH" dt.realtype = "TENCH" dt.debufftype = nil dt.timeleft = timeleft dt.timemax = timemax dt.untilcancelled = nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = GetInventoryItemTexture("player", id) table_insert(self.tenchdata, dt) end scan_happend.player = true updates_disabled = false end function ElkBuffBars:ScanData_TRACKING() updates_disabled = true for k, v in pairs(self.trackingdata) do RecycleDataTable(v) self.trackingdata[k] = nil end local icon = GetTrackingTexture() if icon then local name = self:GetTrackingName() self:AddKnownName("TRACKING", name) local dt = GetDataTable() dt.id = 1 dt.name = self.db.profile.nameoverride.TRACKING[name] or name dt.realname = name dt.rank = nil dt.type = self.db.profile.typeoverride.TRACKING[name] or "TRACKING" dt.realtype = "TRACKING" dt.debufftype = nil dt.timeleft = 1 dt.timemax = 1 dt.untilcancelled = true dt.charges = 0 dt.maxcharges = nil dt.icon = icon table_insert(self.trackingdata, dt) end scan_happend.player = true updates_disabled = false end function ElkBuffBars:ScanData_Unit_BUFF(unit) local maxcharges = self.db.account.maxcharges.BUFF local datatable = self.buffdata[unit] if not datatable then return end updates_disabled = true for k, v in pairs(datatable) do RecycleDataTable(v) datatable[k] = nil end local i = 1 while true do local name, rank, icon, charges, timemax, timeleft = UnitBuff(unit, i) if not icon then break end local tname = name..(rank and (" "..rank) or "") self:AddKnownName("BUFF", name) if rank then rank = strmatch(rank, PATTERN_RANK) end if timemax then self.db.account.maxtimes.BUFF[tname] = timemax end charges = charges or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = i dt.name = self.db.profile.nameoverride.BUFF[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = (self.db.profile.typeoverride.BUFF[name] or "BUFF") dt.realtype = "BUFF" dt.debufftype = nil dt.timeleft = timeleft or 1 dt.timemax = timemax or 1 dt.untilcancelled = ((not timemax) or timemax == 0) and true or nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = icon table_insert(datatable, dt) i = i + 1 end scan_happend[unit] = true updates_disabled = false end function ElkBuffBars:ScanData_Unit_DEBUFF(unit) local maxcharges = self.db.account.maxcharges.DEBUFF local datatable = self.debuffdata[unit] if not datatable then return end updates_disabled = true for k, v in pairs(datatable) do RecycleDataTable(v) datatable[k] = nil end local i = 1 while true do local name, rank, icon, charges, debuffType, timemax, timeleft = UnitDebuff(unit, i); if not icon then break end local tname = name..(rank and (" "..rank) or "") self:AddKnownName("DEBUFF", name) if rank then rank = strmatch(rank, PATTERN_RANK) end if timemax then self.db.account.maxtimes.DEBUFF[tname] = timemax end charges = charges or 0 if charges > 1 and (not maxcharges[tname] or maxcharges[tname] < charges) then maxcharges[tname] = charges end local dt = GetDataTable() dt.id = i dt.name = self.db.profile.nameoverride.DEBUFF[name] or name dt.realname = name dt.rank = rank and tonumber(rank) or nil dt.type = (self.db.profile.typeoverride.DEBUFF[name] or "DEBUFF") dt.realtype = "DEBUFF" dt.debufftype = debuffType dt.timeleft = timeleft or 1 dt.timemax = timemax or 1 dt.untilcancelled = ((not timemax) or timemax == 0) and true or nil dt.charges = charges dt.maxcharges = maxcharges[tname] dt.icon = icon table_insert(datatable, dt) i = i + 1 end scan_happend[unit] = true updates_disabled = false end local roman_to_arabic = setmetatable({I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000}, {__index=function(self, roman) local arabic = 0 local maxval = 0 for i = roman:len(), 1, -1 do local digitval = self[roman:sub(i,i)] if digitval < maxval then arabic = arabic - digitval else arabic = arabic + digitval maxval = digitval end end self[roman] = arabic return arabic end}) function ElkBuffBars:GetTempBuffName(id) local rank gratuity:SetInventoryItem("player", id) local _, _, buffname = gratuity:Find("^(.+) %(%d+ [^%)]+%)$") if buffname then buffname = strgsub(buffname, " %(%d+ [^%)]+%)", "") -- remove 2nd brackets for buffs with charges local tname, trank = strmatch(buffname, "(.*) (%d*)$") if tname then buffname = tname rank = trank else local tname, trank = strmatch(buffname, "(.*) ([CDILMVX]*)$") if tname then buffname = tname rank = roman_to_arabic[trank] end end return buffname, rank end local itemlink = GetInventoryItemLink("player", id) if itemlink then local name = GetItemInfo(itemlink) return name or "Weapon "..id end return "Weapon "..id end function ElkBuffBars:GetTrackingName() local name, texture, active, category local count = GetNumTrackingTypes() for id=1, count do name, texture, active, category = GetTrackingInfo(id) if active then return name end end return NONE end -- -- -- function ElkBuffBars:UpdateTimes(unit) for k, v in pairs(self.buffdata[unit]) do if not v.untilcancelled then local timemax, timeleft = select(5, UnitBuff(unit, v.id)) if not timemax or timemax == 0 or timeleft > v.timeleft then self:ScanData_Unit_BUFF(unit) break end v.timeleft = timeleft end end for k, v in pairs(self.debuffdata[unit]) do if not v.untilcancelled then local timemax, timeleft = select(6, UnitDebuff(unit, v.id)) if not timemax or timemax == 0 or timeleft > v.timeleft then self:ScanData_Unit_DEBUFF(unit) break end v.timeleft = timeleft end end end function ElkBuffBars:DoUpdates() if updates_disabled then return end for k, v in pairs(self.buffdata.player) do if not v.untilcancelled then local timeleft = GetPlayerBuffTimeLeft(v.id) if timeleft > v.timeleft then self:ScanData_BUFF() break end v.timeleft = timeleft end end for k, v in pairs(self.debuffdata.player) do if not v.untilcancelled then local timeleft = GetPlayerBuffTimeLeft(v.id) if timeleft > v.timeleft then self:ScanData_DEBUFF() break end v.timeleft = timeleft end end -- check for changed weaponbuffs local hasMainHandEnchant, mainHandExpiration, mainHandCharges, hasOffHandEnchant, offHandExpiration, offHandCharges = GetWeaponEnchantInfo() local mainHandName, mainHandRank if hasMainHandEnchant then mainHandName, mainHandRank = self:GetTempBuffName(INVENTORYSLOT_MAINHAND) end local offHandName, offHandRank if hasOffHandEnchant then offHandName, offHandRank = self:GetTempBuffName(INVENTORYSLOT_SECONDARYHAND) end if hasMainHandEnchant ~= old_hasMainHandEnchant or (mainHandExpiration or 0) > (old_mainHandExpiration or 0) or mainHandCharges ~= old_mainHandCharges or mainHandName ~= old_mainHandName or mainHandRank ~= old_mainHandRank or hasOffHandEnchant ~= old_hasOffHandEnchant or (offHandExpiration or 0) > (old_offHandExpiration or 0) or offHandCharges ~= old_offHandCharges or offHandName ~= old_offHandName or offHandRank ~= old_offHandRank then self:ScanData_TENCH() old_hasMainHandEnchant = hasMainHandEnchant old_mainHandCharges = mainHandCharges old_mainHandName = mainHandName old_mainHandRank = mainHandRank old_hasOffHandEnchant = hasOffHandEnchant old_offHandCharges = offHandCharges old_offHandName = offHandName old_offHandRank = offHandRank else for k, v in pairs(self.tenchdata) do if v.id == INVENTORYSLOT_MAINHAND then v.timeleft = mainHandExpiration / 1000 end if v.id == INVENTORYSLOT_SECONDARYHAND then v.timeleft = offHandExpiration / 1000 end end end old_mainHandExpiration = mainHandExpiration old_offHandExpiration = offHandExpiration self:UpdateTimes("focus") self:UpdateTimes("pet") self:UpdateTimes("target") -- if we did a scan, update bar data if next(scan_happend) then for k, v in pairs(self.bargroups) do v:UpdateData(scan_happend) end for k in pairs(scan_happend) do scan_happend[k] = nil end else for k, v in pairs(self.bargroups) do v:UpdateTimeleft() end end end function ElkBuffBars:StickGroup(bargroup) local layout = bargroup.layout local id = layout.id local growup = layout.growup local container = bargroup:GetContainer() local base_y = growup and container:GetBottom() or container:GetTop() local base_left = container:GetLeft() local base_right = container:GetRight() layout.stickto = nil -- self:Print("Sticking bargroup", id) for k, v in pairs(self.bargroups) do local comp_container = v:GetContainer() local comp_y = growup and comp_container:GetTop() or comp_container:GetBottom() if math_abs(comp_y - base_y) < STICKTO_AREA then -- we are on the same y-area local comp_left = comp_container:GetLeft() local comp_right = comp_container:GetRight() local dist_left = math_abs(base_left - comp_left) local dist_mid = math_abs((base_left + base_right) - (comp_left + comp_right)) / 2 local dist_right = math_abs(base_right - comp_right) if dist_left <= STICKTO_AREA or dist_mid <= STICKTO_AREA or dist_right <= STICKTO_AREA then -- self:Print(" - sticking to bargroup ", k) -- we are also on the same x-area -- check if we would loop-stick to ourself local parent = v local hasloop = false while parent.layout.stickto do if parent.layout.stickto == id then -- self:Print(" - LOOP FOUND!") hasloop = true break end parent = self.bargroups[parent.layout.stickto] end if not hasloop then -- we have found a valid group to stick to layout.stickto = k local stickdist = STICKTO_AREA if dist_mid <= STICKTO_AREA then --~ self:Print(" - SUCCESS! -> middle") layout.stickside = "" stickdist = dist_mid end if dist_left <= STICKTO_AREA and dist_left < stickdist then --~ self:Print(" - SUCCESS! -> left") layout.stickside = "LEFT" stickdist = dist_left end if dist_right <= STICKTO_AREA and dist_right < stickdist then --~ self:Print(" - SUCCESS! -> right") layout.stickside = "RIGHT" stickdist = dist_right --~ else --~ self:Print(" - |cffff0000ERROR|r") end bargroup:SetPosition() return true end end end end return false end -- ----- -- FuBar stuff -- ----- ElkBuffBars.hasIcon = true -- icon by Jakobud @ wowace forums ElkBuffBars.hasNoColor = true ElkBuffBars.clickableTooltip = true ElkBuffBars.hideWithoutStandby = true ElkBuffBars.independentProfile = true ElkBuffBars.cannotDetachTooltip = true function ElkBuffBars:OnTextUpdate() self:SetText("ElkBuffBars") end function ElkBuffBars:OnTooltipUpdate() local cat = tablet:AddCategory( 'columns', 2, 'text', L["bargroup"], 'text2', L["type"], 'hideBlankLine', true, 'showWithoutChildren', true ) for k, v in ipairs(self.bargroups) do cat:AddLine( "text", tostring(k)..". "..(v.layout.anchortext or "???"), "text2", v.layout.target, "hasCheck", true, "checked", v.layout.anchorshown, "func", "ToggleAnchor", "arg1", v ) end end -- ----- -- AceOption table -- ----- AO_buffsettings = { type = "group", name = L["Buffs Settings"], desc = L["Change name and type for known buffs"], args = { BUFF = { type = "group", name = "BUFF", desc = "BUFF", args = {}, }, DEBUFF = { type = "group", name = "DEBUFF", desc = "DEBUFF", args = {}, }, TENCH = { type = "group", name = "TENCH", desc = "TENCH", args = {}, }, TRACKING = { type = "group", name = "TRACKING", desc = "TRACKING", args = {}, }, }, order = 101, } AO_groupsettings = {} AO_allopts = { type = "group", args = { buffsettings = AO_buffsettings, groupsettings = { type = "group", name = L["Group Settings"], desc = L["Changes the settings for the bargroups"], args = AO_groupsettings, order = 102, }, newgroup = { type = "execute", name = L["New Group"], desc = L["Creates a new bargroup"], func = function() local bg = ElkBuffBars:AddBarGroup() bg:SetPosition() bg:GetContainer():Show() end, order = 103, }, groupspacing = { type = "range", name = L["Group Spacing"], desc = L["Sets gap between anchored groups"], min = 0, max = 50, step = 1, get = function() return ElkBuffBars.db.profile.groupspacing end, set = function(v) ElkBuffBars.db.profile.groupspacing = tonumber(v) for k, bg in ipairs(ElkBuffBars.bargroups) do bg:SetPosition() end end, order = 104, }, buffframe = { type = "toggle", name = L["Hide Blizzard Buff Frame"], desc = L["Toggles active hiding of the Blizzard buff frame"], get = function() return ElkBuffBars.db.profile.hidebuffframe end, set = function(v) ElkBuffBars.db.profile.hidebuffframe = v ElkBuffBars:HandleFrame_Blizzard_BuffFrame(ElkBuffBars.db.profile.hidebuffframe) end, order = 105, }, tenchframe = { type = "toggle", name = L["Hide Blizzard TEnch Frame"], desc = L["Toggles active hiding of the Blizzard tench frame"], get = function() return ElkBuffBars.db.profile.hidetenchframe end, set = function(v) ElkBuffBars.db.profile.hidetenchframe = v ElkBuffBars:HandleFrame_Blizzard_TemporaryEnchantFrame(ElkBuffBars.db.profile.hidetenchframe) end, order = 105, }, trackingframe = { type = "toggle", name = L["Hide Minimap Tracking Frame"], desc = L["Toggles active hiding of the minimap tracking frame"], get = function() return ElkBuffBars.db.profile.hidetrackingframe end, set = function(v) ElkBuffBars.db.profile.hidetrackingframe = v ElkBuffBars:HandleFrame_Blizzard_MiniMapTracking(ElkBuffBars.db.profile.hidetrackingframe) end, order = 105, }, shiftannounce = { type = "toggle", name = L["Shift-click to announce"], desc = L["Toggles shift-click announcing of buffs to party"], get = function() return ElkBuffBars.db.profile.shiftannounce end, set = function(v) ElkBuffBars.db.profile.shiftannounce = v end, order = 106, }, announceoutofparty = { type = "toggle", name = L["Announce in /say"], desc = L["Toggles announcement of buffs in /say when not in a party"], get = function() return ElkBuffBars.db.profile.announceoutofparty end, set = function(v) ElkBuffBars.db.profile.announceoutofparty = v end, order = 107, }, } } local typeoverride_validate = {BUFF = "BUFF", DEBUFF = "DEBUFF", TENCH = "TENCH", TRACKING = "TRACKING", [""] = L["default"]} function ElkBuffBars:GetNameOptions(type, name) return { type = "group", name = name, desc = name, args = { name = { type = "text", name = L["Shown Name"], desc = L["Sets the name to show"], usage = "none", get = function() return ElkBuffBars.db.profile.nameoverride[type][name] or "" end, set = function(v) ElkBuffBars.db.profile.nameoverride[type][name] = v ~= "" and v or nil end, }, type = { type = "text", name = L["New Type"], desc = L["Sets the new type"], get = function() return ElkBuffBars.db.profile.typeoverride[type][name] or "" end, set = function(v) ElkBuffBars.db.profile.typeoverride[type][name] = (v ~= "" and v ~= type) and v or nil end, validate = typeoverride_validate, } } } end local function SetNameFilter(groupid, white, type, name, value) local bg = ElkBuffBars.bargroups[groupid] local filter = bg.layout.filter local ftname = white and "names_include" or "names_exclude" if value then if not filter[ftname] then filter[ftname] = {} end if not filter[ftname][type] then filter[ftname][type] = {} end filter[ftname][type][name] = true elseif filter[ftname] and filter[ftname][type] then filter[ftname][type][name] = nil local hasdata = false for _ in pairs(filter[ftname][type]) do hasdata = true break end if not hasdata then filter[ftname][type] = nil end hasdata = false for _ in pairs(filter[ftname]) do hasdata = true break end if not hasdata then filter[ftname] = nil end end bg:UpdateData() end local groupoptionscache = {} function ElkBuffBars:GetGroupOptions(id) if not groupoptionscache[id] then groupoptionscache[id] = { type = "group", name = (L["Group %d"]):format(id), desc = (L["Settings for Group %d"]):format(id), args = { anchorshown = { type = "toggle", name = L["Show Anchor"], desc = L["Toggles Anchor"], get = function() return ElkBuffBars.db.profile.bargroups[id].anchorshown end, set = function() ElkBuffBars.bargroups[id]:ToggleAnchor() end, order = 101, }, anchortext = { type = "text", name = L["Name"], desc = L["Sets the group's name"], usage = "", get = function() return ElkBuffBars.db.profile.bargroups[id].anchortext end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.anchortext = v if bg.layout.anchorshown then bg:ToggleAnchor(true) end end, order = 102, }, bars = { type = "group", name = L["Bar Layout"], desc = L["Sets the layout for this group's bars"], args = { bar = { type = "group", name = L["Bar"], desc = L["Settings for the statusbar"], args = { bar = { type = "toggle", name = L["Show Statusbar"], desc = L["Toggles display of the statusbar"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bar end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.bar = v bg:SetLayout() end, order = 101, }, bartexture = { type = "text", name = L["Bar Texture"], desc = L["Sets the bar texture"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bartexture end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.bartexture = v bg:SetLayout() end, validate = LSM3_statusbar, order = 102, }, barcolor = { type = "color", name = L["Bar Color"], desc = L["Sets the color for the bar"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.barcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.barcolor[1] = r bg.layout.bars.barcolor[2] = g bg.layout.bars.barcolor[3] = b bg.layout.bars.barcolor[4] = a bg:SetLayout() if bg.layout.anchorshown then bg:ToggleAnchor(true) end end, hasAlpha = true, order = 103, }, -- bgbar = { type = "toggle", name = L["Show Background"], desc = L["Toggles display of the bar background"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.bgbar end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.bgbar = v bg:SetLayout() end, order = 104, }, barbgcolor = { type = "color", name = L["Background Color"], desc = L["Sets the color for the bar's background"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.barbgcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.barbgcolor[1] = r bg.layout.bars.barbgcolor[2] = g bg.layout.bars.barbgcolor[3] = b bg.layout.bars.barbgcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 105, }, -- debufftypecolor = { type = "toggle", name = L["Debuff Coloring"], desc = L["Toggles if the bar is colored by debuff type"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.debufftypecolor end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.debufftypecolor = v bg:UpdateBars() end, order = 106, }, barright = { type = "toggle", name = L["Bar Direction LTR"], desc = L["Toggles if the bar depletes from left to right"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.barright end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.barright = v bg:SetLayout() end, order = 107, }, timelessfull = { type = "toggle", name = L["Full bars for timeless"], desc = L["Toggles full bars for timeless buffs"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.timelessfull end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.timelessfull = v bg:UpdateData() end, order = 108, }, }, order = 101, }, icon = { type = "group", name = L["Icon"], desc = L["Settings for the icon"], args = { icon = { type = "text", name = L["Position"], desc = L["Sets icon showing"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.icon or "false" end, set = function(v) if v == "false" then v = false end local bg = ElkBuffBars.bargroups[id] bg.layout.bars.icon = v bg:SetLayout() end, validate = {["false"] = L["hide"], ["LEFT"] = "Left Side", ["RIGHT"] = "Right Side"}, order = 101, }, -- "LEFT", "RIGHT", false iconcount = { type = "toggle", name = L["Buff Stacks - Show"], desc = L["Toggles showing of buff stacks on the icon"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcount end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.iconcount = v bg:SetLayout() end, order = 102, }, -- true, false iconcountanchor = { type = "text", name = L["Buff Stacks - Anchor"], desc = L["Sets the anchor for the buff stacks on the icon"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountanchor end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.iconcountanchor = v bg:SetLayout() end, validate = {"TOPLEFT", "TOP", "TOPRIGHT", "LEFT", "CENTER", "RIGHT", "BOTTOMLEFT", "BOTTOM", "BOTTOMRIGHT"}, order = 103, }, -- iconcountfont = { type = "text", name = L["Buff Stacks - Font"], desc = L["Sets the font for the buff stacks on the icon"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountfont end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.iconcountfont = v bg:SetLayout() end, validate = LSM3_font, order = 104 }, -- iconcountfontsize = { type = "range", name = L["Buff Stacks - Font Size"], desc = L["Sets the font size for the buff stacks on the icon"], min = 4, max = 32, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.iconcountfontsize end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.iconcountfontsize = tonumber(v) bg:SetLayout() end, order = 105, }, -- iconcountcolor = { type = "color", name = L["Buff Stacks - Font Color"], desc = L["Sets the font color for the buff stacks on the icon"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.iconcountcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.iconcountcolor[1] = r bg.layout.bars.iconcountcolor[2] = g bg.layout.bars.iconcountcolor[3] = b bg.layout.bars.iconcountcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 106, }, -- }, order = 102 }, texttl = { type = "group", name = L["Text topleft"], desc = L["Settings for the topleft text"], args = { textTL = { type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTL or "false" end, set = function(v) if v == "false" then v = false end local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTL = v bg:SetLayout() end, validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]}, order = 101, }, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" textTLfont = { type = "text", name = L["Font"], desc = L["Sets the font"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLfont end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTLfont = v bg:SetLayout() end, validate = LSM3_font, order = 102, }, -- textTLfontsize = { type = "range", name = L["Font Size"], desc = L["Sets the font size"], min = 4, max = 32, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLfontsize end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTLfontsize = tonumber(v) bg:SetLayout() end, order = 102, }, -- textTLcolor = { type = "color", name = L["Font Color"], desc = L["Sets the font color"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textTLcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTLcolor[1] = r bg.layout.bars.textTLcolor[2] = g bg.layout.bars.textTLcolor[3] = b bg.layout.bars.textTLcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 103, }, -- textTLalign = { type = "text", name = L["Alignment"], desc = L["Sets the text alignment (only if topleft text hidden)"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTLalign end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTLalign = v bg:SetLayout() end, validate = {"left", "center", "right"}, order = 104 }, -- left, center, right }, order = 103, }, texttr = { type = "group", name = L["Text topright"], desc = L["Settings for the topright text"], args = { textTR = { type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTR or "false" end, set = function(v) if v == "false" then v = false end local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTR = v bg:SetLayout() end, validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]}, order = 101, }, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" textTRfont = { type = "text", name = L["Font"], desc = L["Sets the font"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTRfont end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTRfont = v bg:SetLayout() end, validate = LSM3_font, order = 102, }, -- textTRfontsize = { type = "range", name = L["Font Size"], desc = L["Sets the font size"], min = 4, max = 32, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textTRfontsize end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTRfontsize = tonumber(v) bg:SetLayout() end, order = 103, }, -- textTRcolor = { type = "color", name = L["Font Color"], desc = L["Sets the font color"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textTRcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textTRcolor[1] = r bg.layout.bars.textTRcolor[2] = g bg.layout.bars.textTRcolor[3] = b bg.layout.bars.textTRcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 104, }, -- }, order = 104, }, textbl = { type = "group", name = L["Text bottomleft"], desc = L["Settings for the bottomleft text"], args = { textBL = { type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBL or "false" end, set = function(v) if v == "false" then v = false end local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBL = v bg:SetLayout() end, validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]}, order = 101, }, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" textBLfont = { type = "text", name = L["Font"], desc = L["Sets the font"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLfont end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBLfont = v bg:SetLayout() end, validate = LSM3_font, order = 102, }, -- textBLfontsize = { type = "range", name = L["Font Size"], desc = L["Sets the font size"], min = 4, max = 32, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLfontsize end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBLfontsize = tonumber(v) bg:SetLayout() end, order = 103, }, -- textBLcolor = { type = "color", name = L["Font Color"], desc = L["Sets the font color"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textBLcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBLcolor[1] = r bg.layout.bars.textBLcolor[2] = g bg.layout.bars.textBLcolor[3] = b bg.layout.bars.textBLcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 104, }, -- textBLalign = { type = "text", name = L["Alignment"], desc = L["Sets the text alignment (only if bottomleft text hidden)"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBLalign end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBLalign = v bg:SetLayout() end, validate = {"left", "center", "right"}, order = 105, }, -- left, center, right }, order = 105, }, textbr = { type = "group", name = L["Text bottomright"], desc = L["Settings for the bottomright text"], args = { textBR = { type = "text", name = L["Text shown"], desc = L["Sets the text which is shown"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBR or "false" end, set = function(v) if v == "false" then v = false end local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBR = v bg:SetLayout() end, validate = {["false"] = L["hide"], ["NAME"] = L["Name"], ["NAMERANK"] = L["Name, Rank"], ["NAMECOUNT"] = L["Name, Count"], ["NAMERANKCOUNT"] = L["Name, Rank, Count"], ["RANK"] = L["Rank"], ["COUNT"] = L["Count"], ["TIMELEFT"] = L["Time Left"], ["DEBUFFTYPE"] = L["Debuff Type"]}, order = 101, }, -- false, "NAME", "NAMERANK", "NAMECOUNT", "NAMERANKCOUNT", "RANK", "COUNT", "TIMELEFT", "DEBUFFTYPE" textBRfont = { type = "text", name = L["Font"], desc = L["Sets the font"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBRfont end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBRfont = v bg:SetLayout() end, validate = LSM3_font, order = 102, }, -- textBRfontsize = { type = "range", name = L["Font Size"], desc = L["Sets the font size"], min = 4, max = 32, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.textBRfontsize end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBRfontsize = tonumber(v) bg:SetLayout() end, order = 103, }, -- textBRcolor = { type = "color", name = L["Font Color"], desc = L["Sets the font color"], get = function() return unpack(ElkBuffBars.db.profile.bargroups[id].bars.textBRcolor) end, set = function(r, g, b, a) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.textBRcolor[1] = r bg.layout.bars.textBRcolor[2] = g bg.layout.bars.textBRcolor[3] = b bg.layout.bars.textBRcolor[4] = a bg:SetLayout() end, hasAlpha = true, order = 104, }, -- }, order = 106, }, abbreviate_name = { type = "range", name = L["Abbreviate Name"], desc = L["Abbreviate names longer than this (0 = disabled)"], min = 0, max = 100, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.abbreviate_name end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.abbreviate_name = tonumber(v) bg:UpdateText() end, order = 107, }, timeformat = { type = "text", name = L["Time Format"], desc = L["Sets the format the time is shown in"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.timeformat end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.timeformat = v bg:UpdateTimeleft() end, validate = {"DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED"}, order = 108, }, -- "DEFAULT", "EXTENDED", "FULL", "SHORT", "CONDENSED" padding = { type = "range", name = L["Padding"], desc = L["Sets the padding for the text strings"], min = 0, max = 10, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.padding end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.padding = tonumber(v) bg:SetLayout() end, order = 109, }, tooltipanchor = { type = "text", name = L["Tooltip Anchor"], desc = L["Sets the anchor for tooltips"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.tooltipanchor end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.tooltipanchor = v end, validate = {"default", "ANCHOR_TOPRIGHT", "ANCHOR_RIGHT","ANCHOR_BOTTOMRIGHT", "ANCHOR_TOPLEFT", "ANCHOR_LEFT", "ANCHOR_BOTTOMLEFT", "ANCHOR_CURSOR", "ANCHOR_PRESERVE", "ANCHOR_NONE"}, order = 110, }, height = { type = "range", name = L["Height"], desc = L["Sets the bar hight"], min = 0, max = 100, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.height end, set = function(v) local bg = ElkBuffBars.bargroups[id] local blayout = bg.layout.bars blayout.height = tonumber(v) if blayout.height > blayout.width then blayout.height = blayout.width end bg:SetLayout() bg:UpdateBarPositions() end, order = 111, }, width = { type = "range", name = L["Width"], desc = L["Sets the bar Width"], min = 0, max = 500, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.width end, set = function(v) local bg = ElkBuffBars.bargroups[id] local blayout = bg.layout.bars blayout.width = tonumber(v) if blayout.width < blayout.height then blayout.width = blayout.height end bg:SetLayout() if bg.layout.anchorshown then bg:ToggleAnchor(true) else bg:UpdateBarPositions() end end, order = 112, }, alpha = { type = "range", name = L["Alpha"], desc = L["Sets the groups alpha value"], isPercent = true, get = function() return ElkBuffBars.db.profile.bargroups[id].bars.alpha end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.alpha = tonumber(v) bg:SetLayout() end, order = 113, }, }, order = 103, }, barspacing = { type = "range", name = L["Bar Spacing"], desc = L["Sets gap between bars"], min = 0, max = 50, step = 1, get = function() return ElkBuffBars.db.profile.bargroups[id].barspacing end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.barspacing = tonumber(v) bg:UpdateBarPositions() end, order = 104, }, growup = { type = "toggle", name = L["Grow up"], desc = L["Toggles direction of buffs"], get = function() return ElkBuffBars.db.profile.bargroups[id].growup end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.growup = v bg.layout.stickto = nil bg.layout.stickside = nil bg:SetLayout() bg:SetPosition() end, order = 105, }, sorting = { type = "text", name = L["Sorting"], desc = L["Sets sorting of buffs"], get = function() return ElkBuffBars.db.profile.bargroups[id].sorting end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.sorting = v bg:UpdateData() end, validate = {"name", "none", "timeleft", "timemax"}, order = 106, }, filter = { type = "group", name = L["Filter"], desc = L["Sets the buffs to show"], args = { type = { type = "text", name = L["Type"], desc = L["Sets which types of buffs to show"], get = function(k) return ElkBuffBars.db.profile.bargroups[id].filter.type[k] or false end, set = function(k, v) local bg = ElkBuffBars.bargroups[id] bg.layout.filter.type[k] = v or nil bg:UpdateData() end, multiToggle = true, validate = {"BUFF", "DEBUFF", "TENCH", "TRACKING"}, order = 101, }, untilcancelled = { type = "text", name = L["Timeless Buffs"], desc = L["Sets if and how to filter Timeless Buffs"], get = function() return ElkBuffBars.db.profile.bargroups[id].filter.untilcancelled or "none" end, set = function(v) local bg = ElkBuffBars.bargroups[id] if v == "none" then v = nil end bg.layout.filter.untilcancelled = v bg:UpdateData() end, validate = {only = L["whitelist"], none = L["don't filter"], hide = L["blacklist"]}, order = 102, }, timemax_min = { type = "text", name = L["Min. Timemax"], desc = L["Sets a minimum duration for buffs to show."], usage = L["time in seconds"], get = function() return ElkBuffBars.db.profile.bargroups[id].filter.timemax_min or "" end, set = function(v) v = tonumber(v) local bg = ElkBuffBars.bargroups[id] bg.layout.filter.timemax_min = (v ~= 0) and v or nil bg:UpdateData() end, order = 103, }, timemax_max = { type = "text", name = L["Max. Timemax"], desc = L["Sets a maximum duration for buffs to show."], usage = L["time in seconds"], get = function() return ElkBuffBars.db.profile.bargroups[id].filter.timemax_max or "" end, set = function(v) v = tonumber(v) local bg = ElkBuffBars.bargroups[id] bg.layout.filter.timemax_max = (v ~= 0) and v or nil bg:UpdateData() end, order = 104, }, names_include = { type = "group", name = L["White List"], desc = L["Only show buffs on white list (disabled if empty)"], args = { BUFF = { type = "text", name = "BUFF", desc = "BUFF", get = function(k) local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include return ni and ni.BUFF and ni.BUFF[k] or false end, set = function(name, value) SetNameFilter(id, true, "BUFF", name, value) end, multiToggle = true, validate = knownnames_validate.BUFF, }, DEBUFF = { type = "text", name = "DEBUFF", desc = "DEBUFF", get = function(k) local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include return ni and ni.DEBUFF and ni.DEBUFF[k] or false end, set = function(name, value) SetNameFilter(id, true, "DEBUFF", name, value) end, multiToggle = true, validate = knownnames_validate.DEBUFF, }, TENCH = { type = "text", name = "TENCH", desc = "TENCH", get = function(k) local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include return ni and ni.TENCH and ni.TENCH[k] or false end, set = function(name, value) SetNameFilter(id, true, "TENCH", name, value) end, multiToggle = true, validate = knownnames_validate.TENCH, }, TRACKING = { type = "text", name = "TRACKING", desc = "TRACKING", get = function(k) local ni = ElkBuffBars.db.profile.bargroups[id].filter.names_include return ni and ni.TRACKING and ni.TRACKING[k] or false end, set = function(name, value) SetNameFilter(id, true, "TRACKING", name, value) end, multiToggle = true, validate = knownnames_validate.TRACKING, }, }, order = 105, }, names_exclude = { type = "group", name = L["Black List"], desc = L["Don't show buffs on black list"], args = { BUFF = { type = "text", name = "BUFF", desc = "BUFF", get = function(k) local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude return ne and ne.BUFF and ne.BUFF[k] or false end, set = function(name, value) SetNameFilter(id, false, "BUFF", name, value) end, multiToggle = true, validate = knownnames_validate.BUFF, }, DEBUFF = { type = "text", name = "DEBUFF", desc = "DEBUFF", get = function(k) local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude return ne and ne.DEBUFF and ne.DEBUFF[k] or false end, set = function(name, value) SetNameFilter(id, false, "DEBUFF", name, value) end, multiToggle = true, validate = knownnames_validate.DEBUFF, }, TENCH = { type = "text", name = "TENCH", desc = "TENCH", get = function(k) local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude return ne and ne.TENCH and ne.TENCH[k] or false end, set = function(name, value) SetNameFilter(id, false, "TENCH", name, value) end, multiToggle = true, validate = knownnames_validate.TENCH, }, TRACKING = { type = "text", name = "TRACKING", desc = "TRACKING", get = function(k) local ne = ElkBuffBars.db.profile.bargroups[id].filter.names_exclude return ne and ne.TRACKING and ne.TRACKING[k] or false end, set = function(name, value) SetNameFilter(id, false, "TRACKING", name, value) end, multiToggle = true, validate = knownnames_validate.TRACKING, }, }, order = 106, }, }, order = 107, }, target = { type = "text", name = L["Target"], desc = L["Sets whos buffs to show"], get = function() return ElkBuffBars.db.profile.bargroups[id].target end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.target = v bg:UpdateData() end, validate = {"focus", "pet", "player", "target"}, order = 108, }, clickthrough = { type = "toggle", name = L["Disable Mouse"], desc = L["Disable mouse input to allow click-through"], get = function() return ElkBuffBars.db.profile.bargroups[id].bars.clickthrough end, set = function(v) local bg = ElkBuffBars.bargroups[id] bg.layout.bars.clickthrough = v bg:SetLayout() end, order = 109, }, copylayout = { type = "text", name = L["Copy Layout"], desc = L["Copys the layout from another bargroup"], usage = L["group id of the layout"], get = false, set = function(v) v = tonumber(v) if v ~= id and ElkBuffBars.bargroups[v] then ElkBuffBars:CopyBarLayout(ElkBuffBars.bargroups[id].layout, ElkBuffBars.bargroups[v].layout) end end, order = 110, }, resetpos = { type = "execute", name = L["Reset Position"], desc = L["Resets the bargroup's position to screen center"], func = function() local bg = ElkBuffBars.bargroups[id] bg.layout.x = nil bg.layout.y = nil bg.stickto = nil bg.stickside = nil bg:SetPosition() end, order = 111, }, remove = { type = "execute", name = L["Remove Group"], desc = L["Removes the bargroup"], func = function() Dewdrop:Close() ElkBuffBars:RemoveBarGroup(id) end, order = 112, }, } } end return groupoptionscache[id] end function ElkBuffBars:ShowDewdrop() Dewdrop:Open(UIParent, "children", AO_allopts, "cursorX", true, "cursorY", true) end ElkBuffBars:RegisterChatCommand({"/ebb"}, { type = "group", args = { config = { type = "execute", name = "config", desc = L["Shows the config menu"], func = function() ElkBuffBars:ShowDewdrop() end, } } }) ElkBuffBars.OnMenuRequest = AO_allopts