Progress Chart — or How I Learned To Stop Worrying About Bad Code And Just Do It (Part 2)
And this time, I was done. For real.
Or was I?
Oh, boy! I wasn't!
Remembering the threaded path
I said I didn't care about route points, last week. I still don't. They're not the issue.
The issue is the following user case:
- I finish my route with Claire
- I start a route with Hongkui
- Midway through, I feel like using the Progress screen to jump to a scene common to both
- After that, which route will I continue in?
Note that at this point I already painstakingly copy-pasted all coordinates for the common Hongkui-Claire page in Chapter 3. You DO NOT want to redo that.
Even then, I found setting a flag AFTER jumping to a scene quite hard. And setting it first, if it's not persistent, just clears it as soon as you jump. Not ideal!
I also tried to make a persistent variable hold the "jump to" label, planning to use it in a transition scene where I also set the route flag and...
I turned to Remember 11, which I was replaying at that time.
For those who don't know: Remember 11 has two main characters. You play through the game with one once, then play a second run from the second's point of view. The cool thing is that some bad endings are unlockable ONLY if you reach another bad ending with the other character and THEN save system data. System data also locks you from reaching, say, day 3 as any character if you already died in day 2. A bit weird to navigate around when you're replaying the game to see all endings, but quite interesting.
Toumayhem is a lot simpler than that, but I figured I could do the same.
Instead of having a boolean for each route, I just made two strings containing the current character's route letter (H for Hongkui, C for Claire, R for Akito and M for Mitsuki): one persistent, one not.
Both are set when you first enter into a character route. All checks in-game are done on the local variable. Why not just use the persistent? Because I asked myself the same question at first, then discovered that it changed all saves. In the scenario from earlier, you could reload a save from Claire's route, in the middle of a Claire-exclusive scene, then keep going as if you were in Hongkui's route since the persistent flag has last been set as his. Not very nice.
Then, after you see one of the endings, you're asked if you want to save system data. If you do, the current route flag is saved as the persistent one!
This alone solves nothing on its own, of course. That's why I revisited a nifty set of functions I already had all over the place...
Yesterday's Enemy is Today's Friend
Something changes with every scene: the scene name (shown in the save/load screen), possibly the game date. This was a pain to handle every time, so I first wrote set_scene_info as a straightforward "put these values into this global variables" and called it at the start of every scene.
But as I worked more on the Progress scene, I realized I could save some work and just input the date.
scene_titles is a big dictionary with scene labels as keys and scene names as values. This way, I could reference both from the same place with no problem at all! And considering I can access the current label anytime, I don't even have to pass it to the function! Well worth sweating writing this thing way back. Good job, past me.
chapter_name is a bit trickier, but very satisfying nonetheless. All story labels (except for EPILOGUE and bad endings) in Toumayhem follow this form:
- N1 stands for Neutral, chapter 1; character-exclusive scenes follow the convention mentioned earlier (that's why I chose it!) so a Claire scene from chapter 3 would start with C3. Some scenes in chapter 1 don't follow this rule because it predates routes, and append the character's letter to the label instead (e.g. N1_090515_1600C). Bad endings are just labeled BE_01 and such.
- 090515 stands for the date: 15th of May 2009. I could've parsed this from the label too instead of inputting it into the function, but it was going to be a real pain in the ass if I ever changed my mind about WHEN exactly the scene happened, or if it starts with a flashback.
- 0900 stands for 09:00, the starting time of the scene. This is just a planning tool, as some scenes are labeled 0900 but actually start at 0600.
Knowing this, you can expect that prefix to be very powerful. I split it into letter and number (if available), then give it a good spin and get the chapter name out of it thanks to another dictionary.
What's interesting, though, is route_name: as you can see, it takes both current_flag and persistent.route_flag to work out what's the current scene's flag! This is because you might start a scene from the Progress screen and have no current_flag set yet, even if you're past chapter 1 already.
Man, what a headache! No wonder I had so many issues with this. But who sets current_flag when you jump to a scene from the Progress screen?
Mic check, 1, 2
Variables are out, we only deal in functions now.
What do you do when you need to see what's your current route? If you check the persistent, you mess with previous saves in other routes. If you check the local, you risk getting into a route without actually having the flag set.
Answer: you need both!
The real question is: when do you need to check a flag? You really don't need it all the time. Therefore — Eureka! — instead of comparing variables and values I just call check_route, which does two things:
- If current_flag is empty, it's set to the value of persistent.route_flag
- It now checks current_flag's value
Since you only need to check for the route value when you are in a route, it's always supposed to be set. Problem solved!
Thou Shalt Not Pass
But we're not done yet! Here's another annoying scenario:
- I finish my route with Claire
- I start a route with Hongkui
- I miss Claire, Hongkui is a dick.
- I jump to a Claire scene through the Progress screen
Now, now... what happens here? current_flag won't be set, and the last persistent.route_flag is Hongkui's. We're going to be thrown back into Hongkui Hell as soon as the next flag check happens! Give me back my Claire time, you lousy simp!!
This is why you can't allow free timeline roaming, and need to lock character-exclusive scenes to the persistent.route_flag. This way, if you want to replay Claire's route, you either start from the beginning or jump to a scene before the flag set. Just like Remember 11 does (except I explain it a bit better in-game, I think).
Route scenes are very easy to lock in the Progress screen thanks to the character letter in the label (I told you it was powerful!). Labels such as the common scenes (shared between two or more characters, but not all) or bad endings (which do not have the character letter in their label) are characterized in another dictionary. Not spotless, but not too shabby either.
And that's it! Hopefully no one will find a bug in the comments. Or in the game when it's out. Man, I really hope it works, this time.
Did you enjoy this write-up? What's something you'd like to know more about? Let me know on Twitter and in the comments, now that I'm free from the clutches of this ever branching flowchart monster!
Leave a comment
Log in with itch.io to leave a comment.