Convenient character and account wide saved variables management.
Many configurable add-ons offer players the option to set them either at a character and account-wide level. ZOS provides quite a few utilities to interact with saved variables and create both of those easily, however it is up to the add-on author to manage multiple tables and switch them accordingly. This can be inneficient and lead to errors, or even less performatic code due to conditional checks everywhere.
LibPreferences leverages Lua's metatable mechanism to provide a transparent way to create and use variables that can be switched between character and account-wide. It replaces the standard ZO_SavedVars methods with a single call to create the tables for you.
Usage
Lua Code:
-- syntax: LibPreferences.New(savedVariablesTable, defaults, options)
preferences = LibPreferences.New("ExampleVars", {
foo = "corge",
bar = "grault",
}, {
version = 1, -- ZO_SavedVars methods' version parameter
-- namespace = nil, -- ZO_SavedVars methods' namespace parameter
-- profile = GetWorldName(), -- ZO_SavedVars methods' profile parameter
})
d(preferences:IsAccountWide()) -- false
d(preferences.foo) -- corge
d(preferences.bar) -- grault
preferences.foo = "garply"
d(self.preferences.foo) -- garply
-- switch to account-wide settings
preferences:SetAccountWide(true)
d(preferences.foo) -- corge
d(preferences.bar) -- grault
preferences.foo = "waldo"
d(preferences.foo) -- waldo
-- switch back to character-specific settings
preferences:SetAccountWide(false)
d(preferences.foo) -- garply
-- you can also access directly the character or account preferences despite the current toggle
d(preferences.character.foo) -- garply
d(preferences.account.foo) -- waldo
-- the account-wide toggle state is saved as a preference on the character object only, so it gets persisted
d(preferences.character.accountWide) -- false
d(preferences.account.accountWide) -- nil
Limitations- you can't have a preference named account, character, target or accountWide
Utility methods
The table returned by
LibPreferences.New has a metatable assigned that provides these utility methods:
- IsAccountWide(): returns true if the preferences are set to account-wide
- SetAccountWide(toggle): changes the preferences between account-wide and character-specific
- Getter(name): returns a function that, when called, retrieves the value of the preference specified
- Setter(name): returns a function that, when called, sets the value of the preference specified (it expects a value as the first parameter)
- IsEqualGetter(name, value): returns a function that evaluates if the current value of the preference specified matches the value
- AccountWideGetter(): returns a function that retrieves the current account-wide toggle value
- AccountWideSetter(): returns a function that changes the account-wide toggle value (it expects a boolean parameter)
As a bonus you can get all those methods and typings on your coding environment if your IDE has support for EmmyLua-style docstrings, such such as the EmmyLua JetBrains plugin or the sumneko.lua VSCode extension.