Saving Local Variables Between Sessions

Gamepedia documents that

If you want to save a local value, you have to first read it from the global environment (_G table) on ADDON_LOADED, then return it into the global environment before the player logs out.

What would this look like? For example, my addon has several global variables and a table that I want to save between sessions. Would this work?

When the addon loads, the game executes this line:
local fooBar = _G.fooBar

Upon logout, reload, etc., the game executes this line
_G.fooBar = fooBar

And how would fooBar be specified as a parameter to the TOC’s ## SavedVariables command?

Hope this wasn’t too confusing.

The only mechanism for saving variable data between sessions are via the ## SavedVariables: and ## SavedVariablesPerCharacter: designations in the .toc.

The first saves entities to the global SavedVariables folder under WTF and the second saves into the individual realm/character SavedVariables folder under WTF.

## SavedVariables: MYADDON_SAVEDDVAR1, MYADDON_SAVEDDVAR2
You can have multiple saved variable spaces for each type if required.

The game doesn’t allocate the space(s), just creates a place holder in the global table for each one so the names must be globaly unique to your addon (Prefix with the addon name or acronym if you think that’s sufficient. Use all upper case and add _DATA or some such if you’re not sure or want to differentiate with local/addon level data ADDONNAME_DATA = {}, get creative :wink:).

The best place to initialise your saved variables is at the PLAYER_LOGIN event as it only fires once after all addons have loaded (including saved variables) and before PLAYER_ENTERING_WORLD.

if event == "PLAYER_LOGIN"  then
    if not MYADDON_SAVEDDVAR1 then -- first time the addon is used
        MYADDON_SAVEDDVAR1 = {} -- allocate a table to store your saved variables (the table will be saved to disk on logout)
        -- Now, load the table with defaults if needed.
        MYADDON_SAVEDDVAR1.foobar = "Some Value"
        MYADDON_SAVEDDVAR1.Frame1 = {
            width=100,
            height=150,
        }
    end
    -- Initialise the addon with the Saved Variables information (new or loaded from disk)
    local foobar = MYADDON_SAVEDDVAR1.foobar
    local Frame1 = CreateFrame("Frame", "MyAddon_Frame1", UIParent)
    Frame1:SetSize(MYADDON_SAVEDDVAR1.Frame1.width, MYADDON_SAVEDDVAR1.Frame1.height)
end

[Example code only]
The Saved Variables are only written out to disk when a session ends so you can’t change during play as changes will be overwritten. They are saved to a filename that uses the addon name with an extension of .lua (.lua.bak files will also be created)

In short, locals don’t get saved unless they are copied to your global SV space before logout like your examples show.

2 Likes

I’m trying to save/restore the position of a frame across reloads, logouts, exits, etc. The position is stored in an array, framePosition.

framePosition = {f:GetPoint())}

In the .toc,

SavedVariablesPerCharacter: framePosition

In the ADDON_LOADED handler, the frame is set to its default, initial position.

    if not framePosition  then
        framePosition = { "CENTER", nil, "CENTER", 0, 0 }
    end

In the frame display code, the location is restored

f:SetPoint( framePosition[1],
framePosition[2],
framePosition[3],
framePosition[4],
framePosition[5] )

If I understand how this works, by the time the addon is loaded, but before the ADDON_LOADED event is fired, this code has been executed. But, I’m missing something because this doesn’t work so clearly I do not understand what exactly is going on.

However, I do have one question: where/how is framePosition to be declared? Since this is Lua, is it parsed as global within the if/then clause since it’s not declared as global?

Anyway, any help would be much appreciated.

You can’t store the frame reference of the relative frame that f is attached to so if possible, store it’s name and retrieve it from the global table next time:

local p,r,t,x,y = f:GetPoint(1)
if r:GetName() then
    r = r:GetName()
else
    r = "UIParent"
end
framePosition = {p, r, t, x, y)

and to restore:

f:SetPoint(framePosition[1], _G[framePosition[2]], framePosition[3], framePosition[4], framePosition[5])

If f is attached to a frame that belongs to your addon, you don’t need to store r

framePosition = {p, t, x, y)
f:SetPoint(framePosition[1], MyAddonFrame, framePosition[2], framePosition[3], framePosition[4])

If f is attached to a frame that doesn’t have a name and you can’t just attach it to UIParent then you need some way of “finding” the frame to attach too when you login.

The ADDON_LOADED event fires first when your addon loads and for every addon that loads after that (you don’t get the event for any addons that load before yours).

If the frame you’re saving/restoring belongs to another addon then maybe consider using the PLAYER_LOGIN event as that fires only once, after all addons identified to load at startup have finished loading and before you enter the world.

Variables declared in the toc as ## SavedVariables or ## SavedVariablesPerCharacter are initially created in the global table with a nil value. When you logout/exit the value of the variables (including nil) will be written to the addons SavedVariables file(s) under the WTF folder (location being dependent on whether the variable is global or per character).

The game subsequently loads whatever has been saved in the various SV files as Globals so using unique variable names is important.

If you delete a SV file for your addon before the game starts, it will start again at nil.

2 Likes

Thanks for the response. Much appreciated. Got it working now.

Hi,
I’ve been messing with an addon, and made it save the variables globally.
Now the file is gone, but it seems to be working.
My guess is that they now save on the server side?
It used to save locally, but I think they changed it.
Do you know for sure?

They’re saved locally:

If the .toc has ##SavedVariables: xxxx then
[Wow folder]\_[client version]_\WTF\Account\[your account]\SavedVariables\[addon name.lua]

If it has ##SavedVariablesPerCharacter: xxxx then
[Wow folder]\_[client version]_\WTF\Account\[your account]\[realm]\[character]\SavedVariables\[addon name.lua]

1 Like

That’s why I think they changed it to server side.
The first folder is now completely empty.

Which “first folder” ([Wow folder])?

Start the BattleNet launcher
Select the game version you addon is for
Click the gear button (beside the blue Play button)
Click “Show in Explorer”

That should take you to the Wow folder with the _[client version]_ folder selected.

Open that folder and then follow the path (from above starting at WTF) down to the SavedVariables folder you’re SavedVariables file ([addon name].lua) is in.

Yes, it’s now empty.
The addons work, and settings and variables save.
The local ones have files for each toon.
The account one is empty.

I understand what you mean by this? local ones what?

##SavedVariablesPerCharacter: xxxxthen[Wow folder]_[client version]_\WTF\Account[your account][realm][character]\SavedVariables[addon name.lua]`

This one is the empty one:
##SavedVariables: xxxx then
[Wow folder]\_[client version]_\WTF\Account\[your account]\SavedVariables\

Toon specific setting save to the drive, in the correct path.

The account wide must be server side now.

Are you saying the .toc originally had:

##SavedVariablesPerCharacter: xxxx

and it now has:
##SavedVariables: xxxx
instead (or as well)?

The global space is shared across all addons (and the Blizz. UI). If you wanted per character plus global saved settings you would have to use a different variable name for each and initialise (update etc.) them seperately.

I changed it from ##SavedVariablesPerCharacter: to ##SavedVariables:, to make the settings global.
It works great now, but I was looking for the file where it saves the settings, and that entire folder is empty. That’s why I think it’s stored on the server now.
The PerCharacter files do save locally for each toon.
I think it must have been changed to server side at some point.
Does your folder have files in it?

It’s not just the one addon I changed that’s missing a config file, that entire folder is empty.

There are several folders named SavedVariables under WTF (one directly under WTF, another under Account) These are not the correct folder(s) for global SVs.

You have to go one folder lower (under the folder that is named after your account user name and has your character realm name folders). The correct SavedVariables folder will be in amongst those.

So, even thought the folder structure exists, it’s not used?
There is no global for ALL realms?
All of the setting save per realm?

The folders wil be

ARealm
BRealm
CRealm
SavedVariables
TRealm

The .lua files for “global” saved variables will be in the SavedVariables folder here. The global “All Realms” is for “all realms” assigned to an account user name.

Under each realm is the character folders for that realm and under each character folder is another SavedVariables folder for the per character .lua files,

There is a blank SavedVariables folder under Account.
The SavedVariables folder directly under WTF holds some Blizz. data.