0 votes
by (150 points)

Is there any way to pass information to a link hook before it's processed? I'm trying to automatically generate a set of links based on a dataset that can modify another dataset based on the specific dataset member that was being referenced when the link was generated.

Example code:

(for: each _item, ...$item_set)[{
	(link: _item)+(hook: _item)[
		(set: $current to ($current - $item_set))
		(set: $current to ($current + _item))
		(go-to: (history:)'s last)

Where $item_set is a dataset containing the names of all possible items of this type, $current is a dataset containing the current items of any type. This snippet is intended to switch out, for example, a players current helmet for whatever helmet they choose from a list generated of all available helmets. 

The attempt at naming the hook was made in hopes of being able to access the hook name from within the hook somehow to use that to pass data in, but I haven't been able to find a way to do that yet.

This looks like a sugarcube example of pretty much what I want to do, but I'm hoping to avoid having to convert everything to sugarcube and can't figure out an equivalent in harlowe.


1 Answer

0 votes
by (156k points)
selected by
Best answer

WARNING: There seems to be an inconsistency in your example:

a. The first (set:) macro is subtracting your $item_set collection (an Array?) from your $current value (unknown data type!). If those two variables both contained Arrays then this would result in the items within $item_set being removed from the $current value. If those two variables are of different data types then that would result in a "mismatched data type" related error. 

b. The second (set:) macro is adding the current _item value (unknown data type!) to your $current value (unknown data type!). Again if the data types of those to values are NOT the same then that addition would result in a "mismatched data type" related error.

c. It seems unlikely that $current would be the same data type as both $item_set and _item.


The cause of your issue is the fact that the code withing the link's associated hook isn't executed until after the link is selected, and at the time of that execution the variables referenced by that code will either:

1. Be equal to whatever value that had at the finish of the (for:) loop. (assuming they have been changes since then).

2. No-existing, like the case of the (for:) loop's _item temporary variable.

To solve this issue you need to capture the values of the relevant variables at the time that each of those links were created, and unfortunately Harlowe doesn't have an equivalent to the  <<capture>> macro you would be using if you were implementing this in SugarCube 2.

To get around this limitation you will need to use a (print:) macro to dynamically create each link from a constructed String value.

NOTE: Because of the previously mentioned inconsistency (and because you didn't give examples of the values stored within your variables) the following has been made more generic so you can see the principles required to dynamically generate a link that captures the current value of the _item temporary variable.

(set: $array to (a: "one", "two"))
(set: $variable to "")

(for: each _item, ...$array)[{
	(print: "(hook: _item)+(link: _item)[" +
				"(set: $variable to it + '" + _item + "')" +
				"(go-to: (history:)'s last)" +

... the above example does the following:

a. Places the (hook:) before the (link:) because the tw-hook element will be the parent of the HTML elements generated for the link. This is purely for aesthetic purposes because either way the same HTML structure is generated.

b, Uses the special it operator to indicate that the target variable ($variable or $current in your use-case) is being modified.

c. Uses singe-quotes to wrap the value of the _item variable, which converts that value into a String literal before trying to add it to the current value of $variable.

by (150 points)

Thanks very much for the help! Your generic code is similar enough to what I'm doing that I don't see room for error. With that said, I'm seeing "missing ) after argument list" for each iteration of the for loop. In the code example below, I see that disappear as long as I remove the line: "(set: $wearing to it + '"_helmet"')" +

Any idea what I'm doing wrong here? I don't see any mismatched parenthesis

Since you mentioned it, I'm adding some more code to help give an idea of what's going on better. I'm doing all operations with datasets, so that I can easily migrate items in and out by matching against a master list instead of trying to deal with it in various ways. Basically I want to generate a set of links:




Where clicking on for example helmet2 would remove helmet1 from $wearing and add helmet2 to $wearing. 

(set: $wearing to (ds: "helmet1", "shield1", "boots1"))
(set: $helmet_set to (ds: "helmet1", "helmet2", "helmet3"))

(for: each _helmet, ...$helmet_set)[{
	(print: "(hook: _helmet)+(link: _helmet)[" +
		"(set: $wearing to it - $helmet_set)" +
		"(set: $wearing to it + '"_helmet"')" +
		"(go-to: (history:)'s last)" +


by (156k points)
edited by

the line: "(set: $wearing to it + '"_helmet"')" +

Any idea what I'm doing wrong here? I don't see any mismatched parenthesis

There are two issues with that line of code:

1. Missing the plus symbols required to join two String values together.

If you look at the equivalent line in my example you will see there is a plus between the single-quote-double-quote pair and the _item variable, and a plus between the _item variable and the double-quote-single-quote pair. Leaving out those plus symbols is what is causing the error message you saw.

2. Trying to add two values of different data types together.

(In your latest example) The data type of the $wearing value is DataSet and the data type of the _helmet value is String, and generally Harlowe doesn't support addition (or subtraction) of values with different data types.

To get around this issues you need to convert the two values to the same data type which in this particular use-case is DataSet

(set: $dataset to (ds: "one", "two", "three"))\
dataset before: $dataset

(set: $dataset to it + (ds: "four"))\
dataset after: $dataset


So based on the above information your latest example should look like:

(set: $wearing to (ds: "helmet1", "shield1", "boots1"))
(set: $helmet_set to (ds: "helmet1", "helmet2", "helmet3"))

(for: each _helmet, ...$helmet_set)[{
	(print: "(hook: _helmet)+(link: _helmet)[" +
		"(set: $wearing to it - $helmet_set)" +
		"(set: $wearing to it + (ds: '" + _helmet + "'))" +
		"(go-to: (history:)'s last)" +


by (150 points)
That worked perfectly! Thanks greyelf!
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.