I did that when I first started; single file. It eventually broke the game. I don’t remember why.
I’ve found it easiest to keep my gosubs in the same chapter scene file where they’re called – but that’s in part because the mechanics in my different chapters are all pretty distinct from each other. If I had e.g. a combat mechanic that would recur throughout the game, I’d use *gosub_scene for it.
If I had a gosub that I was only using to avoid repeated text in a particular chapter/scene (which is I think 100% of the use cases in Choice of Rebels) I think it’s easier to have it in the same scene file, so I can quickly use CTRL-F to take me there and remind me what it says, then CTRL-F my way back through the places where it’s called to make sure it fits equally well with any of them.
The auto testing programs started choking on a recent chapter of mine when it ran large, but that scene is currently working fine with 24,000+ lines of code… so you’ve got a reasonably high ceiling to work with for your scene file sizes.
So, I’ve determined I need a gosub to avoid a lot of repeated text.
How would I get the game to access the gosub if it’s in a different file? And how do I get it to go back to where it was after?
Edit:
For clarification…
I’m in chapter one at point X. I need to run a gosub. *gosub label (label being in the gosub file).
But… what next? How do I get it to go back to X?
*label TEXT HERE 1
This is TEXT HERE 1.
*return
*label TEXT HERE 2
This is TEXT HERE 2.
*return
To call the “TEXT HERE 1” label from said file, you can use the following command:
*gosub_scene gosub_file TEXT HERE 1
Let’s say you use a file called ‘subroutines’ to keep all your gosubs.
And the code you need is in that file under the label called ‘some_code’.
Then you use
*gosub_scene subroutines some_code
to go there. And use
*return
to get back to where the subroutine was called from.
Like this
*label some_code
your code goes here
*return
*gosub_scene label_name will send the game to the file and label. The *return at the end of the subroutine will send it back to where the game was at originally.
Gotcha. And I just put *return in the gosub file? Not in the scene file?
Edit:
Also, holy mackerel guys. Ya’ll responded q u i c k
*blah blah
*go_scene gosub [label here]
*other code
Then in the gosub…
*blah blah blah
Text here
*return
Like this?
Oh. Just saw this. Three replies at once.
And the gosub will display text as well like any other scene file right?
Basically, I have… counts
9 potential outcomes for a particular *choice option. The flavor text is almost identical save for a few paragraphs but I can’t do the loop trick I learned earlier because it’s the first, middle and last of 8 paragraphs so I don’t think there’s a way to loop that without a gosub.
If there’s a better option, please for the love of God, I’m all ears.
Hello again Coal. Just saw this too.
This does answer one of my other questions.
This is the code I’m trying to simplify by the way, just in case it helps.
#Option
*if (Combat >= 50)
TEXT
*goto TunnelGucchi
*if (Combat >= 40)
*if (WornArmor = "Composites")
*set Composites -10
*go_scene gosub AaronMissionLoudHurty
*goto TunnelGucchi
*if (WornArmor = "Metals")
*set Metals -20
*go_scene gosub AaronMissionLoudHurty
*goto TunnelGucchi
*if (WornArmor = "Nothing")
*set Health -50
*if (Health > 0)
*go_scene gosub AaronMissionLoudHurty
*if (Health <= 0)
TEXT
*fake_choice
#Go to the last checkpoint.
*set Aaron 50
*set Health 100
*set Leathers 100
*set Composites 100
*set Metals 100
*goto save_checkpoint
#Let me die, dangit!
*finish
*if (Combat < 40)
*goto DaysOff
*if (WornArmor = "Leathers")
*if (Leathers >= 25)
*set Leathers -25
*go_scene gosub AaronMissionLoudHurty
*goto TunnelGucchi
*if (Leathers < 25)
*set Health+(Leathers-25)
*if (Health > 0)
*goto TunnelGucchi
*if (Health <= 0)
TEXT
*fake_choice
#Go to the last checkpoint.
*set Aaron 50
*set Health 100
*set Leathers 100
*set Composites 100
*set Metals 100
*goto save_checkpoint
#Let me die, dangit!
*finish
*if (Combat < 40)
*goto DaysOff
Ignore my label names. I’m unimaginative.
Is the repeated text at this label going to be something you’ll have in future chapters too, or is this scene the only one that uses it?
If it’s just for this scene, I’d suggest this:
*gosub AaronMissionLoudHurty
[...somewhere below the choice block...personally I put my gosub labels at the bottom of the scene file, after *finish, to be 100% sure the only way the game gets there is when a gosub command is triggered...]
*label AaronMissionLoudHurty
repeated text
*return
all in the same scene file.
If you want your gosubs to have their own scene, first you have to name that scene…and if you name it “gosub,” you’re setting up yourself for typos and your code readers for confusion. Let’s say you name it “subs.”
Then in your combat scene code, you’d have:
*gosub_scene subs AaronMissionLoudHurty
and over in the subs.txt scene file you’d have:
*label AaronMissionLoudHurty
repeated text
*return
There’s no *go_scene command, just *goto_scene (if you want the game to continue there) or *gosub_scene (if you want the game to borrow a quick subroutine from that scene before jumping back to your current one).
I changed the title so you can consolidated all your help requests in one thread going forward.
In case you still wanted an answer from me regarding the *return command:
It acts as a traffic control… it tells the script to go back to the spot it came from and continue following the code from that point.
Edit:
As far as file naming practices, i have separate sub-routine files for each of my normal text files.
I do this because I find it easier to both test and bug hunt this way.
Here is a sample of my file structure from my startup file:
toggles
morgue
*comment morgue_shared
trash_chute
*comment trash_chute_shared
bodies_chute
*comment bodies_chute_shared
The shared files are commented out, because they stay hidden and are not accessed by the script until being told to go there for the sub-routines i have in each
Here is a sample of three subroutines I have in morgue_shared:
*label shared_1
Recognizing the odor as a mixture of voided bowels and spilled blood, you tense your muscles, ready for flight or fight. Raising your head, you begin to focus your gaze on your surroundings, squinting to keep the harsh overhead light from blinding you.
*return
*label shared_2
[i]Murmur… murmurmurmur… murmurmurmurmurmur.[/i]
*return
*label shared_3
"What…" Glancing heavenward, you gather your breath deep inside your chest. Your hand brushes the desk's edge before you, and you decide to straighten up as you ask your question. "… is the meaning of this?
*return
I hope all this helps
Gotcha. And it’s the only scene that uses it. I have just never used a gosub before (I think?)
Thanks. I probably should’ve been asking in the Nood Script doodad but my two brain cells are fighting over the oxygen.
As a side note, is there a benefit to using *gosub this way instead of something like this:
*goto LoudHurty
*label Whatever
*label LoudHurty
blah blah
*goto Whatever
The difference between *goto and *gosub is really mainly that you can use *return with gosubs, so you can use it in multiple places, and return to each of them.
In your example, all *goto that point to loudhurty would then always proceed to whatever, and couldn’t continue in different directions (without more coding at least).
Thanks guys.
Different question.
Is there a way to check if a variable has ever been altered throughout the game?
Say for example, Health is currently at 100, but we need to check if it has ever been below 100 previously.
I don’t think it can be done but I’ve definitely been wrong before.
What you’ve got there is an infinite loop. Once you hit Whatever, you’ll never go anywhere else again.
The first thing I’ll say about gosub is that it’s unnecessary. You can totally write a game without it. It’ll just have plenty of repeated text…like Tin Star and other classics of the medium. If you’re struggling to get your head around it, write without it. It’s more important just to write than to write efficiently.
If you use gosub, it’ll take the reader to a section of code that should not be reachable any other way than a *gosub command. That section of code starts with a *label and needs to end with *return. The whole thing is called a subroutine. Instead of copy-pasting that bit of text/code repeatedly, you can just type *gosub (followed by the subroutine label name) and the game will jump to the subroutine. When it gets to *return, it’ll go back to the specific *gosub command that triggered it.
If the game runs into a *return without having hit a *gosub, though, it’ll crash. (Because it’s got nowhere to “return” to. ) So be careful not to *goto any label that is used for a *gosub.
There’s no built-in function that will do it for you, but there are a couple ways you could do it, depending on what you need it for.
If you want to know if your health stat is different now than it was at e.g. the end of Ch 3, you could *create ch_3_health
in startup.txt, *set ch_3_health health
at the end of Ch 3, and then at any point in the rest of the game compare health to ch_3_health to see what’s changed.
If you want to know if health has ever reached 60, you could have a gosub you put in your code every time health goes down:
*set health -10
*gosub checkhealth
[...somewhere else below...]
*label checkhealth
*if health <= 60
*set health_was_60 true
*return
and for the rest of the game you’d be able to check the variable health_was_60
to confirm if health had ever dropped that low.
Oops. I forgot to include the most important part.
*goto LoudHurty
*label Whatever
*goto NotLoopingPlease
*label LoudHurty
blah blah
*goto Whatever
My bad. I knew I forgot something.
Edit:
I really should double check my code but it’s 11am and I’ve been awake since 3am… yesterday.
Appreciate it though. I’m not sure I quite understand the use of a gosub. They seem like a *goto and *label combo which… I guess can be useful for some things? Repeat text but I can’t think of any scenes I’d ever write that would repeat that often.
In Stormwright, you can find yourself with nomads or villagers in the early game. There are some choices I want to give the MC on either branch – like the choice of last name, for a reader who’s not loading a G1 save file. But I definitely don’t want to copy-paste all the picklastname code twice, once in each branch.
I could use *goto picklastname
to send readers from either branch to a block of name selection code…but when that bit’s done, I want a reader on the nomad path to go back to the nomad story, and a reader on the villager path to be sent back to the village story.
*gosub picklastname/*return
does that automatically for me, saving me the trouble of ending the picklastname choice block with something like
*if nomad
*goto nomad_continue
*if village
*goto village_continue
Instead I can just end it with *return.
But the longer code example will still work just fine and pass all the tests…so if it makes more sense to you than *gosub and *return, go that route!
That makes a lot of sense actually. Thanks.