How can I build a large story most efficiently?

Twine Version: 2.3.5
Story Format: Harlowe 1.2.4

I realize this is a very general question, so I’m mostly looking for a starting point for solving any of these issues and suggestions on any resources that might explain them better.

I am working on a story that I anticipate will become big enough to slow down the interface in Twine (I’m at around 300 passages and barely in the beginning of the first chapter) and although the story I planned out is quite big, I suspect a large amount of the passages in the project are unnecessary. I have implemented features that I like and I have been able to make things work on a surface level, but I feel that I lack “common sense” when it comes to the code.

For example, I have many instances where Passage 1 will lead to an “invisible” Passage 2 that only exists to execute code before moving on to Passage 3, which I’ve read somewhere is bad, though I wouldn’t be able to say why. I would change this if I only knew some other way. I also tend to use if/else statements to solve everything I want to do with the game, which feels excessive. I’ve spent time reading the wiki of course, but it does not offer much context in terms of efficiency.

In other words, the game functions almost exactly like I want it to at the moment, but if someone more experienced looked over the code, I’m sure they would start feeling nauseous real fast. And my worry is that if I keep going with the same method, it will cause problems down the line and I’ll have to overhaul the entire thing to make it work.

Currently I am looking into using grunt-entwine-quickstart to eventually combine multiple stories and hopefully export it as a desktop application. I’d be interested to hear from anyone who has done this or used a similar method.

I’m pretty set on using my current story format as it is the only one where I can get backgrounds, audio and video to work and it’s the only format I’m familiar with. It is also the version I used when I created the structure of the game. If using the newer version will be easier in the long run I’m open to changing it provided it doesn’t fundamentally change too much in terms of how the coding works or mess up the work I’ve already started.

I suppose the most important questions are 1. Can I export variables between separate html files to save player choices and 2. Is there any resource for Twine specifically where I can find basic “do’s and don’ts”, such as how many if/else statements are acceptable within a passage and so on.

Otherwise I’m interested to hear viewpoints on how to best structure a story with many variables and passages without slowing down the interface too much.

2 Likes

The story’s History system tracks which Passages the reader has visited, the order that the visited, and the current value of any Story Variables that were changed within the ‘current’ Passage. Each time you transition from one Passage to another the story’s History system is updated, which takes time and memory.

When you add an ‘invisible’ Passage (one the reader doesn’t get to see the content of) into the path the reader is traveling through your story it results in the History being larger than actually needed, which results in it using more memory.

If you want to use a Passage to contain game logic, then you could use the (display:) macro to ‘execute’ its contents within the current Passage.
(untested example)

Blah blah...

(link-reveal-goto: "Link Text", "Next Passage")[
	(display: "Passage containing Game Logic that updates some variables")
]
2 Likes

Thank you, that makes sense. Would it also be better to use the display macro in an inventory passage instead of writing out all the if statements to show an item in one passage?

At the moment I have multiple lines that look like this

(if:$item1 is true)[[[image of item]]]

in an inventory passage for every item and it’s starting to feel a bit clunky.

warning: The following code examples have not been tested, they may contain syntax errors.

The subject of how to implement an ‘Inventory’ is a complex one, as there are isn’t one ‘correct’ method because the list of features & behaviours wanted by an Author can vary greatly. Two of the more basic methods are…

  1. You can use Boolean variables (like you have done) to represent if the Reader has an ‘item’ or not.
    note: the ‘correct’ way to base a condition on the current value of a Boolean variable is…
<!-- Checking if a variable equals true -->
(if: $hasLantern)[You use the lantern to illuminate the dark room...]

<!-- Checking if a variable equals false -->
(if: not $hasLantern)[The room is too dark to see what it contains...]

<!-- Checking if a variable equals true or false -->
(if: $hasLantern)[You use the lantern to illuminate the dark room...]
(else:)[The room is too dark to see what it contains...]

(if: not $hasLantern)[The room is too dark to see what it contains...]
(else:)[You use the lantern to illuminate the dark room...]
  1. Using an Array variable to track the items the Reader has…
<!-- pre-initialise the Array variable, likely done in the project's startup tagged Passage. -->
(set: $carrying to (a:))

<!-- Adding an item to the array -->
(set: $carrying to it + (a: "lantern"))

<!-- Using the Array's length property to determine how many items are being carried. -->
(if: $carrying's length > 0)[You are carrying (print:  $carrying's length) items]
(else:)[You aren't carrying anything.]

<!-- Removing an item from the array. -->
(set: $carrying to it - (a: "lantern"))
2 Likes