How would i go about a push and an equip function for this?

So im trying to make an armor system work where you’d equip something and it would be added to your character, but unfortunately when i do my macro to show the list of what you can equip, it only shows the most recent one that is pushed into your inventory!

here is the for macro function im doing to select your equipment

<<nobr>>
<<for _i, _item range $head>>
	<<if _item.gear>>
        	<<print "'' _item.gear''" +"'':''">><br>
    		<<print _item.details.description>><br>
            	<<if _item.details.equipped is false>>
                	<<link "Equip" "testpassage">>
            			<<set _item.details.equipped to true>>
                    	<<print _item.details.stats>>
					<</link>>
                <<else>>
                	<<link "Remove" "testpassage">>
            			<<set _item.details.equipped to false>>
                    	<<print _item.details.undostats>>
                    <</link>>
                <</if>>
		<</if>>
	<</for>>
<</nobr>>

here are the push and set functions that lead up to it,

<<set $head to ({
	    gear: "",
        details: {
        	equipped: "",
        	description: "",
        	stats: "",
        	undostats: ""
            }
})>>

<<set $head.push to ({
	    gear: "Leather Cap",
        details: {
        	equipped: false,
        	description: "A gift from side character A",
        	stats: "<<set $armor +=1>>",
        	undostats: "<<set $armor -=1>>"
            }
})>>
<<set $head.push to ({
	    gear: "Leather Cap the sequel",
        details: {
        	equipped: false,
        	description: "A gift from side character B",
        	stats: "<<set $armor +=1>>",
        	undostats: "<<set $armor -=1>>"
            }
})>>

when i test the program, it only shows “leather cap the sequel” “A gift from side character B” and the button to equip it, but it doesnt show the first leather cap or anything about it!

First of all, if you’re going to use push, which is an array method, you want $head to be an array:

<<set $head to []>>

Then you add new elements with <<set $head.push()>>

<<set $head.push({
	    gear: "Leather Cap",
        details: {
        	equipped: false,
        	description: "A gift from side character A",
        	stats: "<<set $armor +=1>>",
        	undostats: "<<set $armor -=1>>"
            }
})>>

That said, if the stats don’t change throughout the game, it’s best to use the setup object instead of story variables, as Greyelf explained here.

I tried doing the <<set $head to []>> macro to replace what i had set it to prior, but when i did that, the <<for>> macro i used just prints nothing at all.

p.s: I’ll change it over to setup.head soon but i dont quite fully understand the differences between them, i’ll try to reread their post again but it hasnt done much to change the outcome when id try it out. I’m still learning how this all works so i’ll take the time to figure that out. the only thing in that function that changes is Equipped changing to true via the For macro

You also need to fix the way you’re using the push method. It’s <<set $head.push([gear])>>, not <<set $head.push to ([gear])>> like you’re using. This code works for me:

<<set $head to []>>

<<set $head.push({
	    gear: "Leather Cap",
        details: {
        	equipped: false,
        	description: "A gift from side character A",
        	stats: "<<set $armor +=1>>",
        	undostats: "<<set $armor -=1>>"
            }
})>>
<<set $head.push({
	    gear: "Leather Cap the sequel",
        details: {
        	equipped: false,
        	description: "A gift from side character B",
        	stats: "<<set $armor +=1>>",
        	undostats: "<<set $armor -=1>>"
            }
})>>

<<for _i, _item range $head>>
	<<if _item.gear>>
        <<print "'' _item.gear''" +"'':''">><br>
    	<<print _item.details.description>><br>
        <<if _item.details.equipped is false>>
            <<link "Equip" "testpassage">>
            	<<set _item.details.equipped to true>>
                <<print _item.details.stats>>
			<</link>>
        <</if>>
    <<else>>
            <<link "Remove" "testpassage">>
            	<<set _item.details.equipped to false>>
                <<print _item.details.undostats>>
            <</link>>
	<</if>>
<</for>>

As for using story variables vs using setup, story variables are for variables that change during play, and setup is for variables that don’t. Every time a player moves to a new passage, the current state of the story gets saved to the history so that the player can undo their turn if they want. This includes all the story variables—since they can change throughout the story, the game needs to remember what their value was at that moment so it can return to it if the player wants. The history and the story variables also get stored in the saves, for obvious reasons.

This means that if you store your equipment data in the story variables, a new copy gets made every time the player navigates to a new passage, which is wasteful. Since the data doesn’t change throughout the playthrough, you only need one copy. It’s not normally a huge issue, but if you’re storing a lot of data it can cause slowdowns on passage transitions or bloated save file sizes.

The fact that the story variables get stored in the saves also causes another problem. Say you notice there’s a bug in your equipment data (for example you gave the wrong stats to a helmet). So you update your story so that the helmet has the correct stats. But if a player who was playing your game before the update loads their save, all the story variables from their save file get loaded into their game—which includes the helmet variable with the incorrect stats! This doesn’t happen with setup.

In your case, the only thing that changes in your equipment data is whether a piece of gear is equipped or not, so it’s better to store the equipment data (description, stats, undostats) in setup then have an array that contains the currently equipped gear, as Greyelf explained in their post.

Ahhhhhh i see, thanks for letting me know! Also thanks for the help! the inventory system was setting back my development of this game for like a month now!

okay i am realizing now that when i click the links for equiping the item that the game registers that i have equipped the sequel leather hat no matter which link i click on, so i tried adding a 3rd option by doing a push for “Sir leather cap III” , and now when i use the equip link now, it just runs the equip link for whichever gear was the last one to be added, even running their stat boosts in the process. heres what i have

<<for _i, _item range setup.head>>
	<<if _item.gear>>
    <<if _item.details.equipped is true>>
    <<print "You are currently wearing the '' _item.gear''">>
	<br><br>
    <</if>>
    <</if>>
<</for>>

that one shows what is equipped

<<for _i, _item range setup.head>>
	<<if _item.gear>>
        <<print "'' _item.gear''" +"'':''">><br>
    	<<print _item.details.description>><br>
        <<if _item.details.equipped is false>>
            <<link "Equip" "testpassage">>
            	<<set _item.details.equipped to true>>
                <<print _item.details.stats>>
			<</link>>
    <<else>>
            <<link "Remove" "testpassage">>
            	<<set _item.details.equipped to false>>
                <<print _item.details.undostats>>
            <</link>>
		<</if>>
    <</if>>
    <br>
    <br>
<</for>>
<</nobr>>

this one is what i use to equip stuff

is there a way to prevent it from doing this issue? I cant quite find anything like this online. is there a way to reference a specific item’s equipped status in arrays or something?

You need to wrap your links in a <<capture>> macro, for reasons explained here.

<<for _i, _item range setup.head>>
    <<capture _item>>
	    <<if _item.gear>>
            <<print "'' _item.gear''" +"'':''">><br>
    	    <<print _item.details.description>><br>
            <<if _item.details.equipped is false>>
                <<link "Equip" "testpassage">>
            	    <<set _item.details.equipped to true>>
                    <<print _item.details.stats>>
		    	<</link>>
            <</if>>
        <<else>>
                <<link "Remove" "testpassage">>
                	<<set _item.details.equipped to false>>
                    <<print _item.details.undostats>>
                <</link>>
    	<</if>> 
    <</capture>>
<</for>>

But since you moved the data to setup, you can no longer use _item.details.equipped to store whether the item is equipped. Doing this means that the players current equipment wouldn’t be saved. You need to use, for example, an array like this:

<<set $equipment to {
    head: "",
    body: ""
}>>

You can then equip gear like this:

<<if $equipment.head != _item.gear>>
    <<link "Equip" "testpassage">>
        <<set $equipment.head to _item.gear>>
        <<print _item.details.stats>>
    <</link>>
<</if>>

unequip it like this:

<<set $equipment.head to "">>

and check your equipment like this:

<<print "You are currently wearing the $equipment.head">>
1 Like

Thanks so much! My code is finally working without issue! You’re the best, man!

1 Like