Remember what has been revealed between passages

Twine Version: 2.11.1.0

I’m using Sugarcube 2, and while I have some basic HTML, CSS, and Javascript knowledge I’m mostly self-taught and don’t know much of the terms and words for what I’m looking for, so I apologise if I am unclear or if I don’t understand specific terms. Essentially; explain like I am five years old.

I have clickable text that reveals new text (using linkreplace and append). The way I have it written is to make the revealed text appear underneath the initial text, and I want to keep it that way.

What I am looking for is a way for the game to remember what has been clicked (and thus revealed) and what has not when moving between passages. This is to minimise the amount of times a player has to reclick the same things when exploring rooms or scenes ie. moving between passages. I have nested appends in passages, and I figure that can grow tiresome if you have to retrace these nested lines of text multiple times. At the same time, I do not want all information to be on screen immediately, both due to spoilers, but also as to not overwhelm players with walls of text. I have seen the Line-by-line text reveal by JoshuaGrams(was not allowed to link this, maybe since I’m new?), but since my story isn’t linear, and my Javascript knowledge isn’t that great, I haven’t been able to use it; though I like the function of being able to switch between passages and still only have what has yet been revealed fully visible.

I figure there is a way to do this using StoryInit and setting $variables, but I have never used these functions before, and it’s tripping me up. What are the pros and cons using these functions to remember revealed text, and how could I implement it? Does it scale well? Is it possible at all, or have I misunderstood use of variables?

Here is how I have some of the passages written. I don’t mind having to change things around for this to work, but preferably this will keep it’s base functionality:

<<nobr>>
Initial Text Start,
          <<linkreplace 'OBJECT_A'>>
              OBJECT_A
              <<append '#more' t8n>>
                  <br>
        DESCRIPTION OF OBJECT_A. FOLLOW-UP TEXT WITH
                  <<linkreplace 'ACTION_A'>>
                   ACTION_A
                   <<append '#more' t8n>>
                    <br>
                     RESULT OF ACTION_A.
                      <</append>>
                      <</linkreplace>>
         .
              <</append>>
          <</linkreplace>>
, CONTINUES 
                  <<linkreplace 'OBJECT_B'>>
                      OBJECT_B
                      <<append '#more' t8n>>
                          <br>
                          DESCRIPTION OF OBJECT_B.
                      <</append>>
                  <</linkreplace>>
FINALLY 
                <<linkreplace 'OBJECT_C'>>
                    OBJECT_C
                    <<append '#more' t8n>>
                        <br>
                        DESCRIPTION OF OBJECT_C.
                    <</append>>
                <</linkreplace>>.
<</nobr>>

@@#more;@@

Thank you so much for any help!

1 Like

@Hituro’s Click To Proceed (CTP) macros might do what you’re looking for?

1 Like

Yes, the easiest way to keep track of whether a player has or has not seen something is to use variables, and if you want to do anything more complicated in Twine than the kind of straight branching you’d see in a paper Choose Your Own Adventure book, you are going to need variables and should try to get comfortable with using them instead of looking for some sort of workaround that’s almost certainly going to end up being more effort for worse effect.

The way you would do it is inside your <<linkreplace>> for OBJECT_A for example, you would put <<set $seenObjectA = true>> (or whatever you want to call your variable). You don’t necessarily need to initialize it by writing <<set $seenObjectA = false>> in StoryInit although it’s often considered best practice to do so, especially if you like to use the “test from here” functionality of the Twine editor.

Then in each passage where OBJECT_A appears (since your game is not linear), you’d also put something like this:

<<if $seenObjectA>>
  This is the OBJECT_A that you did (action) to.
<<else>>
   (the markup for OBJECT_A that's in your original post)
<</if>>
2 Likes

Thank you!

I did try to wrap my head around the variables, but could not get them to do as I wanted in this case on my own. And after a couple hours of googling, I was wondering if I was perhaps barking up the wrong tree with the variables and StoryInit.

I will look further into variables and play around with it, as well as testing with your example. Glad to know I wasn’t completely wrong in my assumption. Thank you again!

1 Like

FWIW, (permanent) variables are basically the way to remember things between passages, so if you’re trying to get the game to remember something between passages using variables and it’s not working, the question you should probably be asking is “what is wrong with the way I’m setting/checking these variables?” rather than “what should I be using instead of variables?”

I hope my quick example was helpful, but if you can’t get it working, I can try to write up something more detailed.

2 Likes

What kind of error messages or behavior are you seeing with your use of variables? Maybe it could help diagnose what is going wrong.

The most common error I’ve encountered with what you’re doing is testing for the value of a variable before it has been defined. For example, the following code won’t print anything

<<if $myVariable==true>>
<<print $myVariable>>
<</if>>
<<if $myVariable==false>>
<<print $myVariable>>
<</if>>

Because the $myVariable is neither true nor false, but undefined.

If you set the variable at the top of the passage <<set $myVariable=false>>, it won’t do what you want either, because every time the page loads, the variable will be reset to false (or whatever other value you set it for at the top of the passage).

The best place to define global variables is in a special passage called “StoryInit” which runs once when the story first launches.

After testing some things, the following worked in terms of still showing my content the way I want it to:

<<nobr>>
Initial Text Start, 
<<if $seenObjectA>>
    OBJECT_A
    <<append '#more' t8n>>
        <br>
        DESCRIPTION OF OBJECT_A. FOLLOW-UP TEXT WITH
        <<if $seenActionA>>
            ACTION_A
            <br>
            RESULT OF ACTION_A.
        <<else>>
            <<linkreplace 'ACTION_A'>>
                <<set $seenActionA = true>>
                ACTION_A
                <<append '#more' t8n>>
                    <br>
                    RESULT OF ACTION_A.
                <</append>>
            <</linkreplace>>
        <</if>>
    <</append>>
<<else>>
    <<linkreplace 'OBJECT_A'>>
        <<set $seenObjectA = true>>
        OBJECT_A
        <<append '#more' t8n>>
            <br>
            DESCRIPTION OF OBJECT_A. FOLLOW-UP TEXT WITH
            <<linkreplace 'ACTION_A'>>
                <<set $seenActionA = true>>
                ACTION_A
                <<append '#more' t8n>>
                    <br>
                    RESULT OF ACTION_A.
                <</append>>
            <</linkreplace>>
        <</append>>
    <</linkreplace>>
<</if>>
<<if $seenObjectB>>
    OBJECT_B
    <<append '#more' t8n>>
        <br>
        DESCRIPTION OF OBJECT_B.
    <</append>>
<<else>>
    <<linkreplace 'OBJECT_B'>>
        <<set $seenObjectB = true>>
        OBJECT_B
        <<append '#more' t8n>>
            <br>
            DESCRIPTION OF OBJECT_B.
        <</append>>
    <</linkreplace>>
<</if>>
<<if $seenObjectC>>
    OBJECT_C
    <<append '#more' t8n>>
        <br>
        DESCRIPTION OF OBJECT_C.
    <</append>>
<<else>>
    <<linkreplace 'OBJECT_C'>>
        <<set $seenObjectC = true>>
        OBJECT_C
        <<append '#more' t8n>>
            <br>
            DESCRIPTION OF OBJECT_C.
        <</append>>
    <</linkreplace>>
<</if>>
.
<</nobr>>

@@#more;@@

And the StoryInit like this:

<<set $seenObjectA = false>>
<<set $seenActionA = false>>
<<set $seenObjectB = false>>
<<set $seenObjectC = false>>

So I click OBJECT_A, and the new text “DESCRIPTION OF OBJECT_A. FOLLOW-UP TEXT WITH ACTION_A” appears at the bottom as expected. The issue is when revisiting the passage, I get this error immediately after the text OBJECT_A:
Error: ((append)): no elements matched the selector “#more

Targeting this part:

<<append '#more' t8n>>
    <br>
    DESCRIPTION OF OBJECT_A. FOLLOW-UP TEXT WITH
    <<if $seenActionA>>
        ACTION_A
        <br>
        RESULT OF ACTION_A.
    <<else>>
        <<linkreplace 'ACTION_A'>>
            <<set $seenActionA = true>>
            ACTION_A
            <<append '#more' t8n>>
                <br>
                RESULT OF ACTION_A.
            <</append>>
        <</linkreplace>>
    <</if>>
<</append>>

I figure the reason is that on reloading, there is something about the “@@#more;@@” not being loaded yet? Is there a way to make sure it’s loaded on a revisit, or am I running into a limitation that’s way above my knowledge level? (Or the good old ‘You are doing this very wrong’? ^^’)

I’m unfortunately not sure because I don’t use that macro in that way, but I will say that having text gradually appear after the passage first loads, without a way to make it appear faster, tends to be extremely unpopular and you might want to consider how integral that is to your artistic vision (the side benefit of not doing it being that this append issue would no longer be relevant).

1 Like

What I want is the new text to reveal as the reader explores the space of a singular passage, but to stay revealed in case they move from one passage to another and then back, much to eliminate the frustration of having to reclick it all each time. But I guess I will have to look into another solution for this, restructuring it a bit.

Thank you nonetheless for the help! Wouldn’t be where I’m at without it!

You’re right: SugarCube builds the new passage sort of “offscreen” and then adds the whole thing to the document afterwards. So when you do <<append '#more'>> right away (instead of when the link is clicked) the #more element isn’t findable yet. I think there’s a workaround for that now, but of course I haven’t got the name solidly in my head yet…

…ah, yeah, the DOM macro warning in the docs says to use <<done>>.

So I think for your reload code you should be able to do <<done>><<append '#more'>> ... <</append>><</done>> instead of just append by itself.

1 Like

Sorry, it was the fact that you used <<append>> with a transition outside of a link markup that gave me the impression that you wanted to have the text visibly appear after the passage loads, but I guess it’s more about having it show up in the right place?

1 Like

Back to trying, and this seems to work exactly as I wanted! My bad for not properly reading the documentation I suppose ^^’

Thank you so much!!

2 Likes