Howdy, Stranger!

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

Current variable value for loop (Twine 2, Sugarcube)

I'm working on an inventory system and I've fixed lots of little problems so far...the only problem is this:
<<set $items to ["testitem", "stick", "rock", "watch"]>>
<<set $locs to ["inv", "Your Bedroom", "Your Bedroom", "Upstairs Hallway"]>>
<<set $desc to ["Test", "A small stick broken from a tree branch.", "A smooth stone.", "A plain digital watch."]>>

<<widget "roominv">>
You can see:

<<nobr>>
<<for $i to 0; $i < $items.length; $i++>>
<<set $baseString to "(T): Take the " + $items[$i] + "">>
<<set $passageString to passage()>>
<<if $locs[$i] is passage()>>
    <<print "a " + $items[$i]>>
	<br>
<</if>>
<<if $locs[$i] is passage()>>
    <<click $baseString $passageString>>
    	<<if $invCur < $invMax>>
This is where the problem is:
        	        <<set $locs[$i] to "inv">>
        	<<set $invCur to $invCur++>>
        <<else>>
        	<<alert "You can't pick it up: you're carrying too much as it is.">>
        <</if>>
    <</click>>
    <br>
<</if>>
<</for>>
<</nobr>>
<</widget>>

I need $i to be whatever it is during that iteration of the loop, and not equal to what it is afterward. (Which happens to be the length of the array; I checked.)

For example, the 3rd link printed (3rd iteration of the for loop):

<<set $locs[2] to "inv">>

Or, for the 7th link printed:

<<set $locs[6] to "inv">>

If I replace the $i value with a specific number, the inventory works perfectly (I can pick up and drop the item represented by the number, and it's added to the current room and stays there. I just can't do it with the other items.) Is there a way to do this, or some sort of workaround, if possible?

Comments

  • The $i inside the <<click>> is being bound late (i.e. when the player clicks it). You're going to have to force the $i to be bound early (i.e. when the <<click>> is constructed).

    Try the following, it's ugly, but it should work:
    <<widget "roominv">>
    You can see:
    
    <<nobr>>
    <<for $i to 0; $i < $items.length; $i++>>
    <<set $baseString to "(T): Take the " + $items[$i]>>
    <<set $passageString to passage()>>
    <<if $locs[$i] is passage()>>
        <<print "a " + $items[$i]>>
        <br>
        <<print '<<click [[' + $baseString + '|' + $passageString + ']]>><<if $invCur < $invMax>><<set $locs[' + $i + '] to "inv">><<set $invCur++>><<else>><<alert "You can\'t pick it up: you\'re carrying too much as it is.">><</if>><</click>>'>>
        <br>
    <</if>>
    <</for>>
    <</nobr>>
    <</widget>>
    
    I also fixed a few oddities in your shown example (back to back <<if>>s which had the exact same condition and you don't need to assign when you use the increment/decrement operators, they modify the variable's value in-place).
  • edited September 2015
    You can use a <<print>> to output the <<click>> code, it would look something like the following:
    note: I was not able to test this using your example because I don't know the values of the other variables.
    <<if $locs[$i] is passage()>>
    
    <<for $i to 0; $i < 5; $i++>>
    	<<print "<<click $baseString $passageString>><<if $invCur < $invMax>>This is where the problem is:<<set $locs[" + $i + "] to \"inv\">><<set $invCur to $invCur++>><<else>><<alert \"You can't pick it up: you're carrying too much as it is.\">><</if>><</click>>">>
    <</for>>
    
    <</if>>
    
    ... the important part is the + $i +, which is taking the current value of the loop's $i variable and concating it to the "click macro" string being built, said string is then <<print>>ed which turns it back in to code. The double quotes within the "click macro" string needed to be escaped using a backslash.
  • Works like a charm, thanks!
Sign In or Register to comment.