Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Multiple Variables in Setter Links Created with the Print Command (SugarCube)

Hi! After googling and finding some other discussion on here, I discovered that the easiest way to create dynamic links that 'remember' the state information at their moment of construction is to use the print command to build them. In this case, I want to list all of the locations that the player can visit, and so I loop through all locations and check which ones can be visited, etc. When the player selects an option, they consume some stamina - and the amount they consume is different for each location.

So, in order to deduct the correct amount of stamina, the stamina reduction must be hardcoded into the link while the list of links is being generated, using the print command. That is:
<<print '[[' + $ + '|' + $cur_location.passage + '][$pc.stamina = $pc.stamina - ' + $cur_location.stamina + ']]'>> (Stamina: <<print $cur_location.stamina>>)

($cur_location is updated with each step through the loop)

This was working for me, exactly as intended. However, when I went to try to adjust the 'setter' portion of the setter link by adding in a second set variable so that I could keep track of the player's location, i.e.
<<print '[[' + $ + '|' + $cur_location.passage + '][$pc.stamina = $pc.stamina - ' + $cur_location.stamina + '; $location = ' + $cur_location + ']]'>> (Stamina: <<print $cur_location.stamina>>)

I got the "Error: Script Error.."

I tested this using a non-dynamically generated link (i.e. removing the print command and keeping all the rest the same) and that produced no errors (though of course, it deducted the wrong amount of stamina and set $location to the wrong thing because it used the values at the end of the loop when the user clicked).

So I was wondering, have I just made some sort of silly error in the second bunch of code there, or do I need to use a different syntax (maybe the ; character is upsetting Twine somehow when it's inside the print command?), or do I just need to work around this completely?

Thank you very much for any insight.


  • I realised what was going wrong here. When you build links dynamically using the print command like that, you're essentially printing Twine code that can then be understood by the program, and so I figured I could put any old twine code in there I wanted. But, the variables that you want to use dynamically (so, $cur_location.stamina and $cur_location in the above) have to have their current value be explicitly printed so it can be saved as just text and hence unchanged when the variable later updates.

    So the problem is, when I try to print out a whole struct (which is what $location is), Twine can't print that in any normal way, and so when it tries to print it, I end up generating junk code and getting a script error instead. The same issue doesn't happen with the top example, because $cur_location.stamina is just some integer that Twine is happy to print and the code generates fine.

    I ended up going with a workaround.
  • You should always state the story format you're using and its full version, because advice will tend to vary based on that information. I'll assume you're using SugarCube v2, as you should be at this point.

    What you attempted to do is generally called the Stupid Print Trick™—i.e. using <<print>> to force early rendering/evaluation. As you found out, printing objects is problematic, because they do not have a convenient way to render themselves as literals which can be printed.

    There are a few solutions to this dilemma. Obviously, you could rework your code to obviate the need to use the object in the first place, which is what you seem to have done. Alternatively, you could either use the <<capture>> macro or double down on the Stupid Print Trick™.

    Here are some examples of the latter two solutions.

    For versions of SugarCube ≥v2.14.0 (recommended)
    Use the <<capture>> macro to localize $cur_location during the loop for the link. For example:
    <<capture $cur_location>>
    \[[$|$cur_location.passage][$pc.stamina = $pc.stamina - $cur_location.stamina; $location = $cur_location]] (Stamina: <<print $cur_location.stamina>>)

    For versions of SugarCube <v2.14.0 (not recommended)
    If your $cur_location object is simply a property bag—i.e. it consists solely of data properties—then you may use JSON.stringify(…) to render it into a printable form for the Stupid Print Trick™. For example:
    <<print '[[' + $ + '|' + $cur_location.passage + '][$pc.stamina = $pc.stamina - ' + $cur_location.stamina + '; $location = ' + JSON.stringify($cur_location) + ']]'>> (Stamina: <<print $cur_location.stamina>>)
  • Thanks a lot for that! :)

    Seems my Sugarcube is 2.1.1 although I will update it to the latest now. I had no idea about the <<capture>> macro, that seems way easier and I think I'll go back and use that instead.
  • Hoshikuzu wrote: »
    Seems my Sugarcube is 2.1.1 […]
    That's pretty old. Be sure to check out the release notes and upgrade instructions to see what's new and/or updated.
Sign In or Register to comment.