1. All Hail Temos
  2. News
  3. How to Rewind Time - Devlog #1

How to Rewind Time - Devlog #1

Kicking off the Devlog series for All Hail Temos, this is how I implement saving the game, but instead of normal save game files, I want full timeline Rewinding, so the player can travel back to any point in the past, at a certain granularity, and then play forward from there. It also means no worrying about saving, because everything is always being saved, and you can always go back and try something again.

For UX reasons, I will still have a bookmark of save games, so you dont have to scrub through the timeline if you know you want to remember an area for rewinding to.

This does make Save Scumming a first-class feature of All Hail Temos, so I make it easy to go back and try different options, and I introduce you to the reality of time travel into a story with many branching paths. But that is a design discussion, and this is a technical devlog.



[h2]Introduction[/h2]

Every change in the game is stored in a sequential record, and then when you rewind, you can rewind over your entire play session, including when you reloaded previous game saves before, those are all just in the time line linearly. So you will have a you-tube like scrubber bar and you just go back in time to where you want to Rewind to. Then your Journal gets a summarized version of this, which is your actual Historic Record, and is what will be in your journal book, even though all the information exists in the timeline, the book only contains the Historic Record. Later I will add a toggle so you can actually get the entire timeline in the book.

Side Note: Your gameplay Journal can be exported as an EPUB in a later release.

[h2]Journal Historic Record - what you have done
[/h2]
The Journal Historic Record, looks like this:


0
1
2
3
456


You start the game: 0 and advance to 1 -> 2 -> 3 -> but then you played 455 more snapshots worth of gameplay, and did a rewind all the way back to #3, which created the new 456 to start making changes from. All the 0-456 exist in the timeline, but your journal only sees 5 items.

[h2]Snapshots of the Game - Instant-Frames[/h2]

Every snapshot of time above contains a lot of changes inside of it. I call the full snapshots of the game, which is normally called a save file, an Instant-Frame (or I-Frame) and the individual changes in the snapshot I call Progress-Frames (or P-Frame), which roughly also map to terms used in MPEG encoding. That looks like this:


---
i: 456
start:
985473299343: 9875
123173621736: 1001
progress:
# location: progress IDs, ...
985473299343: 9876, 9877, 9878
123173621736: 9879, 9808
---



This shows the snapshot 456, has 5 changes in it, across 2 different locations. Location 985... and 123... have several changes made to them. So these are the I-Frame and P-Frame numbers together. Which are made sequential by the Journal Historic Record, by just putting the snapshot I-Frame number in a sequence.

[h2]Changes to the Game - Progress-Frames[/h2]

Finally, this is the change data (Progress-Frame), which contains all the information needed to rebuild exactly what was happening when the game was being played, and also constantly updates where the player is, what they are doing, their physics information, and the same for any other NPCs in the location.


file: i_p_001_456
---
p: 9876
seed: 756894
seed_advance: 126
day: 76543.4
day_last: 76543.4
state:
- Tenin.returned_horse_cart
counter:
Tenin.angry: 6
start:
1: ACTIVE, 337,0.523, 123,321,213, 0,90,270, 0,0,0, 0,0,0
actor:
1: 10000, 123,321,213, 0,90,250, 0,0,0, 0,0,0
98754321: 0,123.4
object:
# Destroyed object
628374: -1,1
# Removed object, by the player
628374: 0,1
---


This repeats the I/P frame information, so you can always easily tell where you are, and search for them in the text files. I also put this information into the filenames that are stored, so modders can easily look at the files. There will also be instructions on all file formats, in case people want to mess with things, to enable low level modding types. It also gives the time in-game days since the player started, so we know the current time, and it gives the last time this file was updated, as it stores both a fixed change, and updates about what people are doing.

I also keep the Seed and times advanced since re-seeding for the Random Number Generation. This allows me to reset the seed, call it the number of times advanced, and the next random number will always be the same.

[h2]Storing State at Every Location, for Every Situation[/h2]

In AHT, every time you go anywhere, the location you are seeing was set up specifically to be that way, at that time, in your circumstances. If you had answered a question differently, or done a quest, the stage may have different actors there, different furniture or props, anything could be changed, as it was completely set up by your narrative stage, when you triggered spawning that area. So I already know the starting state of any location in precise detail, so the only thing to track are things that have changed.

In the state section, I say that the Narrative has changed, and you advanced a quest-line of returning a horse cart. In the counter section, I update a counter that also changed, so this guy has gotten angry more 6 times. Since its angry, it is a counter going up. But if it was irritated it might go up or down, depending on how they are reacting to what you are doing in the world. You could make someone angry who isn’t there, because you did/said something, and after 1 day and you enter a location, they confront you over it.

In the actors sections, I give the UUID of the actors (1 = the player), and what they are doing currently, and information about that.

[h2]Example of Change State[/h2]

For instance the player is free roaming around, and I give their current animation, time into that animation, position XYZ, rotation XYZ, momentum XYZ and rotational momentum XYZ. So I know where they are, what they are doing, and how to carry the physics into a reloaded scene.

Maybe they were jumping off a roof, and had forward momentum. I don’t want them to lose that, and they just fall on the ground, but I’m also saving minimal information, so it doesn’t take a lot of file IO or space, and is easier to parse as a human. Its also written in a pseudo-barebones-YAML format I made. The other actor (Tenin = 987...) is at station 0 (Guarding), at 123.4 seconds into that action.

[h2]Objects of Loot and Destruction[/h2]

Finally objects tells me if an object has been destroyed, or taken, and by who (actor UUID, 1 = player). So the player took that item out of the area.

The other object was destroyed, by the player. Other actors could destroy or take things too, and this leaves exact information for any quests related to theft. You could trick someone else into stealing something for you, and in my narrative logic, I can test whether it was the player or someone else who took it.

But, if they player has the item and they didn’t take it, I can then narratively say that they tricked or convinced the other people to do it for them. If the other person is their friend, then they have built alliances I can acknowledge in some narrative way, and if the other person was attacked by them afterwards and the player took it, which I also know, I can narratively say they were devious.

[h2]Conclusion[/h2]

I hope you have enjoyed this explanation of how to save and rewind time in All Hail Temos. If you are are interested in game, the Prologue demo is planned for release in the beginning of September. Wishlist it to remember.