0 votes
by (510 points)
I'll try to keep this one as brief as possible. My story has some RPG elements in it including two stats that are the subject of my problem. First is Stamina, second is Vitality (HP, basically). The idea is that they are two separate stats that have their own pools, however, if your stamina is reduced below 0 it will reduce your vitality by 1 instead and keep the stamina at 0.

I know the basic code I can use to make this work, and it's not really the subject of my question. The problem is I am using a PassageHeader passage in my story to constantly display these stats, and the passage header evaluates all of its stuff before the main passage. This means that if I include the code to reduce stamina inside the passage, the header at the top won't update to reflect this change until the player changes the passage, meaning the stats displayed will always be 1 step behind.

A possible solution to this is to include the code inside the link to the next passage, which would be fine except I'm not sure how to use an if statement inside the link. Any advice would be greatly appreciated.

2 Answers

+1 vote
by (510 points)
 
Best answer

This is the second time I have answered my own question mere minutes after asking it. I had an epiphany right afterward. So, the way I see it, the way twine breaks down evaluations it goes in a certain order: Link > Header > Passage. I know this because if I include a stat change in the link, the header will reflect that change, but if the stat change is in the passage being linked to, the header will not reflect the change until the next passage. So for those who also want to do this, all you need to do is make your link look like this:

[[Ow the pain][$losestam to "true"]]

Then in the PassageHeader passage, put this code:

<<if $losestam is "true">><<if $stam is 0>><<set $vital -= 1>><<else>><<set $stam -= 1>><</if>><</if>><<set $losestam to "false">>

at the very top. This not only will change the stats immediately before loading the next passage, it will also reset the variable we used to open the if statement. This way we can still control when the stat is decreased. The only potential downside to this is that it means we can only decrease the stats by 1 at a time, but I'm pretty sure we can fix that with some clever variable shenanigans.

by (159k points)

@JackOLantern

It is better to use the Boolean values of true and false when using a variable to track if something happened or not (eg. On/Off, Yes/No, etc..).

<<if $variableA>>variableA is equal to true<</if>>

<<if not $variableB>>variableB is equal to false<</if>>

... notice the lack of quotation marks, this also works for variables set within Setter Links.

You can then use code like the following when testing if the variable's value is true or false.

<<if $variableA>>variableV is equal to true<</if>>

<<if not $variableA>>variableV is equal to true<</if>>

... notice the lack of the is operator and a comparison value.

Obviously you can use whatever variable names make sense in your story.

by (63.1k points)

You shouldn't quote boolean values. 

Right: 
<<set $var to true>>

Wrong: 
<<set $var to "true">>

The <<if>> macro evaluates the expression it's given into a boolean, so you don't need to test for true, just pass the variable, provided you set it to an actual boolean and not a string. 

Good: 
<<if $var>>

Bad: 
<<if $var is true>>

You can set all the code you put to evaluate the stuff in a PassageReady special passage, which evaluates just before the incoming passage's header will. 

I support the idea of tying incremented and decremented variables in links though, so I'd say the spirit of this solution is spot on. 

by (510 points)
I was not aware that twine accepted true/false without quotes, I figured I had to make them strings in order for it to work. I also wasn't aware of the PassageReady special passage, that actually makes things a bit nicer to deal with. Thanks for pointing out that it exists.
0 votes
by (63.1k points)

I wasn't thinking when I looked at this the other night.  I think it's possible to get a better solution that allows for multiple points to be lost doing something like this instead:

::PassageReady
<<if $loseStam>>
    <<set _stamDiff to $stam - $loseStam>>
    <<set $loseStam to 0>>
    <<if _stamDiff < 0>>
        <<set $stam to 0>>
        <<set $vital += _stamDiff>>
    <<else>>
        <<set $stam to _stamDiff>>
    <</if>>
<</if>>

::in some passage
[[click here|some other passage][$loseStam to 3]]

 

...