Changing StoryMenu options right when it's clicked, not after visiting new passage?

Twine Version: 2.0.5
Sugarcube version: 2.30.0

I’ve started using Tweego–this shouldn’t make a difference, but in case I messed something up, I can present the code some other way.

My object here is to verify the player can change from hard to easy mode, and vice versa, by clicking the options. And they can!

But the problem is, the menu text doesn’t refresh until I move to another room.

How do I refresh the menu text? Can I? I guess I could just have a command saying “go to passage()” but that might disrupt things later on when I’m trying to, say, see where the player last came from.

Code below.

:: StoryTitle
My Code Laboratory

:: StoryData
  "ifid": "22224444-7777-1111-9999-555566668888",
  "format": "SugarCube",
  "format-version": "2.30.0",
  "start": "Start"

:: StoryInit

<<set $hardmode=false>>

:: StoryMenu [StoryMenu]

<<set $hm to 'Hard mode, click for easy'>>
<<if $hardmode == false>><<set $hm to 'Easy mode, click for hard'>><</if>>

<<link "$hm">><<set $hardmode = not $hardmode>><</link>>

:: Start

Click the option, then click [[Start]], and the option will change!

Don’t really use the Sugarcube StoryMenu, but I’ll put in my two cents to see if it helps:

You’re updating $hardmode but not $hm, the corresponding string. You could use if and else macros inside the <<link "$hm">> block to check the new value of $hardmode after it’s set, then set $hm to the corresponding value as well? But I’m not sure if that would update the value of the link. There might be a macro that updates it or something.

Personally, since I don’t use Sugarcube macros much, the way I’d do this would be making a Javascript function that gets run when the link "$hm" is clicked, and changes the text of the link to match up with the current value of $hm. Something like ( put this in StoryMenu instead of <<link "$hm">><<set $hardmode = not $hardmode>><</link>>)

<<link "
  <span id='difficultyValue'>$hm</span>
<<run setup.changeDifficulty()>>

setup.changeDifficulty = function() {
  State.variables.hardmode = !State.variables.hardmode;
  if (State.variables.hardmode === true) { = "Hard mode, click for easy";
  else { = "Easy mode, click for hard";

  const difficultyValue = document.getElementById("difficultyValue");
  difficultyValue.innerText =;

What this does is create a span with id “difficultyValue” around the difficulty value link, and when the link is clicked, the function changeDifficulty sets the value of hardmode, sets hm correspondingly, and looks for the element with id “difficultyValue” to change the text inside to match the new value of hm. I haven’t tested this code, so there might be errors. Edit: I have now tested the code and fixed the errors, there were a few. But it works.

Might be a better way out there, though, maybe one that doesn’t involve as much JS.

1 Like

I think that link needs to actually go to a passage to work properly.

[[$hm|Start][$hardmode to not $hardmode]]


<<link $hm "Start">><<set $hardmode to not $hardmode>><</link>>
1 Like

If you want to update the UI after the passage is rendered you need to do it explicitly (using an id and a jQuery selector). This is kinda ugly, but it worked:

:: StoryMenu [StoryMenu]
<<set _labels to ['Easy mode, click for hard', 'Hard mode, click for easy']>>
<<set _hm to _labels[Number($hardmode)]>>

<<link "<span id='dif'>_hm</span>">>
	<<set $hardmode to not $hardmode>>
    <<set _hm to _labels[Number($hardmode)]>>
	<<replace "#dif">>_hm<</replace>>

So the typical “Hanon fudges around this” solution would be that the link in the menu navigates to a page that says “Successfully updated! You are in hard mode! Congratulations!” with a back link so the variable change will display.


Thanks, everyone. I learned a lot. @n-n, it may seem a bit ugly, but it works nicely, and really, I was expecting potentially a lot uglier. I think your code can be reused other places, too, as I may have other options!

@KADW, thanks for the javascript code. Some minor tweaks and it did what I wanted. I get the sense I don’t understand it fully yet, but I understand it enough for now, and once I get it completely, it’ll help with other stuff.