Overview
If you run in to problems with the save/load cycle, it's often useful to inspect savegame files.
Games are saved in the savegame folder with an extension of ".gam".
Unpacking a "gam" file
I have no idea how to do this! <need to find out how and detail or link here>
Once you've unpacked the "gam" file, you'll end up with a folder like containing stuff like this:
scriptstate.ini
The scriptstate.ini
file contains the saved state from your script, which includes:
- Global variables
- Timers (see setTimer()) and queued functions (see queue())
If you want to learn more, I suggest taking a look at qtscript.cpp which is where the magic happens.
Here's an example of the contents of the file for a basic game between me and nullbot AI, saved a few seconds after starting the game: scriptstate.ini
Global variables
As you can see, each player gets a [globals_X]
section in the file, where X is the player number (zero-referenced). It's in this section that your global variables are stored, and as you can see it's a real mess!
Global variables containing primitive values look like this:
[globals_0] lastHitTime=0 me=0 selectedPlayer=0 difficulty=0 mapName=Sk-Startup baseType=0 alliancesType=0 powerType=1000 maxPlayers=2 scavengers=false mapWidth=64 mapHeight=128 DORDER_ATTACK=3 DORDER_MOVE=2 DORDER_SCOUT=28 ...
Arrays containing primitive values look like this:
truckBodies=Body3MBT, Body2SUP, Body4ABT, Body1REC truckPropulsions=hover01, wheeled01 tankBodies=Body7ABT, Body6SUPP, Body8MBT, Body5REC, Body3MBT, Body2SUP, Body4ABT, Body1REC tankPropulsions=HalfTrack, wheeled01 vtolBodies=Body7ABT, Body6SUPP, Body8MBT, Body5REC, Body3MBT, Body2SUP, Body4ABT, Body1REC
But as soon as you start dealing with objects, it becomes a real mess:
mgCyborgStats=@Variant(\0\0\0\t\0\0\0\x2\0\0\0\n\0\0\0$\0\x43\0y\0\x62\0o\0r\0g\0\x43\0h\0\x61\0i\0n\0\x31\0G\0r\0o\0u\0n\0\x64\0\0\0\n\0\0\0\x1c\0\x43\0y\0\x62\0o\0r\0g\0\x43\0h\0\x61\0i\0n\0g\0u\0n), @Variant(\0\0\0\t\0\0\0\x2\0\0\0\n\0\0\0\x16\0\x43\0y\0\x62\0R\0o\0t\0M\0g\0G\0r\0\x64\0\0\0\n\0\0\0\x16\0\x43\0y\0\x62\0o\0r\0g\0R\0o\0t\0M\0G), @Variant(\0\0\0\t\0\0\0\x2\0\0\0\n\0\0\0\x18\0\x43\0y\0\x62\0-\0\x42\0o\0\x64\0-\0L\0\x61\0s\0\x31\0\0\0\n\0\0\0\x1a\0\x43\0y\0\x62\0-\0W\0p\0n\0-\0L\0\x61\0s\0\x65\0r) rocketCyborgStats=@Variant(\0\0\0\t\0\0\0\x2\0\0\0\n\0\0\0 \0\x43\0y\0\x62\0o\0r\0g\0R\0k\0t\0\x31\0G\0r\0o\0u\0n\0\x64\0\0\0\n\0\0\0\x18\0\x43\0y\0\x62\0o\0r\0g\0R\0o\0\x63\0k\0\x65\0t), @Variant(\0\0\0\t\0\0\0\x2\0\0\0\n\0\0\0\x1c\0\x43\0y\0\x62\0-\0\x42\0o\0\x64\0-\0\x41\0t\0m\0i\0s\0s\0\0\0\n\0\0\0\x1c\0\x43\0y\0\x62\0-\0W\0p\0n\0-\0\x41\0t\0m\0i\0s\0s)
Good luck making sense of that!
And, if you have anything with functions (or anything else Warzone doesn't know how to persist), you'll end up with this sort of thing:
statusX=@Invalid() statusY=@Invalid() statusTime=@Invalid()
Timers and queued functions
Timers set with setTimer() and queued functions set with queue() are also persisted to the file, which explains why you have to pass function names and not functions in to them, etc.
An example of some timers and queued functions is shown below:
[triggers_11] player=1 function=adapt object=-1 frame=60002 type=0 ms=60000 [triggers_12] player=1 function=debugTrucks object=-1 frame=49002 type=0 ms=49000