599 lines
19 KiB
Lua
599 lines
19 KiB
Lua
local addonName = "AccountWideRaidProfiles"
|
|
local dbName = "AccountWideRaidProfilesDB"
|
|
|
|
local addon = LibStub("AceAddon-3.0"):NewAddon(addonName,"AceHook-3.0", "AceEvent-3.0", "AceConsole-3.0")
|
|
local AceGUI = LibStub("AceGUI-3.0")
|
|
|
|
local CVAR_FRAME_STYLE = "useCompactPartyFrames"
|
|
local DEFAULT_CUF_PROFILE_NAME = "Primary"
|
|
|
|
local RAID_CONTAINER_WIDTH = 300
|
|
local MINIMUM_RAID_CONTAINER_HEIGHT = 86
|
|
|
|
local MINIMUM_RAID_BLOCK_WIDTH = 72
|
|
local MAXIMUM_RAID_BLOCK_WIDTH = 144
|
|
local MINIMUM_RAID_BLOCK_HEIGHT = 36
|
|
local MAXIMUM_RAID_BLOCK_HEIGHT = 72
|
|
|
|
local ADDON_INACTIVE_PROFILE = "ADDON_INACTIVE"
|
|
|
|
local ADDON_RELOAD_DIALOG = "ACCOUNT_WIDE_RAID_PROFILES_RELOAD_DIALOG"
|
|
|
|
local function ShallowCopy(orig)
|
|
local orig_type = type(orig)
|
|
local copy
|
|
if orig_type == 'table' then
|
|
copy = {}
|
|
for orig_key, orig_value in pairs(orig) do
|
|
copy[orig_key] = orig_value
|
|
end
|
|
else -- number, string, boolean, etc
|
|
copy = orig
|
|
end
|
|
return copy
|
|
end
|
|
|
|
|
|
|
|
StaticPopupDialogs[ADDON_RELOAD_DIALOG] = {
|
|
text = "Account Wide Raid Profiles has applied changes to the raid profile settings. Reloading the user interface is required to avoid tainting the raid frame. Do you want to reload now?",
|
|
button1 = YES,
|
|
button2 = NO,
|
|
OnAccept = function(self)
|
|
ReloadUI()
|
|
end,
|
|
OnCancel = function(self)
|
|
addon:Print("The user interface is not reloaded. The addon has applied new raid profile settings, but has tainted the raid frame that may cause it not responding to user input. To fix it, enter \"\/reload\" in chat.")
|
|
end,
|
|
timeout = 0,
|
|
hideOnEscape = 1,
|
|
}
|
|
|
|
function addon:OnInitialize()
|
|
addon:RegisterEvent("COMPACT_UNIT_FRAME_PROFILES_LOADED")
|
|
self.needReload = false
|
|
self.disableOptionPanelUpdate = false
|
|
self.inCombat = false
|
|
self.isOptionOpen = false
|
|
self.db = LibStub("AceDB-3.0"):New(dbName)
|
|
self.initialized = false
|
|
local addonOption = addon:SetUpOptionsPanel(addonOption)
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable(addonName, addonOption, {"awrp"})
|
|
self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions(addonName, addonName)
|
|
addon:HookAll()
|
|
end
|
|
|
|
|
|
|
|
function addon:COMPACT_UNIT_FRAME_PROFILES_LOADED(...)
|
|
if (not self.db.profile.profiles) then
|
|
addon:StoreAll()
|
|
self.initialized = true
|
|
else
|
|
if (addon:IsAddonActive()) then
|
|
local tempProfile = {}
|
|
addon:StoreAllToProfile(tempProfile)
|
|
if not addon:isProfilesEqual(self.db.profile, tempProfile) then
|
|
addon:LoadAll()
|
|
addon:ReloadDialog()
|
|
else
|
|
self.initialized = true
|
|
end
|
|
else
|
|
addon:StoreAll()
|
|
self.initialized = true
|
|
end
|
|
self.initialized = true
|
|
end
|
|
addon:HookAll()
|
|
end
|
|
|
|
function addon:ShowRaidFrameWhenSolo()
|
|
if ((not self.inCombat) and (not IsInGroup()) and GetCVar(CVAR_FRAME_STYLE) == '1' ) then
|
|
CompactRaidFrameContainer:Show()
|
|
CompactRaidFrameManager:Show()
|
|
end
|
|
end
|
|
|
|
function addon:HideRaidFrameWhenSolo()
|
|
if ((not self.inCombat) and (not IsInGroup()) and GetCVar(CVAR_FRAME_STYLE) == '1' ) then
|
|
CompactRaidFrameContainer:Hide()
|
|
CompactRaidFrameManager:Hide()
|
|
end
|
|
end
|
|
|
|
function addon:OnOptionShow()
|
|
self.isOptionOpen = true
|
|
end
|
|
|
|
function addon:OnOptionHide()
|
|
self.isOptionOpen = false
|
|
if (self.needReload) then
|
|
self.needReload = false
|
|
addon:HideRaidFrameWhenSolo()
|
|
addon:ReloadDialog()
|
|
end
|
|
end
|
|
|
|
function addon:HookAll()
|
|
addon:UnhookAll()
|
|
self.db.RegisterCallback(self, "OnProfileReset", "ResetProfiles")
|
|
self.db.RegisterCallback(self, "OnProfileChanged", "RefreshProfiles")
|
|
self.db.RegisterCallback(self, "OnProfileCopied", "RefreshProfiles")
|
|
|
|
|
|
addon:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
addon:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
addon:SecureHookScript(self.optionsFrame, "OnShow", "OnOptionShow")
|
|
addon:SecureHookScript(self.optionsFrame, "OnHide", "OnOptionHide")
|
|
|
|
if (addon:IsAddonActive() and self.initialized) then
|
|
addon:SecureHook("SetRaidProfileSavedPosition","StorePosition")
|
|
addon:SecureHook("CompactUnitFrameProfiles_ApplyProfile", "StoreAll")
|
|
addon:SecureHook("SetCVar", "StoreFrameStyleChanges")
|
|
end
|
|
end
|
|
|
|
function addon:GetActiveRaidProfileId()
|
|
for i=1, GetNumRaidProfiles() do
|
|
if self.db.profile.lastProfile == self.db.profile.profiles[i] then
|
|
return i
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function addon:PLAYER_REGEN_DISABLED()
|
|
self.inCombat = true
|
|
end
|
|
|
|
function addon:PLAYER_REGEN_ENABLED()
|
|
self.inCombat = false
|
|
end
|
|
|
|
-- Unsecure function. Need reload somewhere after calling this function.
|
|
function addon:UnlockFrame()
|
|
if (not self.inCombat) then
|
|
CompactRaidFrameManagerDisplayFrameLockedModeToggle:SetText(UNLOCK)
|
|
CompactRaidFrameManagerDisplayFrameLockedModeToggle.lockMode = false
|
|
CompactRaidFrameManager_UpdateContainerLockVisibility(CompactRaidFrameManager)
|
|
CompactRaidFrameContainer_UpdateDisplayedUnits(CompactRaidFrameContainer)
|
|
CompactRaidFrameContainer_TryUpdate(CompactRaidFrameContainer)
|
|
RaidOptionsFrame_UpdatePartyFrames()
|
|
CompactRaidFrameManager_UpdateShown(CompactRaidFrameManager)
|
|
if (self.isOptionOpen) then
|
|
addon:ShowRaidFrameWhenSolo()
|
|
end
|
|
end
|
|
end
|
|
|
|
function addon:RefreshProfiles()
|
|
self.needReload = true
|
|
addon:UnhookAll()
|
|
if (not self.db.profile.profiles) then
|
|
addon:ResetProfiles()
|
|
else
|
|
addon:LoadAll()
|
|
end
|
|
if (self.isOptionOpen) then
|
|
addon:ShowRaidFrameWhenSolo()
|
|
end
|
|
addon:HookAll()
|
|
end
|
|
|
|
function addon:ResetProfiles()
|
|
self.needReload = true
|
|
addon:UnhookAll()
|
|
local profiles = {}
|
|
for i=1, GetNumRaidProfiles() do
|
|
tinsert(profiles, GetRaidProfileName(i))
|
|
end
|
|
for i=1, #profiles do
|
|
DeleteRaidProfile(profiles[i])
|
|
end
|
|
CreateNewRaidProfile(DEFAULT_CUF_PROFILE_NAME)
|
|
SetActiveRaidProfile(DEFAULT_CUF_PROFILE_NAME)
|
|
SetCVar(CVAR_FRAME_STYLE, false)
|
|
addon:StoreAll()
|
|
addon:HookAll()
|
|
if (self.isOptionOpen) then
|
|
addon:ShowRaidFrameWhenSolo()
|
|
end
|
|
end
|
|
|
|
function addon:IsAddonActive()
|
|
return true -- Change this in the future
|
|
end
|
|
|
|
----------------------- Load and store raid prorfiles ---------------------------
|
|
|
|
function addon:LoadAll(...)
|
|
if (addon:IsAddonActive()) then
|
|
addon:UnhookAll()
|
|
local profiles = {}
|
|
for i=1, GetNumRaidProfiles() do
|
|
tinsert(profiles, GetRaidProfileName(i))
|
|
end
|
|
for i=1, #profiles do
|
|
DeleteRaidProfile(profiles[i])
|
|
end
|
|
|
|
SetCVar(CVAR_FRAME_STYLE, self.db.profile.frameStyle)
|
|
|
|
profiles = self.db.profile.profiles
|
|
local options = self.db.profile.options
|
|
local positions = self.db.profile.positions
|
|
|
|
for i=1, #profiles do
|
|
local profile = profiles[i]
|
|
CreateNewRaidProfile(profile)
|
|
for option, value in pairs(options[i]) do
|
|
SetRaidProfileOption(profile, option, value)
|
|
end
|
|
SetRaidProfileSavedPosition(profile, unpack(positions[i]))
|
|
end
|
|
|
|
SetActiveRaidProfile(self.db.profile.lastProfile)
|
|
|
|
CompactUnitFrameProfiles_ValidateProfilesLoaded(CompactUnitFrameProfiles)
|
|
addon:UpdateOptionsPanel()
|
|
end
|
|
end
|
|
|
|
function addon:StoreFrameStyleChanges(glStr, value)
|
|
if glStr == CVAR_FRAME_STYLE and not self.isOptionOpen then
|
|
self.db.profile.frameStyle = value
|
|
end
|
|
end
|
|
|
|
function addon:StorePosition(...)
|
|
args = {...}
|
|
for i=1, #self.db.profile.positions do
|
|
if self.db.profile.profiles[i] == args[1] then
|
|
self.db.profile.positions[i] = {select(2,unpack(args))}
|
|
end
|
|
end
|
|
if (not self.disableOptionPanelUpdate) then
|
|
addon:UpdateOptionsPanel()
|
|
end
|
|
end
|
|
|
|
function addon:StoreAllToProfile(db)
|
|
local profiles = {}
|
|
for i=1, GetNumRaidProfiles() do
|
|
tinsert(profiles, GetRaidProfileName(i))
|
|
end
|
|
|
|
db.frameStyle = GetCVar(CVAR_FRAME_STYLE)
|
|
db.profiles = profiles
|
|
db.options = {}
|
|
db.positions = {}
|
|
db.lastProfile = GetActiveRaidProfile()
|
|
|
|
for i=1, #profiles do
|
|
local profile = profiles[i]
|
|
db.options[i] = GetRaidProfileFlattenedOptions(profile)
|
|
db.positions[i] = {GetRaidProfileSavedPosition(profile)}
|
|
end
|
|
|
|
if (not self.disableOptionPanelUpdate) then
|
|
addon:UpdateOptionsPanel()
|
|
end
|
|
end
|
|
|
|
function addon:StoreAll()
|
|
addon:StoreAllToProfile(self.db.profile)
|
|
end
|
|
|
|
function addon:isProfilesEqual(p1, p2)
|
|
if ((not p1) or (not p2)) then return false end
|
|
if (p1.frameStyle ~= p2.frameStyle) then return false end
|
|
if (#p1.profiles ~= #p2.profiles) then return false end
|
|
if (#p1.options ~= #p2.options) then return false end
|
|
if (#p1.positions ~= #p2.positions) then return false end
|
|
|
|
for i=1, #p1.profiles do
|
|
if (p1.profiles[i] ~= p2.profiles[i]) then return false end
|
|
if (#p1.options[i] ~= #p2.options[i]) then return false end
|
|
if (#p1.positions[i] ~= #p2.positions[i]) then return false end
|
|
for j,_ in pairs(p1.options[i]) do
|
|
if (p1.options[i][j] ~= p2.options[i][j]) then
|
|
return false
|
|
end end
|
|
for j=1,#p1.positions[i] do
|
|
a = p1.positions[i][j]
|
|
b = p2.positions[i][j]
|
|
na = tonumber(a)
|
|
nb = tonumber(b)
|
|
if ((not na) and (not nb) and (a ~= b)) then
|
|
return false
|
|
end
|
|
if (na and nb and math.abs(na-nb) > 1) then
|
|
return false
|
|
end end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function addon:ReloadDialog()
|
|
StaticPopup_Show(ADDON_RELOAD_DIALOG)
|
|
end
|
|
|
|
---------------------------- Option panel ----------------------------------------------
|
|
function addon:UpdateOptionsPanel()
|
|
local addonOption = addon:SetUpOptionsPanel(addonOption)
|
|
LibStub("AceConfig-3.0"):RegisterOptionsTable(addonName, addonOption, {"awrp", addonName})
|
|
LibStub("AceConfigRegistry-3.0"):NotifyChange(addonName)
|
|
end
|
|
|
|
function addon:SetUpOptionsPanel()
|
|
local option = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
|
|
option = ShallowCopy(option)
|
|
option.name = "Account Wide Raid Profiles"
|
|
option.desc = "Manage Profiles and extra options of Account Wide Raid Profiles"
|
|
option.args = ShallowCopy(option.args)
|
|
option.args.rp = {
|
|
type = "execute",
|
|
name = "rp",
|
|
desc = "Open blizzard raid profile settings.",
|
|
guiHidden = true,
|
|
func = function()
|
|
InterfaceOptionsFrame_OpenToCategory(_G["CompactUnitFrameProfiles"])
|
|
end
|
|
}
|
|
option.args.config = {
|
|
type = "execute",
|
|
name = "config",
|
|
desc = "Open addon config panel.",
|
|
guiHidden = true,
|
|
func = function()
|
|
InterfaceOptionsFrame_OpenToCategory(addonName)
|
|
InterfaceOptionsFrame_OpenToCategory(addonName)
|
|
end
|
|
}
|
|
option.args.space0 = {
|
|
name = "",
|
|
type = 'description',
|
|
width = 'full',
|
|
cmdHidden = true,
|
|
order = 100,
|
|
}
|
|
option.args.configButton = {
|
|
order = 110,
|
|
type = "execute",
|
|
name = "Open Raid Profile Option",
|
|
desc = "Open Blizzard raid profile option.",
|
|
width = "double",
|
|
cmdHidden = true,
|
|
func = function()
|
|
InterfaceOptionsFrame_OpenToCategory(_G["CompactUnitFrameProfiles"])
|
|
end
|
|
}
|
|
option.args.descChange = {
|
|
name = "The raid frame is always shown when you adjust it in this panel.\n",
|
|
type = 'description',
|
|
width = 'full',
|
|
cmdHidden = true,
|
|
order = 111,
|
|
}
|
|
option.args.currentProfile = {
|
|
order = 112,
|
|
type = "description",
|
|
name = function(info) return "Current Raid Profile: " .. " "
|
|
.. NORMAL_FONT_COLOR_CODE
|
|
.. GetActiveRaidProfile()
|
|
.. FONT_COLOR_CODE_CLOSE .."\n" end,
|
|
width = "double",
|
|
}
|
|
option.args.frameStyle = {
|
|
order = 113,
|
|
type = "toggle",
|
|
name = "Use Raid-Style Party Frames",
|
|
desc = "Use Party Frames in the same style as the Raid Frames. These frames obey your Raid Frame options.",
|
|
get = function(info) return GetCVar(CVAR_FRAME_STYLE) == "1" end,
|
|
set = function(info, val)
|
|
if val then
|
|
SetCVar(CVAR_FRAME_STYLE, "1")
|
|
if CompactUnitFrameProfilesRaidStylePartyFrames then
|
|
CompactUnitFrameProfilesRaidStylePartyFrames:SetChecked(true)
|
|
end
|
|
else
|
|
SetCVar(CVAR_FRAME_STYLE, "0")
|
|
if CompactUnitFrameProfilesRaidStylePartyFrames then
|
|
CompactUnitFrameProfilesRaidStylePartyFrames:SetChecked(false)
|
|
end
|
|
end
|
|
end,
|
|
width = "double",
|
|
}
|
|
option.args.isAttached =
|
|
{
|
|
order = 114,
|
|
type = "toggle",
|
|
name = "Attach frame",
|
|
desc = "If Raid frame attaches to the raid panel on the left edge of the screen.",
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end,
|
|
width = "normal"
|
|
}
|
|
option.args.xOffset = {
|
|
order = 115,
|
|
name = "x Offset",
|
|
desc = "Pixels between the left of the screen and the topleft corner of the frame container.",
|
|
type = "range",
|
|
min = 0,
|
|
step = 1,
|
|
disabled = function(...) return addon:GetOption("isAttached") end,
|
|
max = math.floor(GetScreenWidth()-RAID_CONTAINER_WIDTH),
|
|
width = "normal",
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end
|
|
}
|
|
option.args.yOffset = {
|
|
order = 120,
|
|
name = "y Offset",
|
|
desc = "Pixels between the bottom of the screen and the topleft corner of the frame container.",
|
|
type = "range",
|
|
min = MINIMUM_RAID_CONTAINER_HEIGHT,
|
|
step = 1,
|
|
disabled = function(...) return addon:GetOption("isAttached") end,
|
|
max = math.floor(GetScreenHeight()),
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end
|
|
}
|
|
option.args.spacer3 = {
|
|
name = "",
|
|
type = 'description',
|
|
width = 'full',
|
|
cmdHidden = true,
|
|
order = 125,
|
|
}
|
|
option.args.frameHeight = {
|
|
order = 130,
|
|
name = "Frame Height",
|
|
desc = "Height of the frame block.",
|
|
type = "range",
|
|
min = MINIMUM_RAID_BLOCK_HEIGHT,
|
|
step = 1,
|
|
max = MAXIMUM_RAID_BLOCK_HEIGHT,
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end
|
|
}
|
|
option.args.frameWidth = {
|
|
order = 135,
|
|
name = "Frame Width",
|
|
desc = "Width of the frame block.",
|
|
type = "range",
|
|
min = MINIMUM_RAID_BLOCK_WIDTH,
|
|
step = 1,
|
|
max = MAXIMUM_RAID_BLOCK_WIDTH,
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end
|
|
}
|
|
option.args.containerHeight = {
|
|
order = 140,
|
|
name = "Container Height",
|
|
desc = "Pixels of the height of the frame container.",
|
|
type = "range",
|
|
min = MINIMUM_RAID_CONTAINER_HEIGHT,
|
|
step = 1,
|
|
max = math.floor(math.min(GetScreenHeight()-90,addon:GetOption("yOffset"))),
|
|
get = function(info) return addon:GetOption(info[#info]) end,
|
|
set = function(info, val) addon:SetOption(info[#info], val) end
|
|
}
|
|
return option
|
|
end
|
|
|
|
function addon:GetOption(optionName)
|
|
|
|
local manager = CompactRaidFrameManager
|
|
local top = manager.containerResizeFrame:GetTop()
|
|
local bottom = manager.containerResizeFrame:GetBottom()
|
|
local isAttached = (select(2, manager.containerResizeFrame:GetPoint(1)) == manager)
|
|
local left = manager.containerResizeFrame:GetLeft()
|
|
|
|
if (optionName == "isAttached") then
|
|
return isAttached
|
|
elseif (optionName == "xOffset") then
|
|
return math.floor(left)
|
|
elseif (optionName == "yOffset") then
|
|
return math.floor(top)
|
|
elseif (optionName == "containerHeight") then
|
|
return math.floor(top-bottom)
|
|
elseif (optionName == "frameWidth") then
|
|
return self.db.profile.options[addon:GetActiveRaidProfileId()]["frameWidth"]
|
|
elseif (optionName == "frameHeight") then
|
|
return self.db.profile.options[addon:GetActiveRaidProfileId()]["frameHeight"]
|
|
end
|
|
end
|
|
|
|
function addon:SetOption(optionName, value)
|
|
if not self.inCombat then
|
|
self.disableOptionPanelUpdate = true
|
|
|
|
self.needReload = true
|
|
if (optionName == "frameWidth") then
|
|
SetRaidProfileOption(GetActiveRaidProfile(), "frameWidth", value)
|
|
CompactUnitFrameProfiles_ApplyCurrentSettings()
|
|
elseif (optionName == "frameHeight") then
|
|
SetRaidProfileOption(GetActiveRaidProfile(), "frameHeight", value)
|
|
CompactUnitFrameProfiles_ApplyCurrentSettings()
|
|
else
|
|
local manager = CompactRaidFrameManager
|
|
if (optionName == "isAttached") then
|
|
manager.dynamicContainerPosition = value
|
|
end
|
|
if ( manager.dynamicContainerPosition ) then
|
|
SetRaidProfileSavedPosition(GetActiveRaidProfile(), true)
|
|
else
|
|
local topPoint, topOffset
|
|
local bottomPoint, bottomOffset
|
|
local leftPoint, leftOffset
|
|
|
|
local screenHeight = GetScreenHeight()
|
|
local top = manager.containerResizeFrame:GetTop()
|
|
local topDifference = 0
|
|
if (optionName == "yOffset") then
|
|
topDifference = value - top
|
|
top = value
|
|
end
|
|
if ( top > screenHeight / 2 ) then
|
|
topPoint = "TOP"
|
|
topOffset = screenHeight - top
|
|
else
|
|
topPoint = "BOTTOM"
|
|
topOffset = top
|
|
end
|
|
|
|
local bottom = manager.containerResizeFrame:GetBottom()
|
|
if (optionName == "yOffset") then
|
|
bottom = bottom + topDifference
|
|
if (bottom < 0) then
|
|
bottom = 0
|
|
end
|
|
elseif (optionName == "containerHeight") then
|
|
bottom = top - value
|
|
end
|
|
if ( bottom > screenHeight / 2 ) then
|
|
bottomPoint = "TOP"
|
|
bottomOffset = screenHeight - bottom
|
|
else
|
|
bottomPoint = "BOTTOM"
|
|
bottomOffset = bottom
|
|
end
|
|
|
|
local isAttached = (select(2, manager.containerResizeFrame:GetPoint(1)) == manager)
|
|
if (optionName == "isAttached") then
|
|
isAttached = value
|
|
end
|
|
if ( isAttached ) then
|
|
leftPoint = "ATTACHED"
|
|
leftOffset = 0
|
|
else
|
|
local screenWidth = GetScreenWidth()
|
|
local left = manager.containerResizeFrame:GetLeft()
|
|
if (optionName == "xOffset") then
|
|
left = value
|
|
end
|
|
if ( left > screenWidth / 2 ) then
|
|
leftPoint = "RIGHT"
|
|
leftOffset = screenWidth - left
|
|
else
|
|
leftPoint = "LEFT"
|
|
leftOffset = left
|
|
end
|
|
end
|
|
|
|
SetRaidProfileSavedPosition(GetActiveRaidProfile(), false
|
|
, topPoint, topOffset, bottomPoint, bottomOffset, leftPoint, leftOffset)
|
|
end
|
|
CompactRaidFrameManager_ResizeFrame_LoadPosition(CompactRaidFrameManager)
|
|
end
|
|
self.disableOptionPanelUpdate = false
|
|
addon:UnlockFrame()
|
|
addon:UpdateOptionsPanel()
|
|
else
|
|
addon:Print("Cannot change options in combat.")
|
|
end
|
|
end |