Accessing object properties with array elements

I might be going about this the wrong way, but want to access an objects properties through a separate array. My objects looks like this, setup in Javascript for various ingredients. I’ll just list one here to save space.

setup.Milk = {
	name: "milk",
	cost: 10,
	stack: 15,
	desc: "Milk, it does the body good.",
};

Then I have an array with just the keys in them, I did this to save memory instead of making an array of objects.

<<set $ingredients = ["Sauces","Spices","Milk","Beans","Cheese","Eggs","Vegetables","Crackers","Pasta","Ham","Chicken","Sirloin","Fish","Butter","Potatoes"]>>

I then want to access the properties of the object using $ingredients. The only way I’ve been able to do it is using the index. For instance, this prints out the description of milk.

<<=setup[$ingredients[2]].desc>>

This does not, and returns a desc undefined.

<<=setup[$ingredients["Milk"]].desc>>

I could probably make a for loop and search when the index matches the name, but seems like it could lead to trouble down the road. Am I going about this wrong?

twine 2.315
sugarcube 2.34

Sounds like you just want to write

<<=setup["Milk"].desc>>
1 Like

The $ingredients array is needed to keep track of what ingredients the player has. So when they go to the kitchen, the can get a listing of the ingredients, descriptions, and other properties like stack (amount they currently have).

What about a conditional

<<if $ingredients.includes("Milk")>>
<<=setup["Milk"].desc>>
<</if>>

And if you want to print the description of every object, I think the best way is indeed a for loop

<<for _product range $ingredients>>
<<=setup[_product].desc>> <!-- And also whatever else you wanna print -->
<</for>>
1 Like

Your $ingredients variable contains an Array of String values, and Array elements are referenced using an Integer based index. Which in the case of JavaScript’s offset based indexes the 1st element has an index of 0 zero, the 2nd element has an index of 1 (one), and so forth…

This is why your original $ingredients[2] reference worked, because that accessed the 3rd element of the Array, which is the “Milk” String value.

As the special setup variable references a Generic Object, you could use Bracket notation like the following to access your “Milk” item…

setup["Milk"]

…which is why the print macro based code suggested by Andrew Plotkin works…

Remember you can use the indexOf() method to get the index from the ingredient name, ie:

<<= setup[$ingredients[$ingredients.indexOf("Milk")]].desc>>

Thanks all, I’m sure I can get it done using the includes or indexOf methods

While that is true, in practice it makes no sense to do so in the example you supplied…

<<= setup[$ingredients[$ingredients.indexOf("Milk")]].desc>>

…because you would need to know the value (“Milk”) of the element you want to determine the index of…

$ingredients.indexOf("Milk")

…and if you already know that value it makes more sense to use it directly to access the related property in the setup object…

setup["Milk"]

…thus why the following was supplied as a solution…

<<= setup["Milk"].desc>>
1 Like

Indeed I think the includes method with conditionals will be my best bet like below. Again the whole purpose is not to store large objects in arrays. H1ev doesn’t post anymore, but was always adamant about not doing that in Twine.

<<if $ingredients.includes("Milk")>>\
<<set _img = setup['Milk'].piclarge>>\
<img class="inv" @src=_img>
Item: <<=setup["Milk"].name>>
Desc: <<=setup["Milk"].desc>>
<</if>>\
<<if $ingredients.includes("Sauces")>>\
<<set _img = setup['Sauces'].piclarge>>\
<img class="inv" @src=_img>
Item: <<=setup["Sauces"].name>>
Desc: <<=setup["Sauces"].desc>>
<</if>>\
1 Like

Who is H1ev?

HiEv, typo on my part. But he created a lot of macros for Twine and could answer just about anything.

https://qjzhvmqlzvoo5lqnrvuhmg.on.drv.tw/UInv/Sample_Code.html#Main%20Menu

1 Like