+3 votes
by (550 points)

I'm trying to manipulate an object generically by setting a temporary variable to act on that is supposed to modify the original object. What I think is happening is that I'm making a copy of that object and modifying the copy, which leaves the original untouched.

Here is my code:

resource tester

<<nobr>>
<<set $chosenResource>>
<<set $Water = {
"name" : "Water",
"type" : "resource",
"resourceType" : "standard",
"amount" : 0,
}>><</nobr>>\
\
You have <<=$Water.amount>> water rations left
\<<set $Water.amount += 1>>
You have <<=$Water.amount>> water rations left
\<<set $Water.amount -= 1>>
You have <<=$Water.amount>> water rations left

<<link "Fill" "incrementResource">><<set $chosenResource = $Water>><</link>>

incrementResource:

<<= $chosenResource.name>>: <<= $chosenResource.amount>>
Adding 1
\<<set $chosenResource.amount += 1>>
<<= $chosenResource.name>>: <<= $chosenResource.amount>>
<hr>
<<set _temp = State.index(State.length - 2).title>>\
<<link "Continue" _temp>><</link>>

 

How do I set a variable to reference an existing object, instead of copying an object?

1 Answer

+1 vote
by (63.1k points)
selected by
 
Best answer

It is possible to do this.  The problem you're having is that the State is copied to each passage, and references to variables, because they're shallow copies, get broken on each new passage (i.e. they don't reference the new copies in the current State).  This means that your code setting the $chosenResource needs to be moved into your new passage for the reference to work the way you want it to.

There's a few ways to do it, but here's how I would handle it:

:: StoryInit
<<set $chosenResource>>
<<set $Water = {
    name : "Water",
    type : "resource",
    resourceType : "standard",
    amount : 0,
}>>
/% note that you don't need to quote object keys--they aren't strings, technically %/

:: a-passage
You have <<=$Water.amount>> water rations left
\<<set $Water.amount += 1>>
You have <<=$Water.amount>> water rations left
\<<set $Water.amount -= 1>>
You have <<=$Water.amount>> water rations left

<<link "Fill" "incrementResource">>
    <<set $chosenResource = 'Water'>>
    /% set it to the variable's name, but omit the sigil %/
<</link>>

:: incrementResource
/% set the reference inside the passage %/ \
<<set $chosenResource = State.variables[$chosenResource]>>\
\
<<= $chosenResource.name>>: <<= $chosenResource.amount>>
Adding 1
\<<set $chosenResource.amount += 1>>
<<= $chosenResource.name>>: <<= $chosenResource.amount>>
<hr>
[[Continue|previous()]]
/% simplified return link; 
   be sure to delete the auto-created 'previous()' passage %/

 

by (550 points)
Awesome! This was the final straw that made me switch from Harlowe to Sugarcube, and I'm happy to be past it.

Thank you for your help!

Also, what do you mean by 'be sure to delete the auto-created 'previous()' passage'?
by (2.1k points)
I believe he means that if you type that into the twine editor, it will automatically create a passage called previous(). It assumes you're trying to link to a passage called "previous()" as opposed to using a function.
...