Skip to content

Commit

Permalink
Add support for automation profiles (#788)
Browse files Browse the repository at this point in the history
* Add support for automation profiles

The current automation system doesn't scale too well when dealing with
multiple characters. The "Change profile" action ends up being
with rules that are often character-specific, meaning users need to
populate this rule with long and complicated rulesets if they play
multiple characters - and then need to update it each time they
make a new character.

To alleviate this problem a new profile system has been added that
functions similarly to profiles in Ace-based addons.

The dropdown to the right of the automation panel allows users to
create, enable, or modify a profile. Profiles can be activated on a
per-character basis, but will always default to a shared "Default"
profile when the addon is first loaded on a new character.

* Correctly migrate settings to new format

* Plural normalization

* Remove commented tooltip code

* Directly read/write expressions from DB

This removes the need for a few additional event handlers; while one
would prefer to keep the storage format separate from the runtime format
there's also no real need right now.

* I'll reverse you in a minute

---------

Co-authored-by: Solanya <[email protected]>
  • Loading branch information
Meorawr and Solanya authored Nov 6, 2023
1 parent 51f3916 commit ee6d757
Show file tree
Hide file tree
Showing 9 changed files with 451 additions and 29 deletions.
1 change: 1 addition & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ stds.wow = {
"CLOSE",
"COMBO_POINTS",
"DEFAULT_CHAT_FRAME",
"DELETE",
"DISABLE",
"DISABLED_FONT_COLOR",
"ENABLE_COLORBLIND_MODE",
Expand Down
1 change: 1 addition & 0 deletions .pkgmeta
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions totalRP3/Core/StringUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions totalRP3/Locales/enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
94 changes: 65 additions & 29 deletions totalRP3/Modules/Automation/Automation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 = {};
Expand All @@ -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",
Expand Down Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit ee6d757

Please sign in to comment.