0 votes
by (120 points)

I'm using Harlowe 2.1.0 and I'm not sure if there's something I'm missing. 

I want to track two stats in my game: energy and pride, and have them visible in the header at all times. This is what I've added to the header passage (nevermind the Swedish words before the variables):

Energi: $energy
Stolthet: $pride

And this is what's in the first passage of the story:

(Set: $energy to 10)
(Set: $pride to 10)

[[Nu börjar det!->Start]]

Problem is, the energy and pride shown in the first passage is 0, not 10. Not until I click the link below and go to the "start" passage, the number bumps up. 

I've tried to google how to show the variables as ten from the get go, but had no success.

Thankful for any help or advice. This is my first time attempting to make a game with Twine :)

3 Answers

0 votes
by (63.1k points)

Warning: Gross oversimplifications ahead. 

Twine formats use a parser to read your code, turn it into something the browser understands, and then having the browser display it. This process is expensive (meaning it takes time for it to happen, even if it feels sort of quick), so the formats get around this by basically reading your code once, when a passage is first rendered, and that's about it. 

In Harlowe, you can force a chunk of the page to be rerendered over and over again on a time interval using the (live:) macro, but this is incredibly wasteful, and generally not something you want to do if it is at all possible to avoid. This means your only real option is to force the part of the page you need to update when you need it to update. 

The easiest way to go about this is to use the (display:) macro (so we only need to write the code we want updated once), and the (replace:) macro, to actually update our code. We'll also need to use a named hook to allow our (replace:) macro to selectively target a part of the page. For more on all of these and their finer points, please refer to the documentation at https://twine2.neocities.org which is maintained by the author of Harlowe, and is basically the Bible for working with that format. It's also all one document, meaning its easily searchable. 

First we need to make a passage to display. We'll call it 'stats' to simplify things, and put what is currently in your header there. 

:: stats
Energi: $energy
Stolthet: $pride

Note that this code is written in Twee notation, so the ': :' represents a passage name. 

Next, in the header, we need to display the 'stats' passage and we need to place it in a hook. 

:: header [header]
|statdisplay>[(display: 'stats')]

I called the hook 'statdisplay', and we can refer to this hook using a '?', so it becomes `?statdisplay' when we need to interact with it. Also note that in Twee notation, passage tags go inside brackets next to the passage name. 

Now we'll need to use code like this to rerun the code in our header whenever those stats are updated: 

:: some passage
(set: $energy to 10)
(set: $pride to 10)
(replace: ?statdisplay)[(display: 'stats')]
[[Nu börjar det!->Start]]

I made a few other minor changes: 

  • Don't use upper-case letters in macro names. It will usually work, but isn't recommended. 
  • I placed the code in braces ({}), which will eliminate unwanted line breaks in the passage output. 

 You will need to use this replace code any time you update your stats, which is a bit inconvenient, but it's the easiest and most cost-effective way to achieve what you want. 

You can also place that code in a footer-tagged passage, to have it run on each passage, but after your changes are made. If you use any interactive elements like (link:) to update any stats, though, you'll need to add the replace in there, even if it's in the footer. 

by (68.6k points)

Passage headers are processed before the regular text of any passage, so attempting to access the variables before your code has modified their values is not going to work the way you want.  Chapel offers some workarounds for that issue in their answer.

Additionally.  You should probably be initializing your values within a startup tagged special passage, rather than the starting passage.

0 votes
by (2.7k points)

I could reproduce your issue.

It worked as expected after putting the two setter lines into a new passage tagged with the header 'startup' (without quotes of course).

(Set: $energy to 10) 
(Set: $pride to 10)

The header tagged passage is unchanged.

In the first passage, there is still the link left

 [[Nu börjar det!->Start]]

But this time the points should show 10 already before clicking the link.

Hope, this works for you.

0 votes
by (6.2k points)

If you want variables to change on screen as soon as their values are changed, use the (live:) macro.

(live: 0.00001s)[$energy

Every 0.00001 seconds, everything within the brackets will be resent to the screen, making it look like it updates immediately for the player.

by (159k points)
edited by

Using the (live:) macro this way is not a good idea for many reasons, the main two being:

1. Each (live:) macro creates it's own timer event thread, and such threads need to take control of the page away from the end-user each time the code contain within the macro's associated hook is executed, and that control isn't returned to the end-user until the execution of the code has finished.

Simple put, while the code of the (live:) macro's associated hook is being executed the end-user can't interate with the page. eg. can't select links.

2. The values being shown on the page only need to be changed when the associated variable has been changed.

Dynamic updating of the current page is an expensive process in regards of the time and resources needed to change the web-browser's HTML Document Object Model (DOM).

If you are updating the related area of the page every 10,000th of a second then it extremely likely that 99.99% of those "page area updates" will be a waste of both time & resources because the variable values will be the same as they were the last time that area was updated.

by (6.2k points)
Thank you for explaining this to me. I will take care in future when using (live:) macros.