0 votes
by (190 points)
Hello,

I want to be able to display an array, with each item in the array appearing as a clickable item that will then move that item to a different array (trying to make items equipable in my game). How can I go about this? Thanks!

1 Answer

0 votes
by (390 points)

Here's an example of what I did as a test.

<!-Start-!>
(set:$inv to (a:))(set:$key to 1)
(link:"Pick Up the Key")[(set:$inv to it + (a:$key))]
[[Safety Box]]

<!-Safety Box-!>
(link:"Open the Box")[(if:$inv contains $key)[You open the box. (if:$inv contains $gun)[It is empty.](else:)[(link:"Pick up the Gun.")[(set:$inv to it + (a:$gun))]]]]

(else:)[You need the key.]

[[Start]]
[[Monster]]

<!-Monster-!>
(link:"Kill the Monster")[(if:$inv contains $gun)[You blow its brains out.](else:)[You need a gun.]]

[[Safety Box]]

If you're looking at creating categories of items, such as weapons, armor, potions, etc. You'd first create each individual item with its stats in a datamap. Then you can categorize them by adding them all to an array. If you do all this in a "startup" passage, the items will exist throughout the entire game and you shouldn't need to actually move items from one array to the next.

Hope that helps.

by (190 points)
That's not quite what I'm going for... I want to be able to list out the inventory, right now I have it like so:

(print: $clothes.join(", "))

and each item in the array $clothes will be displayed as clickable, which would move that individual item from the $clothes array to the $outfit array.
by (390 points)

Assuming that all of your clothes had a datafield of "type" in their datamap... i.e.

(set:$shirt to (dm:
"name","Shirt",
"type","clothes"))

And your $inv array had $shirt in it, you could us the (for:each) function to list each item.

(for:each _i,...$inv)[
       (if:$inv's (_i)'s type is 'clothes')[
                    (link:_i's name)[(set:$hero's clothes to _i))]

That would be a start, at least, I believe there are some more experienced Twiners in here that could clean that up... :-/

by (159k points)
edited by

@thetaw
One issue with your example is that the temporary _i variable referenced within the (link:) macro's assocated hook isn't evaluated until the end-users selects that link, and at that time the temporary _i won't exist. The following example demostrates this issue.

debug item value: |debug>[]

{
(set: $list to (a: "one", "two", "three"))
(for: each _item, ...$list)[
	<br>
	(link: _item)[
		(replace: ?debug)[_item]
	]
]
}


Harlowe doesn't have an equivelent of the SugarCube <<capture>> macro, so you need to use the (print:) macro to dynamically build the link and it's associated hook.

debug item value: |debug>[]

{
(set: $list to (a: "one", "two", "three"))
(for: each _item, ...$list)[
	<br>
	(print: "(link: _item)[(replace: ?debug)[ " + _item + "]]")
]
}


So the (link:) within your (for:) macro example would need to look more like the following...

(print: "(link: _i's name)[(set: $hero's clothes to " + _i + ")])")

... however if the _i variable is referencing a complex object (like a data-map) then the above technique will NOT work, because such objects don't convert to the String data-type well.
 

by (390 points)
That is very useful information. Thanks for clarifying and correcting!
by (190 points)
Okay, so I'm new to datamaps (I think I understand them now but they still seem kinda cumbersome) so how would I use those to build a dynamic inventory? I think my main sticking point is figuring out how to make each item in the array able to be a link. Using datamaps I could make them all go to the same $PutOnDesc or something but each would still need to somehow be distinguishable from others in the array
...