Objects linking

I have these objects in the StoryInit and want to link them through ingredients.

<<set $Parsley = {
	name: "Parsley",
	stack: 12
}>>

<<set $Fish = {
	name: "Fish",
	stack: 12
}>>


<<set setup.Casserole = {
    name: "Casserole",
    difficulty: "easy",
    ingredient1: $Fish,
    ingredient2: $Parsley
}>>

My idea is the user will scroll through a list of meals (many more than just casserole) and when they make one of them, it will reduce the “stack” attribute of the needed ingredients. What would be the easiest way to reduce the stack amount? Since ingredient1 and ingredient2 will be constantly changing, I can’t directly decrease them. I want to keep the meal on the setup object to reduce bloat. Thanks

Twine Version: 2.315
Sugarcube: 2.34

Well, there’s always the hacky option, taking advantage of (1) the JS names for the story variables and (2) the fact that if you tell Sugarcube to print something that’s also valid Sugarcube markup, it will then execute the markup:

<<print "<<set State.variables." + setup.Casserole.ingredient1.name + ".stack -= 1>>">> will print and then execute <<set State.variables.Fish.stack -= 1>>, which is functionally equivalent to <<set $Fish.stack -=1>>.

I would probably make this into a widget with the name of the recipe as the argument, something like:

<<widget cook>>
     <<print "<<set State.variables." + setup._args[0].ingredient1.name + ".stack -= 1>>">>
     <<print "<<set State.variables." + setup._args[0].ingredient2.name + ".stack -= 1>>">>
<</widget>>

Which you would call with e.g. <<cook "Casserole">>.

This assumes, of course, that the “name” property is always equivalent to the variable name minus the sigil. If it’s not (like if you have any two-word ingredients) you could add a property that is, like so:

<<set $BlackPepper = {
      name: "Black Pepper",
      varname: "BlackPepper",
      stack: 12
}>>

And then use that property instead.

But there’s probably a more elegant way to do it.

Your setup variable (setup.Casserole) cannot contain story variables. It will not track them as they change, and it doesn’t make any sense anyway, a story variable (like $Fish) is for data whose value changes through the game and needs to be tracked. A setup variable is for data which does not change through the game and does not need to be tracked. So either Casserole should be a story variable, or it should not contain story variables.

I think what you intended was:

<<set setup.Casserole = {
    name: "Casserole",
    difficulty: "easy",
    ingredient1: "$Fish",
    ingredient2: "$Parsley"
}>>

i.e. the ingredients should be the names of the variables you want to use, not the variables themselves.

You can then change those variables using State.setVar() as follows:

<<set _ingredient1 = State.getVar(setup.Casserole.ingredient1)>>
<<set _ingredient1.stack -= 1>>
<<set State.setVar(setup.Casserole.ingredient1,_ingredient1)>>

If the variables are always story variables, you can get rid of the sigil and do this:

<<set setup.Casserole = {
    name: "Casserole",
    difficulty: "easy",
    ingredient1: "Fish",
    ingredient2: "Parsley"
}>>
<<set State.variables[setup.Casserole.ingredient1] -= 1>>

I’d suggest that the second is easier, but it’s up to you.

This would be decrementing the variable as a whole, not the stack property, and <<set State.variables[setup.Casserole.ingredient1.stack] -= 1>> doesn’t appear to work.

If you change the two ingredient properties to the name of the variable as a string instead of the variable itself (which I feel dumb for not thinking of earlier!) you can still use the <<print>> workaround with the somewhat snappier <<print "<<set " + setup.Casserole.ingredient1 + ".stack -= 1>>">>. But the State.setVar() solution also works!

I think you have a typo there: put the .stack outside the square brackets, not inside. setup.Casserole.ingredient1 is the variable name, use that to select the variable’s value from State.variables[], and then .stack at the very end. If I’m reading right, that is: I just skimmed this thread…

<<set State.variables[setup.Casserole.ingredient1].stack -= 1>>

You’re right that that was a mistype on my part, but oddly, State.variables[setup.Casserole.ingredient1].stack doesn’t appear to work either — I get a “Cannot read properties of undefined (reading ‘stack’)” error. I wonder if you can’t access properties with the State.variables[] syntax?

Is this Chrome? That’s a confusing error message, but it means that you’re trying something that ends up being undefined.stack. So maybe the ingredient name is wrong? I’d try printing setup.Casserole.ingredient1 and State.variables[setup.Casserole.ingredient1] to make sure those both look right… maybe the ingredient name still has the sigil on it?

<<print setup.Casserole.ingredient1>> prints “Fish” and <<print State.variables[setup.Casserole.ingredient1]>> prints [object Object] (which is what Sugarcube always does when told to print a variable that is an object), but <<set State.variables[setup.Casserole.ingredient1].stack -= 1>> is still telling me Fish is undefined even though it’s clearly not.

Thanks learned a lot, going to play with this

Hrmph. Alright, let me stop being lazy and go try this…

This seems to work for me, though I’m using SugarCube 2.36.1 instead of 2.34. But I don’t think that should break any of this?

StoryInit

<<set $Parsley = {
	name: "Parsley",
	stack: 12
}>>

<<set $Fish = {
	name: "Fish",
	stack: 12
}>>


<<set setup.Casserole = {
    name: "Casserole",
    difficulty: "easy",
    ingredient1: "Fish",
    ingredient2: "Parsley"
}>>

Start:

<<= JSON.stringify($Fish)>>
<<set State.variables[setup.Casserole.ingredient1].stack -= 1>>
<<= JSON.stringify($Fish)>>
1 Like

Huh! No idea what’s going on on my end, but since it’s working for you I’ll stop trying to hash it out in this thread as it’s unlikely to be useful to OP.

1 Like

Ahh yes, that’s what I get for replying on my phone!

<<set State.variables[setup.Casserole.ingredient1].stack -= 1>>

Is right