Configuring the Config.navigation.override function properly (Twine 2.3.16, SugarCube 2.36.1)

Hi all,

I discovered this function as part of this thread ((SugarCube 2) Monitor a global variable and override content when it gets too high - Twine Forum). I’m fairly confident it can achieve what I need, but I’m stumped about how to make the JS work. It’s currently returning a “[tw-user-script-0]; Unexpected string.” error, and isn’t working as intended.

Appreciate any insight in advance !!

Thank you

Config.navigation.override = function ("OVERMAP 1") {
	
var StoryVar = State.variables;
	
if (StoryVar.story_progression = 2) {
		return "OVERMAP 2";
	}
else if (StoryVar.story_progression = 3) {
		return "OVERMAP  3";
	}
else if (StoryVar.story_progression = 4) {
		return "OVERMAP  4";
	}
else if (StoryVar.story_progression = 5) {
		return "OVERMAP  5";
	}
else return "OVERMAP  1";
};

The syntax of the anonymous call-back function you’re assigning to the Config.navigation.override property is wrong. You’re meant to be defining the name of the call-back function’s 1st argument, not supplying a String value.

eg. The 1st example in the Config.navigation.override property’s documentation gives that 1st argument a name of destinationPassage

Config.navigation.override = function (destinationPassage) {
	/* code */
};

…and the equivalent example in the twinery forum thread you linked to gives the same argument a name of passageName

So replacing the “OVERMAP 1” String value that you current have between the function definitions open and closed parentheses ( ) with an argument name will fix that error message. What you name that argument is up to you.

The next issue with your example is that you’re using the wrong number of equals signs in your conditional expressions. eg. StoryVar.story_progression = 2

In both TwineScript and JavaScript (and a number of other programming languages) the number of equals signs you use has meaning:

  1. A single equals sign = is used as an assignment operator when you want to a assign a value to a variable.
  2. Two equals signs == are used as a comparison operator when you want to compare two values, in a way that allows the data-type of one of those values to be changed to assist in that comparison.
  3. Three equals signs === are used as a comparison operator when you want determine if both values and their data-types are the same.

The following is a variation of your own code with the above issues fixed.
note: I have not tested the following!

Config.navigation.override = function (destinationPassage) {
	var sv = State.variables;
	
	if (sv.story_progression === 2) {
		return "OVERMAP 2";
	}
	else if (sv.story_progression === 3) {
		return "OVERMAP  3";
	}
	else if (sv.story_progression === 4) {
		return "OVERMAP  4";
	}
	else if (sv.story_progression === 5) {
		return "OVERMAP  5";
	}
	else {
		return "OVERMAP  1";
	}
};

Hi Greyelf! Thanks for your help as usual.

Understood on the call-back function’s argument for the property. I applied your code to my scenario and the error no longer appears. However, the functionality is still not working, which leads me to believe I may have misinterpreted what this function can and can’t do in the first place.

Whenever a user clicks a passage link that leads to passage ‘OVERMAP 1’, I need to evaluate the state of variable $story_progression, and override their destination as required.

Right now, they continue to be sent to ‘OVERMAP 1’ even when $story_progression is set to 3.

EDIT: Correction, the issue isn’t that they’re not being sent to the correct ‘OVERMAP’ variation, the issue is that the override is being evaluated on every link click, as opposed to only links that lead to ‘OVERMAP 1’. Hope that makes sense.

The destinationPassage argument of the call-back function contains the name of the Passage being transitioned to, if you want your existing comparison code to only be evaluated when transitioning to the 'OVERMAP 1’ Passage then do something like the following…

Config.navigation.override = function (destinationPassage) {
	var sv = State.variables;
	
	if (destinationPassage === 'OVERMAP 1') {
		if (sv.story_progression === 2) {
			return "OVERMAP 2";
		}
		else if (sv.story_progression === 3) {
			return "OVERMAP  3";
		}
		else if (sv.story_progression === 4) {
			return "OVERMAP  4";
		}
		else if (sv.story_progression === 5) {
			return "OVERMAP  5";
		}
		else {
			return "OVERMAP  1";
		}
	}
};

Note: The Config.navigation.override property is not the ideal method to use if all you want to do is redirect the player away from a single Passage, because as you’ve already discovered the override call-back function is called for every single link selected in your project.

If you want to show a link that conditionally sends the player to one of a list of possible Passage then you may be better off just using a <<link>> macro something like the following…

<<link "Link that sometimes goes to OVERMAP 1">>
	<<set _passage to "OVERMAP 1">>
	<<switch $story_progression>>
		<<case 2>>
			<<set _passage to "OVERMAP 2">>
		<<case 3>>
			<<set _passage to "OVERMAP  3">>
		<<case 4>>
			<<set _passage to "OVERMAP  4">>
		<<case 5>>
			<<set _passage to "OVERMAP  5">>
	<</switch>>
	<<goto _passage>>
<</link>>
1 Like

That code works :slight_smile: Thanks again for weighing in.

It’s a good point regarding the property being called for every single link. The reason why I looked for a JavaScript solution for this issue, is that there are dozens if not over a hundred of those links, scattered throughout the story. It felt like doctoring all of them to make the override work at the “passage-level” would be more error-prone and time consuming than implementing a function.

But if the nav override is resource-heavy and liable to make the game more sluggish, that’s definitely something I’d reevaluate.

The override function is called once during a transition, so the example function provided by Greyelf is unlikely to ever be an issue.

1 Like