How Save/Data Management Works In Wandersong
Wandersong is a musical adventure game about a bard, and it has a lot of characters and cutscenes and conversations! As a result of this, there are a LOT of very small bits of information the game needs to keep track of… The most common being, “how many times have I talked to this character?” It seems like a pointlessly small thing to write about, but it comes up a lot and I have a solution for it that I very much like, so I figured I’d share.
A typical conversation
In short: all data is stored into a giant dictionary. At the start of a new game it’s completely empty, and entries are added as the player interacts with things. If an entry doesn’t exist in the dictionary yet, it’s treated as being set to 0.
Sounds stupid simple, right? OK, it is. But it’s powerful! What follows is an explanation of how it’s implemented in GameMaker Studio.
Instead of “dictionaries,” GameMaker has a data structure called a map. For the uninitiated: a dictionary/map contains data stored in pairs, a “key” and a “value.” The “key” is kind of like an entry name or label, and the “value” tells you what it’s set to right now. At the start of the game, I make a blank map like this:

And then I have but two scripts that deal with this data.
data_set

Which takes two arguments, an entry name and a value. It either adds a new entry to the dictionary, or updates it if it already exists… and for good measure, it autosaves the game too, because why not. (Actually I forgot it did that until now, but I guess it happens so fast I never noticed, so…?)
and data_get

You give it an entry name, and it tells you what’s stored there. Or 0 if it doesn’t exist yet. (This is important!)
And here is how it typically would get used, in the interact-with-a-character event:

So for this event, I used an entry called “talking_to_bob”. I check what’s stored there, give you a different piece of dialog depending on what it is, and then set it to something new for next time. Typically in Wandersong, an NPC conversation tree follows the logic (conversation 1) - > (conversation 2) -> (conversation 3) -> (conversation 2) -> (conversation 3) -> etc. But you can do whatever you want with this.
There are a couple big advantages here. When I save the game, I just save the contents of the game_data dictionary–which is just a couple lines of code to do–but that’s flexible enough to include any amount of data, forever. So I can add new conversations, new conversation branches, or track anything I want anytime while I’m in the middle of writing a scene, and I don’t have to worry about bookkeeping anywhere else. It lets me be flexible and loose and have weird ideas as I’m going, and it makes it very easy to add new responsive content. It’s considered bad practice to save data under a string name as I do here, since I could easily typo “talking_to_bob” and there would be no easy way to track errors that stem from that (unlike a variable name, where a typo would just make game crash). But that “talking_to_bob” entry name is not written out ANYWHERE ELSE IN THE CODE except right here, so it’s easy to correct errors.
The other advantage is the synergy this has with my cutscene system. Or really, the way it deals with my system’s biggest weakness. This is going to be a little abstract. The weakness is this: I send instructions for an entire cutscene all at once to the scene manager, and then sit and wait for the entire scene to play out over time. This is mostly great, but what if I want the cutscene to change depending on data that gets altered after it already started… like in this one, where you enter your name and it’s read back to you?
To make this work, when the cutscene instructions are sent off, instead of supplying the player name, I supply a dictionary entry to look at for the player name… this way, as the cutscene is running,the text can update as the dictionary entry updates. In GameMaker, crucially, you can’t use a regular old variable this way…
And that… covers it! It’s not as glamorous as my last how-to, but I think the usefulness is actually much broader. With all my tools and systems, I’m always looking to get the most power and flexibility with the minimal amount of typing and actual organization/management. If you’re going to make an entire game by yourself, especially one that’s overfilled with content, you have to think this way or you’ll never be done! Anyways. I hope this is useful to you. Feel free to send me questions if I left something unclear!