1234 lines
35 KiB
Lua
1234 lines
35 KiB
Lua
local ElvUI = select(2, ...)
|
|
|
|
local gameLocale
|
|
do -- Locale doesn't exist yet, make it exist.
|
|
local convert = {["enGB"] = "enUS", ["esES"] = "esMX", ["itIT"] = "enUS"}
|
|
local lang = GetLocale()
|
|
|
|
gameLocale = convert[lang] or lang or "enUS"
|
|
ElvUI[2] = ElvUI[1].Libs.ACL:GetLocale("ElvUI", gameLocale)
|
|
end
|
|
|
|
local E, L, V, P, G = unpack(ElvUI); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
|
|
|
|
local ActionBars = E:GetModule("ActionBars")
|
|
local AFK = E:GetModule("AFK")
|
|
local Auras = E:GetModule("Auras")
|
|
local Bags = E:GetModule("Bags")
|
|
local Blizzard = E:GetModule("Blizzard")
|
|
local Chat = E:GetModule("Chat")
|
|
local DataBars = E:GetModule("DataBars")
|
|
local DataTexts = E:GetModule("DataTexts")
|
|
local Layout = E:GetModule("Layout")
|
|
local Minimap = E:GetModule("Minimap")
|
|
local NamePlates = E:GetModule("NamePlates")
|
|
local Threat = E:GetModule("Threat")
|
|
local Tooltip = E:GetModule("Tooltip")
|
|
local Totems = E:GetModule("Totems")
|
|
local ReminderBuffs = E:GetModule("ReminderBuffs")
|
|
local UnitFrames = E:GetModule("UnitFrames")
|
|
|
|
local LSM = E.Libs.LSM
|
|
|
|
--Lua functions
|
|
local _G = _G
|
|
local tonumber, pairs, ipairs, error, unpack, select, tostring = tonumber, pairs, ipairs, error, unpack, select, tostring
|
|
local assert, type, print = assert, type, print
|
|
local twipe, tinsert, tremove, next = table.wipe, tinsert, tremove, next
|
|
local format, find, match, strrep, strlen, sub, gsub, strjoin = string.format, string.find, string.match, strrep, strlen, string.sub, string.gsub, strjoin
|
|
--WoW API / Variables
|
|
local CreateFrame = CreateFrame
|
|
local GetAddOnInfo = GetAddOnInfo
|
|
local GetCVar = GetCVar
|
|
local GetNumPartyMembers = GetNumPartyMembers
|
|
local GetNumRaidMembers = GetNumRaidMembers
|
|
local InCombatLockdown = InCombatLockdown
|
|
local IsInGuild = IsInGuild
|
|
local IsInInstance = IsInInstance
|
|
local SendAddonMessage = SendAddonMessage
|
|
local UnitGUID = UnitGUID
|
|
local ERR_NOT_IN_COMBAT = ERR_NOT_IN_COMBAT
|
|
|
|
--Constants
|
|
E.noop = function() end
|
|
E.title = format("|cff1784d1E|r|cffe5e3e3lvUI|r")
|
|
E.myfaction, E.myLocalizedFaction = UnitFactionGroup("player")
|
|
E.mylevel = UnitLevel("player")
|
|
E.myLocalizedClass, E.myclass = UnitClass("player") -- On Ascension, this is always (Hero, HERO)
|
|
E.myLocalizedRace, E.myrace = UnitRace("player")
|
|
E.myname = UnitName("player")
|
|
E.myrealm = GetRealmName()
|
|
E.mynameRealm = format('%s - %s', E.myname, E.myrealm) -- contains spaces/dashes in realm (for profile keys)
|
|
E.version = GetAddOnMetadata("ElvUI", "Version")
|
|
E.versionNum = tonumber(E.version)
|
|
E.wowpatch, E.wowbuild = GetBuildInfo()
|
|
E.wowbuild = tonumber(E.wowbuild)
|
|
E.resolution = GetCVar("gxResolution")
|
|
E.screenwidth, E.screenheight = tonumber(match(E.resolution, "(%d+)x+%d")), tonumber(match(E.resolution, "%d+x(%d+)"))
|
|
E.isMacClient = IsMacClient()
|
|
E.NewSign = "|TInterface\\OptionsFrame\\UI-OptionsFrame-NewFeatureIcon:14:14|t"
|
|
E.InfoColor = "|cfffe7b2c"
|
|
|
|
--Tables
|
|
E.media = {}
|
|
E.frames = {}
|
|
E.unitFrameElements = {}
|
|
E.statusBars = {}
|
|
E.texts = {}
|
|
E.snapBars = {}
|
|
E.RegisteredModules = {}
|
|
E.RegisteredInitialModules = {}
|
|
E.ModuleCallbacks = {["CallPriority"] = {}}
|
|
E.InitialModuleCallbacks = {["CallPriority"] = {}}
|
|
E.valueColorUpdateFuncs = {}
|
|
E.TexCoords = {0, 1, 0, 1}
|
|
E.VehicleLocks = {}
|
|
E.CreditsList = {}
|
|
|
|
E.InversePoints = {
|
|
TOP = "BOTTOM",
|
|
BOTTOM = "TOP",
|
|
TOPLEFT = "BOTTOMLEFT",
|
|
TOPRIGHT = "BOTTOMRIGHT",
|
|
LEFT = "RIGHT",
|
|
RIGHT = "LEFT",
|
|
BOTTOMLEFT = "TOPLEFT",
|
|
BOTTOMRIGHT = "TOPRIGHT",
|
|
CENTER = "CENTER"
|
|
}
|
|
|
|
local colorizedName
|
|
function E:ColorizedName(name, arg2)
|
|
local length = strlen(name)
|
|
for i = 1, length do
|
|
local letter = sub(name, i, i)
|
|
if i == 1 then
|
|
colorizedName = format("|cff1784d1%s", letter)
|
|
elseif i == 2 then
|
|
colorizedName = format("%s|r|cffe5e3e3%s", colorizedName, letter)
|
|
elseif i == length and arg2 then
|
|
colorizedName = format("%s%s|r|cff1784d1:|r", colorizedName, letter)
|
|
else
|
|
colorizedName = colorizedName..letter
|
|
end
|
|
end
|
|
return colorizedName
|
|
end
|
|
|
|
--This frame everything in ElvUI should be anchored to for Eyefinity support.
|
|
E.UIParent = CreateFrame("Frame", "ElvUIParent", UIParent)
|
|
E.UIParent:SetFrameLevel(UIParent:GetFrameLevel())
|
|
E.UIParent:SetSize(UIParent:GetSize())
|
|
E.UIParent:SetPoint("CENTER", UIParent, "CENTER")
|
|
E.snapBars[#E.snapBars + 1] = E.UIParent
|
|
|
|
E.HiddenFrame = CreateFrame("Frame")
|
|
E.HiddenFrame:Hide()
|
|
|
|
do -- used in optionsUI
|
|
E.DEFAULT_FILTER = {}
|
|
for filter, tbl in pairs(G.unitframe.aurafilters) do
|
|
E.DEFAULT_FILTER[filter] = tbl.type
|
|
end
|
|
end
|
|
|
|
function E:Print(...)
|
|
(_G[self.db.general.messageRedirect] or DEFAULT_CHAT_FRAME):AddMessage(strjoin(" ", self:ColorizedName("ElvUI", true), ...)) -- I put DEFAULT_CHAT_FRAME as a fail safe.
|
|
end
|
|
|
|
local delayedTimer
|
|
local delayedFuncs = {}
|
|
function E:ShapeshiftDelayedUpdate(func, ...)
|
|
delayedFuncs[func] = {...}
|
|
|
|
if delayedTimer then return end
|
|
|
|
delayedTimer = E:ScheduleTimer(function()
|
|
for f in pairs(delayedFuncs) do
|
|
f(unpack(delayedFuncs[f]))
|
|
end
|
|
|
|
twipe(delayedFuncs)
|
|
delayedTimer = nil
|
|
end, 0.05)
|
|
end
|
|
|
|
function E:GrabColorPickerValues(r, g, b)
|
|
-- we must block the execution path to `ColorCallback` in `AceGUIWidget-ColorPicker-ElvUI`
|
|
-- in order to prevent an infinite loop from `OnValueChanged` when passing into `E.UpdateMedia` which eventually leads here again.
|
|
ColorPickerFrame.noColorCallback = true
|
|
|
|
-- grab old values
|
|
local oldR, oldG, oldB = ColorPickerFrame:GetColorRGB()
|
|
|
|
-- set and define the new values
|
|
ColorPickerFrame:SetColorRGB(r, g, b)
|
|
r, g, b = ColorPickerFrame:GetColorRGB()
|
|
|
|
-- swap back to the old values
|
|
if oldR then ColorPickerFrame:SetColorRGB(oldR, oldG, oldB) end
|
|
|
|
-- free it up..
|
|
ColorPickerFrame.noColorCallback = nil
|
|
|
|
return r, g, b
|
|
end
|
|
|
|
function E:SetColorTable(t, data)
|
|
if not data.r or not data.g or not data.b then
|
|
error("SetColorTable: Could not unpack color values.")
|
|
end
|
|
|
|
if t and (type(t) == "table") then
|
|
t[1], t[2], t[3], t[4] = E:UpdateColorTable(data)
|
|
else
|
|
t = E:GetColorTable(data)
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function E:UpdateColorTable(data)
|
|
if not data.r or not data.g or not data.b then
|
|
error("UpdateColorTable: Could not unpack color values.")
|
|
end
|
|
|
|
if (data.r > 1 or data.r < 0) then data.r = 1 end
|
|
if (data.g > 1 or data.g < 0) then data.g = 1 end
|
|
if (data.b > 1 or data.b < 0) then data.b = 1 end
|
|
if data.a and (data.a > 1 or data.a < 0) then data.a = 1 end
|
|
|
|
if data.a then
|
|
return data.r, data.g, data.b, data.a
|
|
else
|
|
return data.r, data.g, data.b
|
|
end
|
|
end
|
|
|
|
function E:GetColorTable(data)
|
|
if not data.r or not data.g or not data.b then
|
|
error("GetColorTable: Could not unpack color values.")
|
|
end
|
|
|
|
if (data.r > 1 or data.r < 0) then data.r = 1 end
|
|
if (data.g > 1 or data.g < 0) then data.g = 1 end
|
|
if (data.b > 1 or data.b < 0) then data.b = 1 end
|
|
if data.a and (data.a > 1 or data.a < 0) then data.a = 1 end
|
|
|
|
if data.a then
|
|
return {data.r, data.g, data.b, data.a}
|
|
else
|
|
return {data.r, data.g, data.b}
|
|
end
|
|
end
|
|
|
|
function E:UpdateMedia()
|
|
if not self.db.general or not self.private.general then return end --Prevent rare nil value errors
|
|
|
|
-- Fonts
|
|
self.media.normFont = LSM:Fetch("font", self.db.general.font)
|
|
self.media.combatFont = LSM:Fetch("font", self.private.general.dmgfont)
|
|
|
|
-- Textures
|
|
self.media.blankTex = LSM:Fetch("background", "ElvUI Blank")
|
|
self.media.normTex = LSM:Fetch("statusbar", self.private.general.normTex)
|
|
self.media.glossTex = LSM:Fetch("statusbar", self.private.general.glossTex)
|
|
|
|
-- Border Color
|
|
local border = E.db.general.bordercolor
|
|
self.media.bordercolor = {border.r, border.g, border.b}
|
|
|
|
-- UnitFrame Border Color
|
|
border = E.db.unitframe.colors.borderColor
|
|
self.media.unitframeBorderColor = {border.r, border.g, border.b}
|
|
|
|
-- Backdrop Color
|
|
self.media.backdropcolor = E:SetColorTable(self.media.backdropcolor, self.db.general.backdropcolor)
|
|
|
|
-- Backdrop Fade Color
|
|
self.media.backdropfadecolor = E:SetColorTable(self.media.backdropfadecolor, self.db.general.backdropfadecolor)
|
|
|
|
-- Value Color
|
|
local value = self.db.general.valuecolor
|
|
|
|
self.media.hexvaluecolor = self:RGBToHex(value.r, value.g, value.b)
|
|
self.media.rgbvaluecolor = {value.r, value.g, value.b}
|
|
|
|
-- Hero Color
|
|
local herocolor = E.db.general.herocolor
|
|
self.media.herocolor = herocolor
|
|
self.oUF.herocolor = {herocolor.r, herocolor.g, herocolor. b}
|
|
|
|
if LeftChatPanel and LeftChatPanel.tex and RightChatPanel and RightChatPanel.tex then
|
|
LeftChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameLeft)
|
|
local a = E.db.general.backdropfadecolor.a or 0.5
|
|
LeftChatPanel.tex:SetAlpha(a)
|
|
|
|
RightChatPanel.tex:SetTexture(E.db.chat.panelBackdropNameRight)
|
|
RightChatPanel.tex:SetAlpha(a)
|
|
end
|
|
|
|
self:ValueFuncCall()
|
|
self:UpdateBlizzardFonts()
|
|
end
|
|
|
|
do --Update font/texture paths when they are registered by the addon providing them
|
|
--This helps fix most of the issues with fonts or textures reverting to default because the addon providing them is loading after ElvUI.
|
|
--We use a wrapper to avoid errors in :UpdateMedia because "self" is passed to the function with a value other than ElvUI.
|
|
local function LSMCallback() E:UpdateMedia() end
|
|
LSM.RegisterCallback(E, "LibSharedMedia_Registered", LSMCallback)
|
|
end
|
|
|
|
function E:ValueFuncCall()
|
|
for func in pairs(self.valueColorUpdateFuncs) do
|
|
func(self.media.hexvaluecolor, unpack(self.media.rgbvaluecolor))
|
|
end
|
|
end
|
|
|
|
function E:UpdateFrameTemplates()
|
|
for frame in pairs(self.frames) do
|
|
if frame and frame.template and not frame.ignoreUpdates then
|
|
if not frame.ignoreFrameTemplates then
|
|
frame:SetTemplate(frame.template, frame.glossTex, nil, frame.forcePixelMode)
|
|
end
|
|
else
|
|
self.frames[frame] = nil
|
|
end
|
|
end
|
|
|
|
for frame in pairs(self.unitFrameElements) do
|
|
if frame and frame.template and not frame.ignoreUpdates then
|
|
if not frame.ignoreFrameTemplates then
|
|
frame:SetTemplate(frame.template, frame.glossTex, nil, frame.forcePixelMode, frame.isUnitFrameElement)
|
|
end
|
|
else
|
|
self.unitFrameElements[frame] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:UpdateBorderColors()
|
|
for frame in pairs(self.frames) do
|
|
if frame and not frame.ignoreUpdates then
|
|
if not frame.ignoreBorderColors then
|
|
if frame.template == "Default" or frame.template == "Transparent" or frame.template == nil then
|
|
frame:SetBackdropBorderColor(unpack(self.media.bordercolor))
|
|
end
|
|
end
|
|
else
|
|
self.frames[frame] = nil
|
|
end
|
|
end
|
|
|
|
for frame in pairs(self.unitFrameElements) do
|
|
if frame and not frame.ignoreUpdates then
|
|
if not frame.ignoreBorderColors then
|
|
if frame.template == "Default" or frame.template == "Transparent" or frame.template == nil then
|
|
frame:SetBackdropBorderColor(unpack(self.media.unitframeBorderColor))
|
|
end
|
|
end
|
|
else
|
|
self.unitFrameElements[frame] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:UpdateBackdropColors()
|
|
for frame in pairs(self.frames) do
|
|
if frame and not frame.ignoreUpdates then
|
|
if not frame.ignoreBackdropColors then
|
|
if frame.template == "Default" or frame.template == nil then
|
|
frame:SetBackdropColor(unpack(self.media.backdropcolor))
|
|
elseif frame.template == "Transparent" then
|
|
frame:SetBackdropColor(unpack(self.media.backdropfadecolor))
|
|
end
|
|
end
|
|
else
|
|
self.frames[frame] = nil
|
|
end
|
|
end
|
|
|
|
for frame in pairs(self.unitFrameElements) do
|
|
if frame and not frame.ignoreUpdates then
|
|
if not frame.ignoreBackdropColors then
|
|
if frame.template == "Default" or frame.template == nil then
|
|
frame:SetBackdropColor(unpack(self.media.backdropcolor))
|
|
elseif frame.template == "Transparent" then
|
|
frame:SetBackdropColor(unpack(self.media.backdropfadecolor))
|
|
end
|
|
end
|
|
else
|
|
self.unitFrameElements[frame] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:UpdateFontTemplates()
|
|
for text in pairs(self.texts) do
|
|
if text then
|
|
text:FontTemplate(text.font, text.fontSize, text.fontStyle)
|
|
else
|
|
self.texts[text] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:RegisterStatusBar(statusBar)
|
|
tinsert(self.statusBars, statusBar)
|
|
end
|
|
|
|
function E:UpdateStatusBars()
|
|
for _, statusBar in pairs(self.statusBars) do
|
|
if statusBar and statusBar:IsObjectType("StatusBar") then
|
|
statusBar:SetStatusBarTexture(self.media.normTex)
|
|
elseif statusBar and statusBar:IsObjectType("Texture") then
|
|
statusBar:SetTexture(self.media.normTex)
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:IncompatibleAddOn(addon, module)
|
|
E.PopupDialogs.INCOMPATIBLE_ADDON.button1 = addon
|
|
E.PopupDialogs.INCOMPATIBLE_ADDON.button2 = "ElvUI "..module
|
|
E.PopupDialogs.INCOMPATIBLE_ADDON.addon = addon
|
|
E.PopupDialogs.INCOMPATIBLE_ADDON.module = module
|
|
E:StaticPopup_Show("INCOMPATIBLE_ADDON", addon, module)
|
|
end
|
|
|
|
function E:IsAddOnEnabled(addon)
|
|
if addon == "Ascension_NamePlates" then
|
|
return C_CVar.GetBool("useNewNamePlates")
|
|
end
|
|
local _, _, _, enabled, _, reason = GetAddOnInfo(addon)
|
|
if reason ~= "MISSING" and enabled then
|
|
return true
|
|
end
|
|
end
|
|
|
|
function E:CheckIncompatible()
|
|
if E.global.ignoreIncompatible then return end
|
|
|
|
if E.private.chat.enable then
|
|
if self:IsAddOnEnabled("Prat-3.0") then
|
|
self:IncompatibleAddOn("Prat-3.0", "Chat")
|
|
elseif self:IsAddOnEnabled("Chatter") then
|
|
self:IncompatibleAddOn("Chatter", "Chat")
|
|
end
|
|
end
|
|
|
|
if E.private.nameplates.enable then
|
|
if self:IsAddOnEnabled("Aloft") then
|
|
self:IncompatibleAddOn("Aloft", "NamePlates")
|
|
elseif self:IsAddOnEnabled("Healers-Have-To-Die") then
|
|
self:IncompatibleAddOn("Healers-Have-To-Die", "NamePlates")
|
|
elseif self:IsAddOnEnabled("TidyPlates") then
|
|
self:IncompatibleAddOn("TidyPlates", "NamePlates")
|
|
elseif self:IsAddOnEnabled("Ascension_NamePlates") then
|
|
self:IncompatibleAddOn("Ascension_NamePlates", "NamePlates")
|
|
elseif self:IsAddOnEnabled("Kui_Nameplates") then
|
|
self:IncompatibleAddOn("Kui_Nameplates", "NamePlates")
|
|
end
|
|
end
|
|
|
|
if E.private.tooltip.enable and self:IsAddOnEnabled("TipTac") then
|
|
self:IncompatibleAddOn("TipTac", "Tooltip")
|
|
end
|
|
|
|
if E.private.worldmap.enable and self:IsAddOnEnabled("Mapster") then
|
|
self:IncompatibleAddOn("Mapster", "WorldMap")
|
|
end
|
|
end
|
|
|
|
function E:CopyTable(currentTable, defaultTable)
|
|
if type(currentTable) ~= "table" then currentTable = {} end
|
|
|
|
if type(defaultTable) == "table" then
|
|
for option, value in pairs(defaultTable) do
|
|
if type(value) == "table" then
|
|
value = self:CopyTable(currentTable[option], value)
|
|
end
|
|
|
|
currentTable[option] = value
|
|
end
|
|
end
|
|
|
|
return currentTable
|
|
end
|
|
|
|
function E:RemoveEmptySubTables(tbl)
|
|
if type(tbl) ~= "table" then
|
|
E:Print("Bad argument #1 to 'RemoveEmptySubTables' (table expected)")
|
|
return
|
|
end
|
|
|
|
for k, v in pairs(tbl) do
|
|
if type(v) == "table" then
|
|
if next(v) == nil then
|
|
tbl[k] = nil
|
|
else
|
|
self:RemoveEmptySubTables(v)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--Compare 2 tables and remove duplicate key/value pairs
|
|
--param cleanTable : table you want cleaned
|
|
--param checkTable : table you want to check against.
|
|
--return : a copy of cleanTable with duplicate key/value pairs removed
|
|
function E:RemoveTableDuplicates(cleanTable, checkTable)
|
|
if type(cleanTable) ~= "table" then
|
|
E:Print("Bad argument #1 to 'RemoveTableDuplicates' (table expected)")
|
|
return
|
|
end
|
|
if type(checkTable) ~= "table" then
|
|
E:Print("Bad argument #2 to 'RemoveTableDuplicates' (table expected)")
|
|
return
|
|
end
|
|
|
|
local rtdCleaned = {}
|
|
for option, value in pairs(cleanTable) do
|
|
if type(value) == "table" and checkTable[option] and type(checkTable[option]) == "table" then
|
|
rtdCleaned[option] = self:RemoveTableDuplicates(value, checkTable[option])
|
|
else
|
|
-- Add unique data to our clean table
|
|
if cleanTable[option] ~= checkTable[option] then
|
|
rtdCleaned[option] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
--Clean out empty sub-tables
|
|
self:RemoveEmptySubTables(rtdCleaned)
|
|
|
|
return rtdCleaned
|
|
end
|
|
|
|
--Compare 2 tables and remove blacklisted key/value pairs
|
|
--param cleanTable : table you want cleaned
|
|
--param blacklistTable : table you want to check against.
|
|
--return : a copy of cleanTable with blacklisted key/value pairs removed
|
|
function E:FilterTableFromBlacklist(cleanTable, blacklistTable)
|
|
if type(cleanTable) ~= "table" then
|
|
E:Print("Bad argument #1 to 'FilterTableFromBlacklist' (table expected)")
|
|
return
|
|
end
|
|
if type(blacklistTable) ~= "table" then
|
|
E:Print("Bad argument #2 to 'FilterTableFromBlacklist' (table expected)")
|
|
return
|
|
end
|
|
|
|
local tfbCleaned = {}
|
|
for option, value in pairs(cleanTable) do
|
|
if type(value) == "table" and blacklistTable[option] and type(blacklistTable[option]) == "table" then
|
|
tfbCleaned[option] = self:FilterTableFromBlacklist(value, blacklistTable[option])
|
|
else
|
|
-- Filter out blacklisted keys
|
|
if blacklistTable[option] ~= true then
|
|
tfbCleaned[option] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
--Clean out empty sub-tables
|
|
self:RemoveEmptySubTables(tfbCleaned)
|
|
|
|
return tfbCleaned
|
|
end
|
|
|
|
do --The code in this function is from WeakAuras, credit goes to Mirrored and the WeakAuras Team
|
|
--Code slightly modified by Simpy
|
|
local function recurse(table, level, ret)
|
|
for i, v in pairs(table) do
|
|
ret = ret..strrep(" ", level).."["
|
|
if type(i) == "string" then ret = ret..'"'..i..'"' else ret = ret..i end
|
|
ret = ret.."] = "
|
|
|
|
if type(v) == "number" then
|
|
ret = ret..v..",\n"
|
|
elseif type(v) == "string" then
|
|
ret = ret.."\""..gsub(gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\""), "\124", "\124\124").."\",\n"
|
|
elseif type(v) == "boolean" then
|
|
if v then ret = ret.."true,\n" else ret = ret.."false,\n" end
|
|
elseif type(v) == "table" then
|
|
ret = ret.."{\n"
|
|
ret = recurse(v, level + 1, ret)
|
|
ret = ret..strrep(" ", level).."},\n"
|
|
else
|
|
ret = ret.."\""..tostring(v).."\",\n"
|
|
end
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
function E:TableToLuaString(inTable)
|
|
if type(inTable) ~= "table" then
|
|
E:Print("Invalid argument #1 to E:TableToLuaString (table expected)")
|
|
return
|
|
end
|
|
|
|
local ret = "{\n"
|
|
if inTable then ret = recurse(inTable, 1, ret) end
|
|
ret = ret.."}"
|
|
|
|
return ret
|
|
end
|
|
end
|
|
|
|
do --The code in this function is from WeakAuras, credit goes to Mirrored and the WeakAuras Team
|
|
--Code slightly modified by Simpy
|
|
local lineStructureTable, profileFormat = {}, {
|
|
profile = "E.db",
|
|
private = "E.private",
|
|
global = "E.global",
|
|
filters = "E.global",
|
|
styleFilters = "E.global"
|
|
}
|
|
|
|
local function buildLineStructure(str) -- str is profileText
|
|
for _, v in ipairs(lineStructureTable) do
|
|
if type(v) == "string" then
|
|
str = str..'["'..v..'"]'
|
|
else
|
|
str = str..'['..v..']'
|
|
end
|
|
end
|
|
|
|
return str
|
|
end
|
|
|
|
local sameLine
|
|
local function recurse(tbl, ret, profileText)
|
|
local lineStructure = buildLineStructure(profileText)
|
|
for k, v in pairs(tbl) do
|
|
if not sameLine then
|
|
ret = ret..lineStructure
|
|
end
|
|
|
|
ret = ret.."["
|
|
|
|
if type(k) == "string" then
|
|
ret = ret..'"'..k..'"'
|
|
else
|
|
ret = ret..k
|
|
end
|
|
|
|
if type(v) == "table" then
|
|
tinsert(lineStructureTable, k)
|
|
sameLine = true
|
|
ret = ret.."]"
|
|
ret = recurse(v, ret, profileText)
|
|
else
|
|
sameLine = false
|
|
ret = ret.."] = "
|
|
|
|
if type(v) == "number" then
|
|
ret = ret..v.."\n"
|
|
elseif type(v) == "string" then
|
|
ret = ret.."\""..gsub(gsub(gsub(gsub(v, "\\", "\\\\"), "\n", "\\n"), "\"", "\\\""), "\124", "\124\124").."\"\n"
|
|
elseif type(v) == "boolean" then
|
|
if v then
|
|
ret = ret.."true\n"
|
|
else
|
|
ret = ret.."false\n"
|
|
end
|
|
else
|
|
ret = ret.."\""..tostring(v).."\"\n"
|
|
end
|
|
end
|
|
end
|
|
|
|
tremove(lineStructureTable)
|
|
|
|
return ret
|
|
end
|
|
|
|
function E:ProfileTableToPluginFormat(inTable, profileType)
|
|
local profileText = profileFormat[profileType]
|
|
if not profileText then return end
|
|
|
|
twipe(lineStructureTable)
|
|
local ret = ""
|
|
if inTable and profileType then
|
|
sameLine = false
|
|
ret = recurse(inTable, ret, profileText)
|
|
end
|
|
|
|
return ret
|
|
end
|
|
end
|
|
|
|
do --Split string by multi-character delimiter (the strsplit / string.split function provided by WoW doesn't allow multi-character delimiter)
|
|
local splitTable = {}
|
|
function E:SplitString(str, delim)
|
|
assert(type (delim) == "string" and strlen(delim) > 0, "bad delimiter")
|
|
|
|
local start = 1
|
|
twipe(splitTable) -- results table
|
|
|
|
-- find each instance of a string followed by the delimiter
|
|
while true do
|
|
local pos = find(str, delim, start, true) -- plain find
|
|
if not pos then break end
|
|
|
|
tinsert(splitTable, sub(str, start, pos - 1))
|
|
start = pos + strlen(delim)
|
|
end -- while
|
|
|
|
-- insert final one (after last delimiter)
|
|
tinsert(splitTable, sub(str, start))
|
|
|
|
return unpack(splitTable)
|
|
end
|
|
end
|
|
|
|
do
|
|
local SendMessageWaiting
|
|
local SendRecieveGroupSize = 0
|
|
|
|
function E:SendMessage()
|
|
SendMessageWaiting = nil
|
|
end
|
|
|
|
local function SendRecieve(_, event, prefix, message, _, sender)
|
|
if event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE" then
|
|
local numRaid = GetNumRaidMembers()
|
|
local num = numRaid > 0 and numRaid or (GetNumPartyMembers() + 1)
|
|
if num ~= SendRecieveGroupSize then
|
|
if num > 1 and num > SendRecieveGroupSize then
|
|
if not SendMessageWaiting then
|
|
SendMessageWaiting = E:Delay(10, E.SendMessage)
|
|
end
|
|
end
|
|
SendRecieveGroupSize = num
|
|
end
|
|
elseif event == "PLAYER_ENTERING_WORLD" then
|
|
if not SendMessageWaiting then
|
|
SendMessageWaiting = E:Delay(10, E.SendMessage)
|
|
end
|
|
end
|
|
end
|
|
|
|
local f = CreateFrame("Frame")
|
|
f:RegisterEvent("CHAT_MSG_ADDON")
|
|
f:RegisterEvent("RAID_ROSTER_UPDATE")
|
|
f:RegisterEvent("PARTY_MEMBERS_CHANGED")
|
|
f:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
f:SetScript("OnEvent", SendRecieve)
|
|
end
|
|
|
|
function E:UpdateAll(ignoreInstall)
|
|
E.private = E.charSettings.profile
|
|
E.db = E.data.profile
|
|
E.global = E.data.global
|
|
E.db.theme = nil
|
|
E.db.install_complete = nil
|
|
|
|
E:DBConversions()
|
|
|
|
ActionBars.db = E.db.actionbar
|
|
Auras.db = E.db.auras
|
|
Bags.db = E.db.bags
|
|
Chat.db = E.db.chat
|
|
DataBars.db = E.db.databars
|
|
DataTexts.db = E.db.datatexts
|
|
NamePlates.db = E.db.nameplates
|
|
Threat.db = E.db.general.threat
|
|
Tooltip.db = E.db.tooltip
|
|
Totems.db = E.db.general.totems
|
|
ReminderBuffs.db = E.db.general.reminder
|
|
UnitFrames.db = E.db.unitframe
|
|
|
|
--The mover is positioned before it is resized, which causes issues for unitframes
|
|
--Allow movers to be "pushed" outside the screen, when they are resized they should be back in the screen area.
|
|
--We set movers to be clamped again at the bottom of this function.
|
|
E:SetMoversClampedToScreen(false)
|
|
E:SetMoversPositions()
|
|
|
|
E:UpdateMedia()
|
|
E:UpdateBorderColors()
|
|
E:UpdateBackdropColors()
|
|
E:UpdateFrameTemplates()
|
|
E:UpdateStatusBars()
|
|
E:UpdateCooldownSettings("all")
|
|
|
|
Layout:ToggleChatPanels()
|
|
Layout:BottomPanelVisibility()
|
|
Layout:TopPanelVisibility()
|
|
Layout:SetDataPanelStyle()
|
|
|
|
if E.private.actionbar.enable then
|
|
ActionBars:ToggleDesaturation()
|
|
ActionBars:UpdateButtonSettings()
|
|
ActionBars:UpdateMicroPositionDimensions()
|
|
end
|
|
|
|
AFK:Toggle()
|
|
|
|
if E.private.bags.enable then
|
|
Bags:Layout()
|
|
Bags:Layout(true)
|
|
Bags:SizeAndPositionBagBar()
|
|
Bags:UpdateCountDisplay()
|
|
Bags:UpdateItemLevelDisplay()
|
|
end
|
|
|
|
if E.private.chat.enable then
|
|
Chat:PositionChat(true)
|
|
Chat:SetupChat()
|
|
Chat:UpdateAnchors()
|
|
end
|
|
|
|
DataBars:ExperienceBar_Toggle()
|
|
DataBars:ReputationBar_Toggle()
|
|
DataBars:UpdateDataBarDimensions()
|
|
|
|
DataTexts:LoadDataTexts()
|
|
|
|
if E.private.general.minimap.enable then
|
|
Minimap:UpdateSettings()
|
|
ReminderBuffs:UpdateSettings()
|
|
end
|
|
|
|
if E.private.nameplates.enable then
|
|
NamePlates:ConfigureAll()
|
|
NamePlates:StyleFilterInitialize()
|
|
end
|
|
|
|
Threat:ToggleEnable()
|
|
Threat:UpdatePosition()
|
|
|
|
Totems:ToggleEnable()
|
|
Totems:PositionAndSize()
|
|
|
|
if E.private.unitframe.enable then
|
|
UnitFrames:Update_AllFrames()
|
|
end
|
|
|
|
if ElvUIPlayerBuffs then
|
|
Auras:UpdateHeader(ElvUIPlayerBuffs)
|
|
end
|
|
|
|
if ElvUIPlayerDebuffs then
|
|
Auras:UpdateHeader(ElvUIPlayerDebuffs)
|
|
end
|
|
|
|
if E.RefreshGUI then
|
|
E:RefreshGUI()
|
|
end
|
|
|
|
if not ignoreInstall and not E.private.install_complete then
|
|
E:Install()
|
|
end
|
|
|
|
Blizzard:SetWatchFrameHeight()
|
|
E:SetMoversClampedToScreen(true) -- Go back to using clamp after resizing has taken place.
|
|
end
|
|
|
|
do
|
|
E.ObjectEventTable, E.ObjectEventFrame = {}, CreateFrame("Frame")
|
|
local eventFrame, eventTable = E.ObjectEventFrame, E.ObjectEventTable
|
|
|
|
eventFrame:SetScript("OnEvent", function(_, event, ...)
|
|
local objs = eventTable[event]
|
|
if objs then
|
|
for object, funcs in pairs(objs) do
|
|
for _, func in ipairs(funcs) do
|
|
func(object, event, ...)
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
function E:HasFunctionForObject(event, object, func)
|
|
if not (event and object and func) then
|
|
E:Print("Error. Usage: HasFunctionForObject(event, object, func)")
|
|
return
|
|
end
|
|
|
|
local objs = eventTable[event]
|
|
local funcs = objs and objs[object]
|
|
return funcs and tContains(funcs, func)
|
|
end
|
|
|
|
function E:IsEventRegisteredForObject(event, object)
|
|
if not (event and object) then
|
|
E:Print("Error. Usage: IsEventRegisteredForObject(event, object)")
|
|
return
|
|
end
|
|
|
|
local objs = eventTable[event]
|
|
local funcs = objs and objs[object]
|
|
return funcs ~= nil, funcs
|
|
end
|
|
|
|
--- Registers specified event and adds specified func to be called for the specified object.
|
|
-- Unless all parameters are supplied it will not register.
|
|
-- If the specified object has already been registered for the specified event
|
|
-- then it will just add the specified func to a table of functions that should be called.
|
|
-- When a registered event is triggered, then the registered function is called with
|
|
-- the object as first parameter, then event, and then all the parameters for the event itself.
|
|
-- @param event The event you want to register.
|
|
-- @param object The object you want to register the event for.
|
|
-- @param func The function you want executed for this object.
|
|
function E:RegisterEventForObject(event, object, func)
|
|
if not (event and object and func) then
|
|
E:Print("Error. Usage: RegisterEventForObject(event, object, func)")
|
|
return
|
|
end
|
|
|
|
local objs = eventTable[event]
|
|
if not objs then
|
|
objs = {}
|
|
eventTable[event] = objs
|
|
eventFrame:RegisterEvent(event)
|
|
end
|
|
|
|
local funcs = objs[object]
|
|
if not funcs then
|
|
objs[object] = {func}
|
|
elseif not tContains(funcs, func) then
|
|
tinsert(funcs, func)
|
|
end
|
|
end
|
|
|
|
--- Unregisters specified function for the specified object on the specified event.
|
|
-- Unless all parameters are supplied it will not unregister.
|
|
-- @param event The event you want to unregister an object from.
|
|
-- @param object The object you want to unregister a func from.
|
|
-- @param func The function you want unregistered for the object.
|
|
function E:UnregisterEventForObject(event, object, func)
|
|
if not (event and object and func) then
|
|
E:Print("Error. Usage: UnregisterEventForObject(event, object, func)")
|
|
return
|
|
end
|
|
|
|
local objs = eventTable[event]
|
|
local funcs = objs and objs[object]
|
|
if funcs then
|
|
for index, fnc in ipairs(funcs) do
|
|
if func == fnc then
|
|
tremove(funcs, index)
|
|
break
|
|
end
|
|
end
|
|
|
|
if #funcs == 0 then
|
|
objs[object] = nil
|
|
end
|
|
|
|
if not next(funcs) then
|
|
eventFrame:UnregisterEvent(event)
|
|
eventTable[event] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function E:ResetAllUI()
|
|
self:ResetMovers()
|
|
|
|
if E.db.layoutSet then
|
|
E:SetupLayout(E.db.layoutSet, true)
|
|
end
|
|
end
|
|
|
|
function E:ResetUI(...)
|
|
if InCombatLockdown() then E:Print(ERR_NOT_IN_COMBAT) return end
|
|
|
|
if ... == "" or ... == " " or ... == nil then
|
|
E:StaticPopup_Show("RESETUI_CHECK")
|
|
return
|
|
end
|
|
|
|
self:ResetMovers(...)
|
|
end
|
|
|
|
function E:CallLoadedModule(obj, silent, object, index)
|
|
local name, func
|
|
if type(obj) == "table" then name, func = unpack(obj) else name = obj end
|
|
local module = name and self:GetModule(name, silent)
|
|
|
|
if not module then return end
|
|
if func and type(func) == "string" then
|
|
E:RegisterCallback(name, module[func], module)
|
|
elseif func and type(func) == "function" then
|
|
E:RegisterCallback(name, func, module)
|
|
elseif module.Initialize then
|
|
E:RegisterCallback(name, module.Initialize, module)
|
|
end
|
|
|
|
E.callbacks:Fire(name)
|
|
|
|
if object and index then object[index] = nil end
|
|
end
|
|
|
|
function E:RegisterInitialModule(name, func)
|
|
self.RegisteredInitialModules[#self.RegisteredInitialModules + 1] = (func and {name, func}) or name
|
|
end
|
|
|
|
function E:RegisterModule(name, func)
|
|
if self.initialized then
|
|
E:CallLoadedModule((func and {name, func}) or name)
|
|
else
|
|
self.RegisteredModules[#self.RegisteredModules + 1] = (func and {name, func}) or name
|
|
end
|
|
end
|
|
|
|
function E:InitializeInitialModules()
|
|
for index, object in ipairs(E.RegisteredInitialModules) do
|
|
E:CallLoadedModule(object, true, E.RegisteredInitialModules, index)
|
|
end
|
|
end
|
|
|
|
function E:InitializeModules()
|
|
for index, object in ipairs(E.RegisteredModules) do
|
|
E:CallLoadedModule(object, true, E.RegisteredModules, index)
|
|
end
|
|
end
|
|
|
|
--DATABASE CONVERSIONS
|
|
function E:DBConversions()
|
|
--Fix issue where UIScale was incorrectly stored as string
|
|
E.global.general.UIScale = tonumber(E.global.general.UIScale)
|
|
|
|
--Not sure how this one happens, but prevent it in any case
|
|
if E.global.general.UIScale <= 0 then
|
|
E.global.general.UIScale = G.general.UIScale
|
|
end
|
|
|
|
if gameLocale and E.global.general.locale == "auto" then
|
|
E.global.general.locale = gameLocale
|
|
end
|
|
|
|
--Combat & Resting Icon options update
|
|
if E.db.unitframe.units.player.combatIcon ~= nil then
|
|
E.db.unitframe.units.player.CombatIcon.enable = E.db.unitframe.units.player.combatIcon
|
|
E.db.unitframe.units.player.combatIcon = nil
|
|
end
|
|
if E.db.unitframe.units.player.restIcon ~= nil then
|
|
E.db.unitframe.units.player.RestIcon.enable = E.db.unitframe.units.player.restIcon
|
|
E.db.unitframe.units.player.restIcon = nil
|
|
end
|
|
|
|
-- [Fader] Combat Fade options for Player
|
|
if E.db.unitframe.units.player.combatfade ~= nil then
|
|
local enabled = E.db.unitframe.units.player.combatfade
|
|
E.db.unitframe.units.player.fader.enable = enabled
|
|
|
|
if enabled then -- use the old min alpha too
|
|
E.db.unitframe.units.player.fader.minAlpha = 0
|
|
end
|
|
|
|
E.db.unitframe.units.player.combatfade = nil
|
|
end
|
|
|
|
-- [Fader] Range check options for Units
|
|
do
|
|
local outsideAlpha
|
|
if E.db.unitframe.OORAlpha ~= nil then
|
|
outsideAlpha = E.db.unitframe.OORAlpha
|
|
E.db.unitframe.OORAlpha = nil
|
|
end
|
|
|
|
local rangeCheckUnits = {"target", "targettarget", "targettargettarget", "focus", "focustarget", "pet", "pettarget", "boss", "arena", "party", "raid", "raid40", "raidpet", "tank", "assist"}
|
|
for _, unit in pairs(rangeCheckUnits) do
|
|
if E.db.unitframe.units[unit].rangeCheck ~= nil then
|
|
local enabled = E.db.unitframe.units[unit].rangeCheck
|
|
E.db.unitframe.units[unit].fader.enable = enabled
|
|
E.db.unitframe.units[unit].fader.range = enabled
|
|
|
|
if outsideAlpha then
|
|
E.db.unitframe.units[unit].fader.minAlpha = outsideAlpha
|
|
end
|
|
|
|
E.db.unitframe.units[unit].rangeCheck = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
--Convert old "Buffs and Debuffs" font size option to individual options
|
|
if E.db.auras.fontSize then
|
|
local fontSize = E.db.auras.fontSize
|
|
E.db.auras.buffs.countFontSize = fontSize
|
|
E.db.auras.buffs.durationFontSize = fontSize
|
|
E.db.auras.debuffs.countFontSize = fontSize
|
|
E.db.auras.debuffs.durationFontSize = fontSize
|
|
E.db.auras.fontSize = nil
|
|
end
|
|
|
|
--Convert old private cooldown setting to profile setting
|
|
if E.private.cooldown and (E.private.cooldown.enable ~= nil) then
|
|
E.db.cooldown.enable = E.private.cooldown.enable
|
|
E.private.cooldown.enable = nil
|
|
E.private.cooldown = nil
|
|
end
|
|
|
|
if not E.db.chat.panelColorConverted then
|
|
local color = E.db.general.backdropfadecolor
|
|
E.db.chat.panelColor = {r = color.r, g = color.g, b = color.b, a = color.a}
|
|
E.db.chat.panelColorConverted = true
|
|
end
|
|
|
|
--Convert cropIcon to tristate
|
|
local cropIcon = E.db.general.cropIcon
|
|
if type(cropIcon) == "boolean" then
|
|
E.db.general.cropIcon = (cropIcon and 2) or 0
|
|
end
|
|
|
|
--Vendor Greys option removed
|
|
if E.db.bags.vendorGrays then
|
|
E.db.general.vendorGrays = nil
|
|
E.db.general.vendorGraysDetails = nil
|
|
end
|
|
|
|
--Heal Prediction is now a table instead of a bool
|
|
local healPredictionUnits = {"player", "target", "focus", "pet", "arena", "party", "raid", "raid40", "raidpet"}
|
|
for _, unit in pairs(healPredictionUnits) do
|
|
if type(E.db.unitframe.units[unit].healPrediction) ~= "table" then
|
|
local enabled = E.db.unitframe.units[unit].healPrediction
|
|
E.db.unitframe.units[unit].healPrediction = {}
|
|
E.db.unitframe.units[unit].healPrediction.enable = enabled
|
|
end
|
|
end
|
|
|
|
--Health Backdrop Multiplier
|
|
if E.db.unitframe.colors.healthmultiplier ~= nil then
|
|
if E.db.unitframe.colors.healthmultiplier > 0.75 then
|
|
E.db.unitframe.colors.healthMultiplier = 0.75
|
|
else
|
|
E.db.unitframe.colors.healthMultiplier = E.db.unitframe.colors.healthmultiplier
|
|
end
|
|
|
|
E.db.unitframe.colors.healthmultiplier = nil
|
|
end
|
|
|
|
if sub(E.db.chat.timeStampFormat, -1) == " " then
|
|
E.db.chat.timeStampFormat = sub(E.db.chat.timeStampFormat, 1, -2)
|
|
end
|
|
|
|
if E.private.skins.blizzard.greeting ~= nil then
|
|
E.private.skins.blizzard.greeting = nil
|
|
end
|
|
|
|
-- VERSION 7.0 -- nameplate overhaul
|
|
if not E.db.version or E.db.version < 7 then
|
|
-- wipe nameplates
|
|
E:CopyTable(self.db.nameplates, P.nameplates)
|
|
end
|
|
|
|
if not E.db.version or E.db.version < 7.13 then
|
|
if not E.db.nameplates.plateSize.width then
|
|
E.db.nameplates.plateSize.width = P.nameplates.plateSize.width
|
|
E.db.nameplates.plateSize.enemyWidth = nil
|
|
end
|
|
|
|
if not E.db.nameplates.plateSize.height then
|
|
E.db.nameplates.plateSize.height = P.nameplates.plateSize.height
|
|
E.db.nameplates.plateSize.enemyHeight = nil
|
|
end
|
|
end
|
|
|
|
E.db.version = E.versionNum
|
|
end
|
|
|
|
function E:RefreshModulesDB()
|
|
-- this function is specifically used to reference the new database
|
|
-- onto the unitframe module, its useful dont delete! D:
|
|
twipe(UnitFrames.db) --old ref, dont need so clear it
|
|
UnitFrames.db = self.db.unitframe --new ref
|
|
end
|
|
|
|
do
|
|
-- Shamelessly taken from AceDB-3.0 and stripped down by Simpy
|
|
function E:CopyDefaults(dest, src)
|
|
for k, v in pairs(src) do
|
|
if type(v) == 'table' then
|
|
if not rawget(dest, k) then rawset(dest, k, {}) end
|
|
if type(dest[k]) == 'table' then E:CopyDefaults(dest[k], v) end
|
|
elseif rawget(dest, k) == nil then
|
|
rawset(dest, k, v)
|
|
end
|
|
end
|
|
|
|
return dest
|
|
end
|
|
|
|
function E:RemoveDefaults(db, defaults)
|
|
setmetatable(db, nil)
|
|
|
|
for k, v in pairs(defaults) do
|
|
if type(v) == 'table' and type(db[k]) == 'table' then
|
|
E:RemoveDefaults(db[k], v)
|
|
if next(db[k]) == nil then db[k] = nil end
|
|
elseif db[k] == defaults[k] then
|
|
db[k] = nil
|
|
end
|
|
end
|
|
|
|
return db
|
|
end
|
|
end
|
|
|
|
function E:Initialize()
|
|
twipe(self.db)
|
|
twipe(self.global)
|
|
twipe(self.private)
|
|
|
|
self.myguid = UnitGUID("player")
|
|
self.data = E.Libs.AceDB:New("ElvDB", self.DF)
|
|
self.data.RegisterCallback(self, "OnProfileChanged", "UpdateAll")
|
|
self.data.RegisterCallback(self, "OnProfileCopied", "UpdateAll")
|
|
self.data._ResetProfile = self.data.ResetProfile
|
|
self.data.ResetProfile = self.OnProfileReset
|
|
self.charSettings = E.Libs.AceDB:New("ElvPrivateDB", self.privateVars)
|
|
E.Libs.DualSpec:EnhanceDatabase(self.data, "ElvUI")
|
|
self.private = self.charSettings.profile
|
|
self.db = self.data.profile
|
|
self.global = self.data.global
|
|
|
|
self:CheckIncompatible()
|
|
self:DBConversions()
|
|
self:UIScale()
|
|
self:BuildPrefixValues()
|
|
self:LoadAPI()
|
|
self:LoadCommands()
|
|
self:InitializeModules()
|
|
self:RefreshModulesDB()
|
|
self:LoadMovers()
|
|
self:UpdateMedia()
|
|
self:UpdateCooldownSettings("all")
|
|
self:Tutorials()
|
|
self.initialized = true
|
|
|
|
Minimap:UpdateSettings()
|
|
|
|
if E.db.general.smoothingAmount and (E.db.general.smoothingAmount ~= 0.33) then
|
|
E:SetSmoothingAmount(E.db.general.smoothingAmount)
|
|
end
|
|
|
|
if not self.private.install_complete then
|
|
self:Install()
|
|
end
|
|
|
|
if self:HelloKittyFixCheck() then
|
|
self:HelloKittyFix()
|
|
end
|
|
|
|
if self.db.general.kittys then
|
|
self:CreateKittys()
|
|
self:Delay(5, self.Print, self, L["Type /hellokitty to revert to old settings."])
|
|
end
|
|
|
|
if self.db.general.loginmessage then
|
|
local msg = format(L["LOGIN_MSG"], self.media.hexvaluecolor, self.media.hexvaluecolor, self.version)
|
|
if Chat.Initialized then msg = select(2, Chat:FindURL("CHAT_MSG_DUMMY", msg)) end
|
|
print(msg)
|
|
E:Print("Use /elvrole [melee, caster, ranged, tank] to optimize the UI for your role. Your current role is "..E.Role)
|
|
end
|
|
|
|
if GetCVar("scriptProfile") ~= "1" then
|
|
collectgarbage("collect")
|
|
end
|
|
end |