Jump to content

Custom CheckpointRecords


tracktwo

Recommended Posts

I'd like to add a custom checkpointrecord to one of my classes in a custom package to get some additional data saved in the saved game, but so far I haven't been able to get it to work. I see in the LZMutator there are some mutators with custom checkpoint records, do these actually get loaded and saved correctly?

 

It looks from the logs like the game scans all the actors to find things to save/load. So I figured as long as I make my class a subclass of Actor and define a CheckpointRecord struct, magic would happen... but this doesn't seem to be the case. Has anyone successfully done this?

Link to comment
Share on other sites

I had to add Mutator class to Default__Checkpoint_TacticalGame list of saved classes to make it work on tactical layer. But you need an object reference to make it work. Engine.Mutator already was there, but you can't import your new class reference.

 

If you're subclassing an existing class and it is already in Default__Checkpoint* list, saves will work. If it's not in the list, but you can add it there, saves will work. If you're making a completely new class, you can use a mutator for the sole purpose of saving your variables.

Link to comment
Share on other sites

Sigh. I need a strategic layer mutator, and while I can add the Mutate calls to invoke my strategy layer mutator, and add the class to the list of strategy layer mutators to load, Engine.Mutator itself is not imported in XComStrategyGame so I can't add it to the default properties list in Checkpoint_StrategyGame.

 

I guess I'll need to go the subclass route and try to subclass one of the existing classes with checkpoints. I tried subclassing XGRecapSaveData and while it saved my new fields correctly it crashed on load. not sure if that's cause I did something wrong or if it's cause XGRecapSaveData is a native class. I'll try some experiments with another class that isn't native.

 

EDIT:

 

I still can't get subclassing to work, possibly there are issues with trying to add a checkpoint record to a subclass whose superclass also has one?

 

However, I did find a working solution: Create my own strategy save game class! The class to use for strategy saves is stored in the XComGameInfo.StrategySaveGameClass variable. So, I just created my own class that inherits from Checkpoint_StrategyGame and adds my class to the default properties (the default properties of the parent class are set first, so all vanilla classes remain in effect). Then I created a mutator class for the strategic layer that sets the variable in XComGameInfo to my class in the GameInfoInitGame hook.

 

This isn't really super viable, though, as really only one mod can do this trick and everyone else is out of luck. Maybe I can cook up some way to make this class load the default properties from a .ini file. I can make the new class a config class, but the parent class variable isn't a config var, so I don't believe it'll read it. And I'm not sure what will happen if I made those vars config vars when the class isn't a config class.

Edited by tracktwo
Link to comment
Share on other sites

I believe we can make child classes of Checkpoint_StrategyGame classes and Checkpoint_TacticalGame classes. The trick will be to initialize StrategySaveGameClass and TacticalSaveGameClass variables in XComHeadquartersGame and XComGameInfo classes. I think we can do it by converting

var Class TacticalSaveGameClass;
var Class StrategySaveGameClass;

into

var config Class TacticalSaveGameClass;
var config Class StrategySaveGameClass;

Both are defined in XComGameInfo class.

 

Property flags for both are zero, we need to add Config flag to both of them:

[BEFORE_CODE]
<%s 1>
<%s 0>
<%u 0x00000000>                    // flags L
<%u 0x00000000>                    // flags H
[AFTER_CODE]
<%s 1>
<%s 0>
<%u 0x00004000>                    // flags L: Config
<%u 0x00000000>                    // flags H

After this we should be able to initialize both variables in DefaultGame.ini with something like

[XComGame.XComGameInfo]
TacticalSaveGameClass=class'Checkpoint_TacticalGame_Mod'

[XComStrategyGame.XComHeadquartersGame]
StrategySaveGameClass=class'Checkpoint_StrategyGame_Mod'

Checkpoint_TacticalGame_Mod and Checkpoint_StrategyGame_Mod classes should point to the same (or different) config file where ActorClassesToRecord and ActorClassesToDestroy should be filled with vanilla and modded classes.

Link to comment
Share on other sites

Subclassing the checkpoint classes definitely works, that's what I just did. Good catch on making the XComGameInfo/XComHeadquartersGame variables config vars, that is simpler than using my mutator to do it.

 

The part I'm unsure about is how to fill the default properties via a .ini file, since the Checkpoint class is not a config class. I tried making my own class a config class and adding ActorClassedToRecord to it, but this doesn't work, the entries are ignored.

 

I guess the actual Checkpoint class needs to be a config class to get this to work. I've never made a class a config class, only added config to variables in existing config classes. But if we can make Checkpoint a config class the subclass becomes unimportant, mods can just directly add new classes to an .ini entry for the original class types.

Link to comment
Share on other sites

Hmm...

var const array< class<Actor> > ActorClassesToRecord;
var const array< class<Actor> > ActorClassesToDestroy;

Both are const. But we can try to remove const flag from them. We won't be able to config them directly, as adding config to class with no config defined won't work, but we should be able to create out own variables like

var config array< class<Actor> > ActorClassesToRecord_Mod;
var config array< class<Actor> > ActorClassesToDestroy_Mod;

And then assign them to ActorClassesToRecord and ActorClassesToDestroy.

 

Another way is, as you suggested, to try adding config to Checkpoint class directly. Then all the child classes will have access to it and we can make both arrays directly configurable.

Edited by wghost81
Link to comment
Share on other sites

Currently Checkpoint class has this flags set:

    ClassFlags = 0x080000B2
        0x00000002: Compiled
        0x00000010: Parsed
        0x00000020: Localized
        0x00000080: RuntimeStatic

We need to add 0x00000004 (Config) to it and init ConfigNameIdx with some name from namelist. Checkpoint should do, as it will result in DefaultCheckpoint.ini filename:

[BEFORE_CODE]
<%u 0x080000B2> // ClassFlags
<Core.Object> // WithinRef
<None> // ConfigNameIdx
[AFTER_CODE]
<%u 0x080000B6> // ClassFlags
<Core.Object> // WithinRef
<Checkpoint> // ConfigNameIdx

In theory this should turn Checkpoint into ini configurable class:

[ModCheckpointRecord.Checkpoint_StrategyGame_Mod]
ActorClassesToRecord=...
Edited by wghost81
Link to comment
Share on other sites

I'll try the checkpoint adjustments when I get home tonight. I don't see how creating the extra _Mod variables will work because there are no instances of this class to assign the variables to. The class has the "RuntimeStatic" flag set, which I can't find any documentation for, but sounds like a static class with no instances used only for its default properties? In that case the config settings are likely the only way.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...