Workflow and User Events - Grisgram/gml-raptor Wiki

I've tried to simplify the workflow for the complicated task of creating a savegame file as much as possible and ended up with only two user events that need attention while the game is saved or loaded.

In addition to that, some objects might need to know, when they are created, whether it is a regular object spawn or if the instance just got created during the game load workflow.
An example for this could be an object that creates additional child instances when it is created (like preparing some bullets so it can shoot or some animated objects surrounding it). If the object just gets restored from a save game, it does not need to create those childs, as they are probably part of the savegame anyway and will get created by the Savegame system.
This is the moment, where you might want to query the SAVEGAME_LOAD_IN_PROGRESS or SAVEGAME_SAVE_IN_PROGRESS macros to skip that part in this case.

The next logical thought is now "Ok, but when those child objects are also created for me, how can the Savegame know, that these 25 Bullets are my Bullets? What about the links between objects, restoring pointers to other instances?".
This very complex question is answered. Savegame can do that!
But before I go into detail on that, let's take a look on the timing in the workflow, especially the two *_IN_PROGRESS macros mentioned above. You need to know, when they are true or false to understand how instance link save and restore works.

Saving Loading
SAVEGAME_SAVE_IN_PROGRESS = true SAVEGAME_LOAD_IN_PROGRESS = true
onGameSaving (User Event 14) onGameLoading (function)
onGameSaving (function) SAVEGAME_LOAD_IN_PROGRESS = false
SAVEGAME_SAVE_IN_PROGRESS = false onGameLoaded (function)
onGameSaved (function) onGameLoaded (User Event 15)

You can see, the present time ...ing (Sav_ing, Load_ing) functions are invoked while the progress variables are true and the past tense ...ed functions are invoked, after the flags returned to false. So, from a timing view, after the process has completed, but before the control is given back to the game. On a call stack view, we are still in the save or load function respectively.

Saving and restoring instance connections

GameMaker assigns each object an unique id when it gets created. This will very likely not be the same, when the game gets saved and loaded back into memory. So we need some kind of reference that allows us to "re-link" objects after they have been loaded.

raptor offers two helper functions for this task.
You have to do this in one direction when the game gets saved (in User Event 14 or in your implementation of onGameSaving) and restore it in User Event 15 or your implementation of onGameLoaded.

This sounds more complicated than it actually is.

Let's play through this with a short example of an object that holds 25 Bullet private child instances and another instance of an AnimatedShield Object that surrounds this object as a kind of a visual damage shield.

Create

// Create event

// Note: this is NOT held in .data! A normal instance variable!
// The objects `Bullet` and `AnimatedShield` are assumed to be also a Saveable objects!

my_bullets = array_create(25);
my_orbiting_shield = undefined;

// Take care, to create bullets only, if you are not currently restored from a savegame
if (!SAVEGAME_LOAD_IN_PROGRESS) {
    var i = 0; repeat(array_length(my_bullets)) {
        my_bullets[@ i] = instance_create_layer(x, y, "Instances", Bullet);
        i++;
    }

    my_orbiting_shield = instance_create_layer(x, y, "Instances", AnimatedShield);
}

onGameSaving (User Event 14)

The function savegame_get_id_array_of saves the instance ids of the Bullets to an array.
This array is stored in data.my_bullet_ids and will therefore be written to the savegame.

// User Event 14 (onGameSaving)
data.my_bullet_ids = savegame_get_id_array_of(my_bullets);
data.my_shield_id = my_orbiting_shield.id;

onGameLoaded (User Event 15)

The function savegame_get_instance_array_of takes the stored ids and restores the corresponding instances after all objects have been loaded.
This mapping is possible, because Savegame saves the ids of all existing objects in the savegame.
So it can find out, which id the object had when it was saved and can find the exact object after loading.

// User Event 15 (onGameLoaded)
my_bullets = savegame_get_instance_array_of(data.my_bullet_ids);
my_orbiting_shield = savegame_get_instance_of(data.my_shield_id);

You can see, storing and restoring of linked objects is done in a single line of code!

More details on the helper functions above and all other available supporting functions of the Savegame system can be found in Savegame functions.

⚠️ **GitHub.com Fallback** ⚠️