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.name + '|' + $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.name + '|' + $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.
Comments
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.
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:
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:
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.