Howdy, Stranger!

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

[Sugarcube 2 2.14.0] How do I build a generic item shop?

edited March 2017 in Help! with 2.0
Hey lads, I'm trying to build an RPG of sorts, and want the player to be able to visit a shop and buy and sell things. For this, I have created a passage called TestItems, which looks like so:
<<set $itemStrawberry = {
	name: "Strawberries",
	description: "They look so yummy!",
	categories: ["fruit", "food"],
	value: 2,
}>>
<<set $frogLiver = {
	name: "Frogman Livers",
	description: "You don't want to remember how you got these.",
	categories: ["utility"],
	value: 500,
}>>
<<set $magicPole = {
	name: "The Utdraig",
	description: "A fishing rod from the days of legend, said to always catch a fish no matter where you throw it.",
	categories: ["fishing rod", "tool", "weapon"],
	value: 500,
}>>
<<set $donut = {
	name: "Doughnut",
	description: "You're not sure what it's filled with, but it's probably fine.",
	categories: ["pastry", "food", "dish"],
	value: 5,
}>>

<<set $itemlist = [$itemStrawberry, $frogLiver, $magicPole, $donut]>>

This gets included in StoryInit, so the list is always available.

I want there to be a generic item shop, so that each individual shop the player encounters contains an array of indices corresponding to the items I want that particular shop to sell. That would look like this:
<<set $testshop = {
	name: "Random Tat",
	stock: [0, 2, 3],
}>>
Now to my problem. I want to be able to generate a list of links which each would perform the respective transaction, ie. I'd get a link for the strawberries, clicking on it would then add the strawberries to my inventory and remove my money. Thing is, the only way I can come up with to do so seems to be a for-loop building a click event for each item, but in doing so all the links would break since they'd all point to an empty object:
Welcome!
$testshop.name currently carries:

<<for _i = 0; $testshop.stock[_i] < $itemlist.length; _i++>>
	<<click $itemlist[$testshop.stock[_i]].name>>
		<<addToInv $itemlist[$testshop.stock[_i]].name>>
	<</click>>
	<<print $itemlist[$testshop.stock[_i]].description>>
	
<</for>>
Just to reiterate, I'm aware that this code doesn't work because _i is only queried after building the page, by which point it is equal to $itemlist.length.
The inventory system is currently an array which doesn't allow multiple identical objects to exist (taken straight from the link in the Twine 2 Guide, since I'm completely new to all this). This is, however, irrelevant because the issue remains that no matter which link I click I get an empty object. My question thus is, can I somehow save each iteration's number value to draw from when clicking a link, or, if not, what else could I do to make this work instead? Can I avoid to hardcode each shop's inventory?

I thank you all in advance,
vm.

Edit: Added Sugarcube version number.

Comments

  • You should always state the story format you're using and its version, because advice will tend to vary based on that information.


    If you're using SugarCube ≥v2.14.0 (≥v2.15.0 for full support), then you may use the <<capture>> macro to capture the value of _i. This is the recommended method of accomplishing your goal. For example:
    <<for _i = 0; $testshop.stock[_i] < $itemlist.length; _i++>>
    	<<capture _i>>
    		<<link $itemlist[$testshop.stock[_i]].name>>
    			<<addToInv $itemlist[$testshop.stock[_i]].name>>
    		<</link>>
    	<</capture>>
    	<<print $itemlist[$testshop.stock[_i]].description>>
    
    <</for>>
    


    Elsewise, if you're using SugarCube <v2.14.0, then you'll have to use the Stupid Print Trick™ to cause the inner _i to be evaluated early—i.e. when the link is created, rather than when it's activated. For example:
    <<for _i = 0; $testshop.stock[_i] < $itemlist.length; _i++>>
    	<<print '<<link $itemlist[$testshop.stock[_i]].name>><<addToInv $itemlist[$testshop.stock[' + _i + ']].name>><</link>>'>>
    	<<print $itemlist[$testshop.stock[_i]].description>>
    
    <</for>>
    


    PS: <<click>> is deprecated, you should be using its replacement <<link>>.
  • If you're using SugarCube ≥v2.14.0 (≥v2.15.0 for full support), then you may use the <<capture>> macro to capture the value of _i. This is the recommended method of accomplishing your goal. For example:
    <<for _i = 0; $testshop.stock[_i] < $itemlist.length; _i++>>
    	<<capture _i>>
    		<<link $itemlist[$testshop.stock[_i]].name>>
    			<<addToInv $itemlist[$testshop.stock[_i]].name>>
    		<</link>>
    	<</capture>>
    	<<print $itemlist[$testshop.stock[_i]].description>>
    
    <</for>>
    

    Worked like a charm. Thank you.
Sign In or Register to comment.