Cannot display object elements in Listbox

Please specify version and format if asking for help, or apply optional tags above:
Twine Version: 2.3.13
Story Format: SugarCube 2.34.1

Hi, i am newbie and have been googling for a while without any success. So i hope anyone here can help me.

I am trying to use dropdown box to let a player select which enemy he/she wants to fight.
I have made an object of each monster contain things like “name” and “hitpoints”
Then I pushed all the enemies in an array $enemyList.

I was hoping i could use the listbox interactive macro for this selection.
It works but the labels of all the options is [object.object]

Is there a way display the name from the enemies in the array?
Why does it say object.object?

image

First, any time you find yourself numbering variables, you’re probably better off using an array instead. In other words, instead of $enemy1, $enemy2, $enemy3, and $enemy4, each of those should be an element in the $enemy array, like this:

<<set $enemy = []>>
...(push the first three enemies here)...
<<set $enemy.push({
	name: "The Dragon",
	addfails: 5,
	hitpointsLow: 3,
	hitpointsRange: 4,
	image: "..."
})>>

This allows you to deal with the data using a loop, rather than having to write separate code for each variable.

Anyways, to answer your main question, the reason why the listbox is showing [object Object] is because you’ve passed objects to the $enemyList array, instead of strings. You should do this instead:

<<set _collection = new Map()>>
<<for _idx, _obj range $enemy>>
	<<set _collection.set(_obj.name, _idx)>>
<</for>>

<<listbox "$selectedEnemy">>
	<<optionsfrom _collection>>
<</listbox>>

That will cause $selectedEnemy to be set to the index of the object selected within the $enemy array when the user selects a value from the listbox.

You can verify that the above code works by adding the following code to see/debug the above code:

  - ''Value:'' <span id="val"></span>

<<script>>
	/* Wait for passage to render... */
	$(document).one(":passagerender", function (element) {
		/* ...and then set the initial value shown after "Value:". */
		$(element.content).find("#val").empty().wiki("$selectedEnemy");
		/* Also, wait for the player to change the listbox... */
		$(element.content).find("#listbox-selectedenemy").on("change", function (el) {
			/* ...and then update of the value shown after "Value:". */
			$("#val").empty().wiki("$selectedEnemy");
		});
	});
<</script>>

That will cause the value of $selectedEnemy to be displayed after the “Value:” bit on the page, even if you change the listbox.

Once the player has selected the enemy, you can use things like $enemy[$selectedEnemy].name to get the selected enemy’s name, etc…

Hope that helps! :slight_smile:

P.S. Please post code within a code block (using the preformatted text </> button), instead of as an image, so that people can copy-and-paste your code, rather than forcing them to have to retype it. Thank you!

1 Like

Great! It works. :smiley: Thanks a lot for the explanation. Eventually, I got what you were doing. Sorry for not posting a code block.