Send player to Game Over passage when health reaches 0?

I’m trying to send the player to a Game Over passage when the health goes below 1.

I’ve tried:
<<if $totalHealth <= 0>><<goto "GameOver">><</if>>

This just causes it to return a blank screen after the health reaches 0, and breaks the game.

I also do not now if I have it under the right place. Right now I have it under PassageReady, but there is also Done, Footer and Header.``

Yeah, that’s kind of a dangerous thing to run for each passage: you’re getting stuck in an infinite loop. When health reaches zero, it’s sending you to GameOver. Then when it tries to show the GameOver passage, health is still zero, so redirects you again. And again. And again…

You could try <<if passage() !== "GameOver" && $totalHealth <= 0>>, or if you’ll have multiple, you could use tags and try <<if !tags().includes('GameOver') && $totalHealth <= 0>>.

But I’d be more inclined to write a widget to decrease your health which checks if you’re dead and takes the appropriate action.

Generally speaking, you should avoid using the <<goto>> macro whenever possible, since <<goto>> doesn’t prevent any other code after it from executing, which can cause problems if you don’t entirely account for that.

Also, you shouldn’t have any “passthrough” passages, where your code goes to one passage and then immediately to another passage before the player sees it, because that approximately doubles the length of time the passage transition takes and it also breaks the “Back” button. Worse, similar to the <<goto>> macro, other code in the “passthrough” passage may also cause unexpected side effects if you’re not careful about that.

The problem is probably that it’s going into an infinite loop, since it tries to go to some passage, is redirected to “GameOver” passage, which then would trigger the <<goto>> check again, sending it to the “GameOver” again, triggering the <<goto>> check again, etc…

The correct way to do what you want is to create a Config.navigation.override function, which will allow you to redirect to a different passage based on certain conditions. For what you want, you’d put this in your JavaScript section:

Config.navigation.override = function (destPassage) {
	var StoryVar = State.variables;
	if (StoryVar.totalHealth <= 0) {
		return "GameOver";
	return destPassage;

That code makes it so that, any time you go to a new passage, it will check the $totalHealth value, and redirect to the “GameOver” passage if it’s less than or equal to 0. Otherwise it will continue on to the the destination passage it would have gone to normally.

If you’d like to add other redirects, just add more “if” statements within that function.

Hope that helps! :slight_smile:

EDIT: Corrected the bug I mention below.


Making sure, as it doesn’t seem to be working (I’ve never used javascript before), destPassage is the place the passage would originally go, right?

If I had [[Damage Test|Test][$totalHealth -= 25]] (current passage is called bug):

Config.navigation.override = function (Test) {
	var StoryVar = State.variables;
	if ((StoryVar.totalHealth <= 0) {
		return "GameOver";
	return Test;

It doesn’t seem to work, as the health depleted into the negatives.

The 2nd example included with the linked Config.navigation.override function documentation demonstrates a “Game Over” like situation.

If you add that example to the Story JavaScript area of a Twine project with a passage structure like the following…
(using TWEE Notation)

:: Start
<<set $health to 10>>

[[Next (no health setter)|Next]]
[[Next (neg health setter)|Next][$health -= 25]]

:: Next
Next passage

:: You Died
You Died passage

…and test each of the above two links then you will see that that method does work when combined with the Wiki based Link-with-Setter link.

Sorry, I had an extra character in there. This line:

	if ((StoryVar.totalHealth <= 0) {

should be like this:

	if (StoryVar.totalHealth <= 0) {

Now it should work.

The “override” function gets triggered every time you go to a new passage, and destPassage is simply a variable which holds a string that is the name of the passage that the game will go to next unless you override it. You don’t have to change the name of that variable, but it shouldn’t matter if you do change it, as long as you change it the same way throughout the function.

Basically, the “override” function acts as an intermediate step between every passage transition. If you try to go from passage “A” to passage “B”, then destPassage would be set to “B”. If you return a different passage name from the “override” function, other than “B”, then it will go to that other passage instead. If you try to go to passage “C”, then destPassage would be set to “C”, etc…

You can use that destPassage variable (or whatever you decide to call it) if you want to have tests in your “override” function which depend on the destination passage name to determine whether to redirect to a different passage or not.

Did you put that code into your JavaScript section (use the bottom menu to access it)? It probably won’t work if you put it elsewhere. Also, you’ll need to remove that extra “(”.

Note: To work with my code, instead of $health, you have to use $totalHealth.

That said, I’ve verified that it should work, so give it another shot.

Have fun! :slight_smile:

1 Like

Ahh… that’s why it wasn’t working. I was trying to do it the same way you do StoryInit, where you write a passage for it. Now that I’ve put it in the right spot it works great. Thank you so much!