[TUTORIAL] Save/load data - two methods

+
[TUTORIAL] Save/load data - two methods

If you need to save/load some data for your mod, here is how to do it:


Method 1 - game facts system:

- connected to game saves(for example if you add fact, and load save before doing it, it will not be saved)
- facts are stored in RAM, game saves (after saving)
- can be used to save and load type int directly
- easy to use


Saving:

Code:
function FactsAdd( ID : string, optional value : int, optional validFor : int  )

Fact by ID passed as first argument is created (if it didn't exist), adds value (also to existing fact) passed as second argument, valid for value of type int passed as third argument(but I'm not sure how validFor works, probably it's pointing to some predefined game time value) if you want your fact to be valid forever, as a third argument pass - 1 or just don't pass third argument.


Code:
function FactsSet(ID : string, val : int, optional validFor : int )

Sets fact by ID passed as first argument to value passed as second argument, optionally sets its validFor to value passed as third argument.
Fact is automatically created if it didn't exist before.

Code:
function FactsSubstract(ID : string, optional val : int)

From a fact by ID passed as first argument, substracts value passed as second argument, val : int is optional, if you only pass fact ID to the function, it will substract 1 from the fact total value.

Loading:


Code:
function FactsQuerySum( ID : string ) : int

Returns value of fact by ID passed to it as argument.

Code:
function FactsDoesExist( ID : string ) : bool

Returns true if fact by ID passed as an argument exists, false if it doesn't.


Other:


Code:
function FactsRemove( ID : string ) : bool

Removes fact by ID passed as argument.

Functions I didn't test:

Code:
function FactsQuerySumSince( ID : string, sinceTime : EngineTime ) : int


Code:
function FactsQueryLatestValue( ID : string ) : int

See scripts/game/facts.ws, there are also "GameplayFacts", only difference seems to be that they can be set to be valid for exact time value instead of predefined values like "normal" facts, but you will have to test it.


Example:

Example exec functions to be called from console (to run it you need console enabler: http://www.nexusmods.com/witcher3/mods/1555/)

Create fact exampleFact, add 10 to its value.

Code:
exec function ExampleFactAdd ()
{
    FactsAdd( "exampleFact", 10, -1  );
}
Set exampleFact to 20.


Code:
exec function ExampleFactSet()
{
    FactsSet("exampleFact", 20, -1 );
}

Substract 5 from exampleFact.


Code:
exec function ExampleFactSubstract()
{
    FactsSubstract("exampleFact", 5);
}

Show exampleFact value.
Code:
exec function ExampleFactValue()
{
    var factString : string;
    factString = IntToString(FactsQuerySum("exampleFact"));
    GetWitcherPlayer().DisplayHudMessage(factString);
}
Show in hud message if exampleFact exists.
Code:
exec function ExampleFactDoesExist()
{
    GetWitcherPlayer().DisplayHudMessage(FactsDoesExist("exampleFact"));
}
Remove exampleFact.
Code:
exec function ExampleFactRemove()
{
    FactsRemove("exampleFact");
}





Method 2 - User.settings and class CInGameConfigWrapper:


- game saves-independent (for example you can save some data, load previous save before doing that and load it without problem),
- stored in RAM, and user.settings after using SaveUserSettings()
- saved data can be accessed by external app from user.settings (which I did in my tool changing sfx presets for example)
- can be used to save and load types string and bool directly
- must use options defined in xmls


Saving:

Code:
function SetVarValue( groupName : name, varName : name, varValue : string )

Sets option passed as second argument of type name, from options group passed as first argument of type name to value of type string.

Code:
function SaveUserSettings()

Saves changes to user.settings file. Without this you will save data only during game runtime.

Loading:

Code:
final function GetVarValue( groupCName : name, varCName : name ) : string;

Returns value of option passed as second argument, from options group passed as first argument.


Example:


To use it you may have to access CInGameConfigWrapper with CCommonGame method GetInGameConfigWrapper():

Code:
theGame.GetInGameConfigWrapper

Example exec functions to be called from console (to run it you need console enabler: http://www.nexusmods.com/witcher3/mods/1555/)


Save values (conversion needed for different types than string and bool):

Code:
exec function ExampleSaveValues( intValue : int, floatValue : float, boolValue : string)
    {
        var configWrapper : CInGameConfigWrapper;
        configWrapper = theGame.GetInGameConfigWrapper();
        
        configWrapper.SetVarValue('Examples', 'ExampleInt', IntToString(intValue));
        configWrapper.SetVarValue('Examples', 'ExampleFloat', FloatToString(floatValue)); 
        configWrapper.SetVarValue('Examples', 'ExampleBool', boolValue); 
    
        theGame.SaveUserSettings();
    }

Load values and show them in hud message (again conversion needed but from saved string to desired type):

Code:
exec function ExampleLoadValues()
    {
        var intValue : int;
        var floatValue : float;
        var boolValue : string;
        var showInt, showFloat, showBool : string;
        
        var configWrapper : CInGameConfigWrapper;
        configWrapper = theGame.GetInGameConfigWrapper();
        
        intValue = StringToInt(configWrapper.GetVarValue('Examples', 'ExampleInt'));
        floatValue = StringToFloat(configWrapper.GetVarValue('Examples', 'ExampleFloat'));
        boolValue = configWrapper.GetVarValue('Examples', 'ExampleBool');
        
        // for example purpose, because you could just load below varabiales directly (remember that in this method everything is saved as string)
        showInt = IntToString(intValue);
        showFloat = FloatToString(floatValue);
        showBool = boolValue;
        
        GetWitcherPlayer().DisplayHudMessage("intValue " + showInt + " floatValue " + showFloat + " boolValue " + showBool);
    }

Example menu options - you should practically always use for them "hideAlways" visibilityCondition because in most cases player doesn't need to see them in menu and possibly overwrite them:

Code:
    <?xml version="1.0" encoding="UTF-16"?>
    <UserConfig>
    <Group id="Examples" displayName="Examples">
        <VisibleVars>
            <Var id="intValue"      displayName="intValue"      displayType="SLIDER;-1000;1000;2000"        visibilityCondition="hideAlways"/>
            <Var id="floatValue"   displayName="floatValue"   displayType="SLIDER;-1000;1000;2000"        visibilityCondition="hideAlways"/>
            <Var id="boolValue"   displayName="boolValue"   displayType="TOGGLE"                        visibilityCondition="hideAlways"/>
        </VisibleVars>
    </Group>                
    </UserConfig>
 
Dude... If knew this "hideAlways" thing before I didn't have to use the hidden.xml to my mods...

But oh well... changing it now would be a huge amount of work.

Ty for the great information, though :D
 
Top Bottom