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