diff --git a/.luacheckrc b/.luacheckrc index df5ae51f1..fb3ae74f5 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -582,6 +582,7 @@ stds.wow = { "CLOSE", "COMBO_POINTS", "DEFAULT_CHAT_FRAME", + "DELETE", "DISABLE", "DISABLED_FONT_COLOR", "ENABLE_COLORBLIND_MODE", diff --git a/.pkgmeta b/.pkgmeta index 5541aa524..e339fd402 100644 --- a/.pkgmeta +++ b/.pkgmeta @@ -20,6 +20,7 @@ ignore: externals: totalRP3/Libs/AceAddon-3.0: https://repos.curseforge.com/wow/ace3/trunk/AceAddon-3.0 totalRP3/Libs/AceConsole-3.0: https://repos.curseforge.com/wow/ace3/trunk/AceConsole-3.0 + totalRP3/Libs/AceDB-3.0: https://repos.curseforge.com/wow/ace3/trunk/AceDB-3.0 totalRP3/Libs/AceEvent-3.0: https://repos.curseforge.com/wow/ace3/trunk/AceEvent-3.0 totalRP3/Libs/AceSerializer-3.0: https://repos.curseforge.com/wow/ace3/trunk/AceSerializer-3.0 totalRP3/Libs/CallbackHandler-1.0: https://repos.curseforge.com/wow/callbackhandler/trunk/CallbackHandler-1.0 diff --git a/totalRP3/Core/StringUtil.lua b/totalRP3/Core/StringUtil.lua index 99d6316a5..916ce4660 100644 --- a/totalRP3/Core/StringUtil.lua +++ b/totalRP3/Core/StringUtil.lua @@ -103,3 +103,19 @@ function TRP3_StringUtil.FindClosestMatch(searchText, candidateList) return matchedText; end + +function TRP3_StringUtil.GenerateIncrementalName(predicate, prefix, suffix) + if not suffix then + suffix = " (%d)"; + end + + local name = prefix; + local count = 1; + + while not predicate(name) do + name = prefix .. string.format(suffix, count); + count = count + 1; + end + + return name; +end diff --git a/totalRP3/Locales/enUS.lua b/totalRP3/Locales/enUS.lua index a25228ca4..8c4e2df64 100644 --- a/totalRP3/Locales/enUS.lua +++ b/totalRP3/Locales/enUS.lua @@ -1159,6 +1159,22 @@ Putting your companion name in [brackets] will allow color and icon customizatio AUTOMATION_TEST_BUTTON = "Test condition", AUTOMATION_TEST_HELP = "Executes the supplied macro condition, printing the option it would select to the chat frame.", AUTOMATION_TEST_OUTPUT = "Test condition result: %s", + AUTOMATION_PROFILE_CREATE = "Create profile", + AUTOMATION_PROFILE_CREATE_HELP = "Creates a new profile.|n|nProfiles can be used to create character-specific rulesets for profile automation.", + AUTOMATION_PROFILE_CREATE_DIALOG_TITLE = "Enter a name for the new automation profile.", + AUTOMATION_PROFILE_CREATE_DIALOG_BUTTON1 = "Create", + AUTOMATION_PROFILE_COPY = "Copy profile", + AUTOMATION_PROFILE_COPY_HELP = "Copies all stored rules from this profile into the currently enabled one.|n|nThis will |cnRED_FONT_COLOR:irreversibly replace|r all rules configured on the current profile.", + AUTOMATION_PROFILE_COPY_DIALOG_TITLE = "Are you sure you want to replace all automation rules in the profile |W|cnGREEN_FONT_COLOR:%s|r|w with the rules from the profile |W|cnGREEN_FONT_COLOR:%s|r|w?", + AUTOMATION_PROFILE_COPY_DIALOG_BUTTON1 = "Copy", + AUTOMATION_PROFILE_ENABLE = "Enable profile", + AUTOMATION_PROFILE_ENABLE_HELP = "Enables this profile for the current character.", + AUTOMATION_PROFILE_DELETE = "Delete profile", + AUTOMATION_PROFILE_DELETE_HELP = "Deletes this profile.|n|nThis is an |cnRED_FONT_COLOR:irreversible|r process; deleted profiles cannot be restored.", + AUTOMATION_PROFILE_DELETE_DIALOG_TITLE = "Are you sure you want to delete the profile |W|cnGREEN_FONT_COLOR:%s|r|w?", + AUTOMATION_PROFILE_RESET = "Reset profile", + AUTOMATION_PROFILE_RESET_HELP = "Resets all stored rules on the currently enabled profile.|n|nThis will |cnRED_FONT_COLOR:irreversibly delete|r all rules configured on the current profile.", + AUTOMATION_PROFILE_RESET_DIALOG_TITLE = "Are you sure you want to reset all automation rules in the profile |W|cnGREEN_FONT_COLOR:%s|r|w?", --*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -- MISC diff --git a/totalRP3/Modules/Automation/Automation.lua b/totalRP3/Modules/Automation/Automation.lua index d3225e3b9..d5ca1d168 100644 --- a/totalRP3/Modules/Automation/Automation.lua +++ b/totalRP3/Modules/Automation/Automation.lua @@ -4,9 +4,21 @@ local TRP3_API = select(2, ...); local L = TRP3_API.loc; +local AceDB = LibStub:GetLibrary("AceDB-3.0"); + local AUTOMATION_UPDATE_THROTTLE = 1; local AUTOMATION_MESSAGE_THROTTLE = 5; +local SavedAutomationDefaults = { + profile = { + actions = { + ["**"] = { + expression = "", + }, + }, + }, +}; + local BaseContext = {}; function BaseContext:Error(message) @@ -54,9 +66,7 @@ end TRP3_Automation = TRP3_Addon:NewModule("Automation", "AceConsole-3.0"); function TRP3_Automation:OnLoad() - self.actions = {}; self.actionsByID = {}; - self.events = TRP3_API.CreateCallbackGroup(); self.conditionsByID = {}; self.conditionsByToken = {}; self.messageCooldowns = {}; @@ -68,8 +78,24 @@ function TRP3_Automation:OnLoad() end function TRP3_Automation:OnInitialize() - self.events:RegisterCallback(TRP3_API.GameEvents, "ADDONS_UNLOADING", self.OnUninitialize, self); - self:LoadSettings(TRP3_SavedAutomation); + local useDefaultProfile = true; + self.db = AceDB:New("TRP3_SavedAutomation", SavedAutomationDefaults, useDefaultProfile); + self.db.RegisterCallback(self, "OnProfileChanged"); + self.db.RegisterCallback(self, "OnProfileCopied"); + self.db.RegisterCallback(self, "OnProfileDeleted"); + self.db.RegisterCallback(self, "OnProfileReset"); + + -- The initial implementation of automation used one settings table + -- without profile support. For users with saved automation rules, we + -- need to import them into the new profile-based system. + + if TRP3_SavedAutomation.actions then + for actionID, actionSettings in pairs(TRP3_SavedAutomation.actions) do + self.db.profile.actions[actionID].expression = actionSettings.expression; + end + + TRP3_SavedAutomation.actions = nil; + end TRP3_API.slash.registerCommand({ id = "set", @@ -106,8 +132,20 @@ function TRP3_Automation:OnDisable() self.ticker = nil; end -function TRP3_Automation:OnUninitialize() - TRP3_SavedAutomation = self:SaveSettings(); +function TRP3_Automation:OnProfileChanged(_, _, profileName) + TRP3_AutomationEvents:TriggerEvent("OnProfileChanged", profileName); +end + +function TRP3_Automation:OnProfileCopied() + TRP3_AutomationEvents:TriggerEvent("OnProfileModified", self.db:GetCurrentProfile()); +end + +function TRP3_Automation:OnProfileDeleted(_, _, profileName) + TRP3_AutomationEvents:TriggerEvent("OnProfileDeleted", profileName); +end + +function TRP3_Automation:OnProfileReset() + TRP3_AutomationEvents:TriggerEvent("OnProfileModified", self.db:GetCurrentProfile()); end function TRP3_Automation:OnDirtyEvent() @@ -132,32 +170,30 @@ function TRP3_Automation:OnContextMessage(message) TRP3_Addon:Print(message); end -function TRP3_Automation:LoadSettings(settings) - local actions = {}; - - if type(settings) ~= "table" then - settings = {}; - end - - if type(settings.actions) ~= "table" then - settings.actions = {}; - end +function TRP3_Automation:GetAllProfiles() + return self.db:GetProfiles(); +end - for actionID, actionSettings in pairs(settings.actions) do - actions[actionID] = { expression = actionSettings.expression }; - end +function TRP3_Automation:GetCurrentProfile() + return self.db:GetCurrentProfile(); +end - self.actions = actions; +function TRP3_Automation:SetCurrentProfile(profileName) + self.db:SetProfile(profileName); end -function TRP3_Automation:SaveSettings() - local settings = { actions = {} }; +function TRP3_Automation:DeleteProfile(profileName) + local silent = true; + self.db:DeleteProfile(profileName, silent); +end - for actionID, actionSettings in pairs(self.actions) do - settings.actions[actionID] = { expression = actionSettings.expression }; - end +function TRP3_Automation:CopyProfile(profileName) + local silent = true; + self.db:CopyProfile(profileName, silent); +end - return settings; +function TRP3_Automation:ResetCurrentProfile() + self.db:ResetProfile(); end function TRP3_Automation:RegisterAction(action) @@ -209,7 +245,7 @@ function TRP3_Automation:GetConditionByToken(conditionToken) end function TRP3_Automation:GetActionExpression(actionID) - local actionSettings = self.actions[actionID]; + local actionSettings = self.db.profile.actions[actionID]; local actionExpression = ""; if actionSettings then @@ -220,8 +256,8 @@ function TRP3_Automation:GetActionExpression(actionID) end function TRP3_Automation:SetActionExpression(actionID, expression) - self.actions[actionID] = self.actions[actionID] or {}; - self.actions[actionID].expression = string.trim(expression or ""); + self.db.profile.actions[actionID].expression = string.trim(expression or ""); + TRP3_AutomationEvents:TriggerEvent("OnProfileModified", self.db:GetCurrentProfile()); self:ResetMessageCooldowns(); self:MarkDirty(); end diff --git a/totalRP3/Modules/Automation/Automation_Settings.lua b/totalRP3/Modules/Automation/Automation_Settings.lua index fd506ebb6..3c431ca0f 100644 --- a/totalRP3/Modules/Automation/Automation_Settings.lua +++ b/totalRP3/Modules/Automation/Automation_Settings.lua @@ -18,6 +18,9 @@ function TRP3_AutomationSettingsMixin:OnLoad() self.Actions:SetScript("OnEnter", function(_, ...) self:OnActionDropDownEnter(...); end); self.Actions:SetScript("OnLeave", function(_, ...) self:OnActionDropDownLeave(...); end); + MSA_DropDownMenu_SetInitializeFunction(self.Profiles, function(_, ...) self:OnProfileDropDownInitialize(...); end); + MSA_DropDownMenu_SetWidth(self.Profiles, self.Profiles:GetWidth()); + self.SaveButton:RegisterCallback("OnClick", self.OnSaveButtonClicked, self); self.TestButton:RegisterCallback("OnClick", self.OnTestButtonClicked, self); self.TestButton:SetText(L.AUTOMATION_TEST_BUTTON); @@ -39,12 +42,28 @@ function TRP3_AutomationSettingsMixin:OnLoad() ScrollUtil.RegisterScrollBoxWithScrollBar(self.EditorScrollBox, self.EditorScrollBar); ScrollUtil.AddManagedScrollBarVisibilityBehavior(self.EditorScrollBox, self.EditorScrollBar, scrollBoxAnchorsWithBar, scrollBoxAnchorsWithoutBar); + + TRP3_AutomationEvents.RegisterCallback(self, "OnProfileChanged"); + TRP3_AutomationEvents.RegisterCallback(self, "OnProfileModified"); + TRP3_AutomationEvents.RegisterCallback(self, "OnProfileDeleted"); end function TRP3_AutomationSettingsMixin:OnShow() self:Update(); end +function TRP3_AutomationSettingsMixin:OnProfileChanged() + self:Update(); +end + +function TRP3_AutomationSettingsMixin:OnProfileModified() + self:Update(); +end + +function TRP3_AutomationSettingsMixin:OnProfileDeleted() + self:Update(); +end + function TRP3_AutomationSettingsMixin:OnActionDropDownEnter() local tooltip = TRP3_MainTooltip; tooltip:SetOwner(self.Actions, "ANCHOR_RIGHT"); @@ -68,6 +87,51 @@ function TRP3_AutomationSettingsMixin:OnActionSelected(actionID) self:SetSelectedActionID(actionID); end +function TRP3_AutomationSettingsMixin:OnActionDropDownInitialize() + self:PopulateActionDropDown(); +end + +function TRP3_AutomationSettingsMixin:OnProfileDropDownInitialize() + self:PopulateProfileDropDown(); +end + +function TRP3_AutomationSettingsMixin:OnCreateProfileSelected() + StaticPopup_Show("TRP3_AUTOMATION_CREATE_PROFILE"); + MSA_CloseDropDownMenus(); +end + +function TRP3_AutomationSettingsMixin:OnEnableProfileSelected(profileName) + TRP3_AutomationUtil.SetCurrentProfile(profileName); + MSA_CloseDropDownMenus(); +end + +function TRP3_AutomationSettingsMixin:OnCopyProfileSelected(profileName) + local textArg1 = TRP3_AutomationUtil.GetCurrentProfile(); + local textArg2 = profileName; + local data = profileName; + + StaticPopup_Show("TRP3_AUTOMATION_COPY_PROFILE", textArg1, textArg2, data); + MSA_CloseDropDownMenus(); +end + +function TRP3_AutomationSettingsMixin:OnDeleteProfileSelected(profileName) + local textArg1 = profileName; + local textArg2 = nil; + local data = profileName; + + StaticPopup_Show("TRP3_AUTOMATION_DELETE_PROFILE", textArg1, textArg2, data); + MSA_CloseDropDownMenus(); +end + +function TRP3_AutomationSettingsMixin:OnResetProfileSelected() + local textArg1 = TRP3_AutomationUtil.GetCurrentProfile(); + local textArg2 = nil; + local data = TRP3_AutomationUtil.GetCurrentProfile(); + + StaticPopup_Show("TRP3_AUTOMATION_RESET_PROFILE", textArg1, textArg2, data); + MSA_CloseDropDownMenus(); +end + function TRP3_AutomationSettingsMixin:OnSaveButtonClicked() local actionID = self:GetSelectedActionID(); local expression = self:GetEditorInputText(); @@ -159,6 +223,121 @@ function TRP3_AutomationSettingsMixin:SetActionDropDownText(text) MSA_DropDownMenu_SetText(self.Actions, text); end +function TRP3_AutomationSettingsMixin:PopulateProfileListMenu(menuLevel) + local profiles = TRP3_AutomationUtil.GetAllProfiles(); + local currentProfileName = TRP3_AutomationUtil.GetCurrentProfile(); + + local function SortCompareProfiles(a, b) + return TRP3_StringUtil.SortCompareStrings(a, b); + end + + table.sort(profiles, SortCompareProfiles); + + for _, profileName in ipairs(profiles) do + local displayText = profileName; + + if profileName == currentProfileName then + displayText = string.format("|cff33ff99%s|r", profileName); + end + + MSA_DropDownMenu_AddButton({ + text = displayText, + value = profileName, + func = function() self:OnEnableProfileSelected(profileName); end, + notCheckable = true, + hasArrow = true, + }, menuLevel); + end + + MSA_DropDownMenu_AddSeparator({}, menuLevel); + + MSA_DropDownMenu_AddButton({ + text = "Create profile", + func = function() self:OnCreateProfileSelected(); end, + notCheckable = true, + tooltipTitle = L.AUTOMATION_PROFILE_CREATE, + tooltipText = L.AUTOMATION_PROFILE_CREATE_HELP, + tooltipOnButton = true, + }, menuLevel); +end + +function TRP3_AutomationSettingsMixin:PopulateProfileActionMenu(menuLevel, profileName) + -- Enable profile button. + + if not TRP3_AutomationUtil.IsCurrentProfile(profileName) then + MSA_DropDownMenu_AddButton({ + text = "Enable profile", + func = function() self:OnEnableProfileSelected(profileName); end, + notCheckable = true, + tooltipTitle = L.AUTOMATION_PROFILE_ENABLE, + tooltipText = L.AUTOMATION_PROFILE_ENABLE_HELP, + tooltipOnButton = true, + }, menuLevel); + end + + -- Copy profile button; this doesn't make sense to show for the current + -- profile as AceDB's idea of "copying" a profile means to import all of + -- the settings from another named profile into the current one. + + if not TRP3_AutomationUtil.IsCurrentProfile(profileName) then + MSA_DropDownMenu_AddButton({ + text = "Copy profile", + func = function() self:OnCopyProfileSelected(profileName); end, + notCheckable = true, + tooltipTitle = L.AUTOMATION_PROFILE_COPY, + tooltipText = L.AUTOMATION_PROFILE_COPY_HELP, + tooltipOnButton = true, + }, menuLevel); + end + + -- Delete profile button; AceDB doesn't allow us to delete the current + -- profile so don't show it for the active one. + -- + -- Additionally we don't want to allow users to delete the default + -- profile. If they do it'll get recreated when they log into a new + -- character anyway. + + if not TRP3_AutomationUtil.IsCurrentProfile(profileName) and not TRP3_AutomationUtil.IsDefaultProfile(profileName) then + MSA_DropDownMenu_AddButton({ + text = "Delete profile", + func = function() self:OnDeleteProfileSelected(profileName); end, + notCheckable = true, + tooltipTitle = L.AUTOMATION_PROFILE_DELETE, + tooltipText = L.AUTOMATION_PROFILE_DELETE_HELP, + tooltipOnButton = true, + }, menuLevel); + end + + -- Reset profile button; AceDB only allows this to work on the currently + -- selected profile. + + if TRP3_AutomationUtil.IsCurrentProfile(profileName) then + MSA_DropDownMenu_AddButton({ + text = "Reset profile", + func = function() self:OnResetProfileSelected(); end, + notCheckable = true, + tooltipTitle = L.AUTOMATION_PROFILE_RESET, + tooltipText = L.AUTOMATION_PROFILE_RESET_HELP, + tooltipOnButton = true, + }, menuLevel); + end +end + +function TRP3_AutomationSettingsMixin:PopulateProfileDropDown() + local menuLevel = MSA_DROPDOWNMENU_MENU_LEVEL; + + if menuLevel == 1 then + self:PopulateProfileListMenu(menuLevel); + elseif menuLevel == 2 then + local profileName = MSA_DROPDOWNMENU_MENU_VALUE; + self:PopulateProfileActionMenu(menuLevel, profileName); + end +end + +function TRP3_AutomationSettingsMixin:SetProfileDropDownText(text) + MSA_DropDownMenu_SetText(self.Profiles, text); +end + function TRP3_AutomationSettingsMixin:SetEditorExampleText(exampleText) -- This ordering of calls is important as repeated calls to -- ApplyDefaultText don't work unless the input text is cleared. @@ -186,9 +365,118 @@ end function TRP3_AutomationSettingsMixin:Update() local action = self:GetSelectedAction(); + local currentProfileName = TRP3_AutomationUtil.GetCurrentProfile(); self:SetEditorShown(action ~= nil); self:SetEditorExampleText(action and action.example or ""); self:SetEditorInputText(action and action.expression or ""); self:SetActionDropDownText(action and action.name or NONE); + self:SetProfileDropDownText(currentProfileName); +end + +------------------------------------------------------------------------------ +-- Static Popup Dialogs + +do + local function IsValidProfileName(profileName) + return string.trim(profileName) ~= "" and not TRP3_AutomationUtil.DoesProfileExist(profileName); + end + + local function OnDialogAccept(self) + local profileName = self.editBox:GetText(); + + if IsValidProfileName(profileName) then + TRP3_AutomationUtil.SetCurrentProfile(profileName); + end + end + + local function OnDialogShow(self) + self.editBox:SetText(TRP3_AutomationUtil.GenerateProfileName()); + end + + local function OnDialogEditBoxEnterPressed(self) + local parent = self:GetParent(); + parent.button1:Click(); + end + + local function OnDialogEditBoxTextChanged(self) + local parent = self:GetParent(); + local profileName = self:GetText(); + + parent.button1:SetEnabled(IsValidProfileName(profileName)); + end + + local function OnDialogEditBoxEscapePressed(self) + local parent = self:GetParent(); + parent:Hide(); + end + + StaticPopupDialogs["TRP3_AUTOMATION_CREATE_PROFILE"] = { + text = L.AUTOMATION_PROFILE_CREATE_DIALOG_TITLE, + button1 = L.AUTOMATION_PROFILE_CREATE_DIALOG_BUTTON1, + button2 = CANCEL, + hasEditBox = 1, + OnAccept = OnDialogAccept, + OnShow = OnDialogShow, + EditBoxOnEnterPressed = OnDialogEditBoxEnterPressed, + EditBoxOnTextChanged = OnDialogEditBoxTextChanged, + EditBoxOnEscapePressed = OnDialogEditBoxEscapePressed, + hideOnEscape = 1, + timeout = 0, + exclusive = 1, + whileDead = 1, + }; +end + +do + local function OnDialogAccept(self) + local profileName = self.data; + TRP3_AutomationUtil.CopyProfile(profileName); + end + + StaticPopupDialogs["TRP3_AUTOMATION_COPY_PROFILE"] = { + text = L.AUTOMATION_PROFILE_COPY_DIALOG_TITLE, + button1 = L.AUTOMATION_PROFILE_COPY_DIALOG_BUTTON1, + button2 = CANCEL, + OnAccept = OnDialogAccept, + hideOnEscape = 1, + timeout = 0, + exclusive = 1, + whileDead = 1, + }; +end + +do + local function OnDialogAccept(self) + local profileName = self.data; + TRP3_AutomationUtil.DeleteProfile(profileName); + end + + StaticPopupDialogs["TRP3_AUTOMATION_DELETE_PROFILE"] = { + text = L.AUTOMATION_PROFILE_DELETE_DIALOG_TITLE, + button1 = DELETE, + button2 = CANCEL, + OnAccept = OnDialogAccept, + hideOnEscape = 1, + timeout = 0, + exclusive = 1, + whileDead = 1, + }; +end + +do + local function OnDialogAccept(self) + TRP3_AutomationUtil.ResetCurrentProfile(); + end + + StaticPopupDialogs["TRP3_AUTOMATION_RESET_PROFILE"] = { + text = L.AUTOMATION_PROFILE_RESET_DIALOG_TITLE, + button1 = RESET, + button2 = CANCEL, + OnAccept = OnDialogAccept, + hideOnEscape = 1, + timeout = 0, + exclusive = 1, + whileDead = 1, + }; end diff --git a/totalRP3/Modules/Automation/Automation_Settings.xml b/totalRP3/Modules/Automation/Automation_Settings.xml index 6ac35f3c7..3c38bc9dd 100644 --- a/totalRP3/Modules/Automation/Automation_Settings.xml +++ b/totalRP3/Modules/Automation/Automation_Settings.xml @@ -43,6 +43,13 @@ https://raw.githubusercontent.com/Meorawr/wow-ui-schema/main/UI.xsd"> + + + + + + + diff --git a/totalRP3/Modules/Automation/Automation_Util.lua b/totalRP3/Modules/Automation/Automation_Util.lua index 0545a7b80..2c516edab 100644 --- a/totalRP3/Modules/Automation/Automation_Util.lua +++ b/totalRP3/Modules/Automation/Automation_Util.lua @@ -6,8 +6,64 @@ local L = TRP3_API.loc; local hasRegisteredSettings; +TRP3_AutomationEvents = TRP3_API.CreateCallbackRegistryWithEvents({ + OnProfileChanged = "OnProfileChanged", -- Triggers when the current profile changes. + OnProfileModified = "OnProfileUpdated", -- Triggers when a profile is edited. + OnProfileDeleted = "OnProfileDeleted", -- Triggers when a profile is deleted. +}); + TRP3_AutomationUtil = {}; +function TRP3_AutomationUtil.GetAllProfiles() + return TRP3_Automation:GetAllProfiles(); +end + +function TRP3_AutomationUtil.GetCurrentProfile() + return TRP3_Automation:GetCurrentProfile(); +end + +function TRP3_AutomationUtil.SetCurrentProfile(profileName) + return TRP3_Automation:SetCurrentProfile(profileName); +end + +function TRP3_AutomationUtil.DoesProfileExist(profileName) + return tContains(TRP3_Automation:GetAllProfiles(), profileName); +end + +function TRP3_AutomationUtil.IsDefaultProfile(profileName) + return profileName == "Default"; +end + +function TRP3_AutomationUtil.IsCurrentProfile(profileName) + return profileName == TRP3_Automation:GetCurrentProfile(); +end + +function TRP3_AutomationUtil.DeleteProfile(profileName) + return TRP3_Automation:DeleteProfile(profileName); +end + +function TRP3_AutomationUtil.CopyProfile(profileName) + return TRP3_Automation:CopyProfile(profileName); +end + +function TRP3_AutomationUtil.ResetCurrentProfile() + return TRP3_Automation:ResetCurrentProfile(); +end + +function TRP3_AutomationUtil.GenerateProfileName() + local playerName = UnitNameUnmodified("player"); + local serverName = GetRealmName(); + + local profileNamePrefix = string.format("%s - %s", playerName, serverName); + local profiles = tInvert(TRP3_Automation:GetAllProfiles()); + + local function IsAvailableProfileName(profileName) + return profiles[profileName] == nil; + end + + return TRP3_StringUtil.GenerateIncrementalName(IsAvailableProfileName, profileNamePrefix); +end + function TRP3_AutomationUtil.RegisterAction(action) TRP3_Automation:RegisterAction(action); end diff --git a/totalRP3/totalRP3.toc b/totalRP3/totalRP3.toc index 15980c204..43e030a83 100644 --- a/totalRP3/totalRP3.toc +++ b/totalRP3/totalRP3.toc @@ -22,6 +22,7 @@ Libs\LibStub\LibStub.lua Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml Libs\AceAddon-3.0\AceAddon-3.0.xml Libs\AceConsole-3.0\AceConsole-3.0.xml +Libs\AceDB-3.0\AceDB-3.0.xml Libs\AceEvent-3.0\AceEvent-3.0.xml Libs\AceSerializer-3.0\AceSerializer-3.0.xml Libs\TaintLess\TaintLess.xml