Dialog pop-up using wiki from a for loop with a variable passage name

Twine Version: 2.3.9
Story Format: SugarCube 2.33.2

I have a passage that is called from multiple places (cell, laptop, desktop, etc.) where the player can buy and read ebooks to increase their stats. I have everything working except for one thing. I have a passage set up for the text of each ebook, and I’m trying to open it in a pop-up window, so it can be read and closed without changing the underlying passage. For example, I have an array of ebooks that looks like:

<<set $ebooks to {
	basiclockpick: {
		name: 'Lockpicking for Dummies',
		description: 'Basic introduction to lockpicking',
		intellect: 10,
		reflexes: 10,
		owned: false,
		price: 20,
	advancedlockpick: {
		name: 'Advanced lockpicking',
		description: 'Opening almost any lock',
		intellect: 70,
		reflexes: 70,
		owned: false,
		price: 100,

And here is how I iterate the loop. Everything works nicely so far, including buying and proper IF statements for buying/owned/not enough money, except for when trying to read and it opens a new pop-up dialog. In this sample, I have two passages called “basiclockpick” and “advancedlockpick” which match the name of the _name variable.

I’m guessing it’s due to the use of the ‘_’ variable as, as I use other pop-ups like this with static passage names and they all work properly. I don’t think the JS can access the temporary variables? If so, is there a way to do this without creating more global variables?

<<for _i, _name range $ebooks>>\
	<<hovertip 'Description: _name.description<br/>Intellect: + _name.intellect<br/>Reflexes: + _name.reflexes'>><<print _name.name.toProperCase()>><</hovertip>>
	Price: $$_name.price
	<<if _name.owned>>\
		<<link "Read">>
				Dialog.setup(State.getVar("_name.name")); /* Get pop-up book title name for pop-up title */
				Dialog.wiki(Story.get(State.getVar("_name")).processText()); /* open the _name passage */
	<<elseif not _name.owned and $mc.money >= _name.price>>\    /* if not owned and have enough money */
		<<capture _name>>\
		<<link Buy>>\
			<<set _name.owned to true>>\
			<<set $mc.money -= _name.price>>\
			<<goto `passage()`>>\   /* reload passage */
	<<elseif not _name.owned and $mc.money < _name.price>>\  /* if not owned and not enough money */
		Not enough money!
	<<set _count + 1>>

I’ve tried it like above, as well as:


First off, you don’t need to do that within a <<script>> macro.

Second, if you’re going to use State.getVar(), then you need to pass the name of the variable as a string (e.g. State.getVar("_varName")).

Third, instead of using State.getVar(), the best way to access variables from JavaScript is to use State.variables for story variables and State.temporary for temporary variables.

Fourth, doing Story.get() on _name just isn’t going to work, no matter how you write it, because _name is a generic object, when the parameter that function needs has to be a string. I’m guessing you mean to use _name.name there?

Fifth, you’re going to need to <<capture>> the value of _name, since this is called inside of a <<link>>.

Put that all together and we get this:

		<<capture _name>>
			<<link "Read">>
				<<run Dialog.setup(_name.name)>> /* Get pop-up book title name for pop-up title */
				<<run Dialog.wiki(Story.get(_name.name).processText())>> /* open the _name passage */
				<<run Dialog.open()>>

Assuming that _name.name is the name of a passage, that should work.

Hope that helps. :grinning:

EDIT: Fixed the missing <<capture>> part.

1 Like

That does make sense. I was using a few older references about the dialog API for buttons and just copied the code between the <<button>> and <</button>> tags. This was one of the links I had based it on, from Reddit.

The way I had set up the passages, was the name matched the $ebooks.‘x’ values. Thus, each passage was named ‘basiclockpicking’ and ‘avancedlockpicking’ and so on to match that setup… but it’ll be easy enough to change it to match the _name.name.

When I had initially tried to get it to work I had the capture tags there, but when it wasn’t working, I stripped it out as part of the reducing the code to minimal and then started trying to find where it had broken. Thanks for catching that.