Twine macro: <<timedgoto>>, a simple timer

This is inspired by the Timer script used in Panic! by Astrid Bin and Stefano Russo. That script implements a sophisticated timer entity which can count down throughout the entire game, can draw itself in graph form in a canvas element, and can be paused and resumed. However, it requires multiple macros to set it up for each use, and it can be a bit cumbersome if you simply want the game to advance to a new passage after a delay.

I felt like writing a similar macro that would be shorter and more specific. This one, <<timedgoto>>, just automatically (and invisibly) goes to the given passage after the given amount of time has passed. Each use of the macro only functions within the passage that uses it - if you're using Sugarcane or single-passage Jonah and leave the passage by a normal link, it will be disengaged. Feel free to consider this a counterpart to <<timedreplace>>.

version.extensions.timedgotoMacro={major:1,minor:2,revision:0};
macros["goto"]=macros.timedgoto={timer:null,handler:function(a,b,c,d){function cssTimeUnit(s){if(typeof s=="string"){if(s.slice(-2).toLowerCase()=="ms"){return +(s.slice(0,-2))||0
}else{if(s.slice(-1).toLowerCase()=="s"){return +(s.slice(0,-1))*1000||0
}}}throwError(a,s+" isn't a CSS time unit");return 0}var t,d,m,s;
t=c[c.length-1];d=d.fullArgs();m=0;if(b!="goto"){d=d.slice(0,d.lastIndexOf(t));
m=cssTimeUnit(t)}d=eval(Wikifier.parse(d));if(d+""&&state&&state.init){if(macros["goto"].timer){clearTimeout(macros["goto"].timer)
}s=state.history[0].passage.title;macros["goto"].timer=setTimeout(function(){if(state.history[0].passage.title==s){state.display(d,a)
}},m)}}};

New: This now takes CSS time values, which are decimal numbers ending in "s" (for seconds) or "ms" (for milliseconds). You can use fractions of seconds as well as whole seconds.

Usage examples:
* <<timedgoto "underwater" 2.5s >> goes to the "underwater" passage if you stay at the current passage for 2 and 1/2 seconds.
* <<timedgoto $deathpassage 5s >> goes to the passage whose name is in the $deathpassage variable if you stay at the current passage for 5 seconds.
* <<timedgoto $playerType + "pit" 1s >> goes to the $playerType + "pit" passage if you stay at the current passage for 1 second.
* <<goto "Throne">> - This shorter version functions the same as <<timedgoto "Throne" 0s>>.
Notes:
* This uses code parameters (that is, it accepts "strings", $variables, and "various"+$combinations of both, and its parameters are interpreted as Javascript), except that the final parameter (the time value) is separated from the rest and interpreted as a literal parameter.

Version history:

  1. 1-9-2013 - Fixed a bug where it caused problems with the (un-patched) browser Back button code.
  2. 18-4-2013 - Changed time units to CSS units, added "goto" variation.
  3. 5-3-2013 - Initial.

Feel free to report any bugs to @webbedspace.

AttachmentSize
Timer Test.tws9.42 KB

Comments

This is great, thanks. Which

This is great, thanks. Which bits of the macro should I be looking at to be able to display the time values within the passage? I'd like to try and make the urgency more obvious to the player...

This isn't designed to allow

This isn't designed to allow this. I might recommend timedloop instead, combined with some <<if>>s and a <<goto>>.

Ok, thanks - I've written

Ok, thanks - I've written the passages to try and get the message across, but I'll experiment with your recommendation.

Been trying to use timedgoto

Been trying to use timedgoto for a method of control of where the user is traversed to, but can't seem to make the command work correctly when used multiple times within a passage....

<<if $race eq "orc">><<timedgoto "fall_feethard" 0s>><<endif>>
<<if $race eq "undead">><<timedgoto "fall_feethard" 0s>><<endif>>
<<if $race eq "dwarf">><<timedgoto "fall_feethard" 0s>><<endif>>
<<if $race eq "dragon" && $dragonform eq 1>><<timedgoto "dragon_fail" 0s>><<endif>>
<<if $race eq "dragon" && $dragonform eq -1>><<timedgoto "fall_feethard" 0s>><<endif>>
<<timedgoto "fall_feetsoft" 0s>>

the above is what I have right now, It seemed to work on some passages, but this one is one that "fall_feetsoft" always overrides since it's the last code at the bottom of the passage.. any ideas how I can fix this? :) [i know, it could of been simplified, but I was breaking it down to what's causing it, if it was the nested if else if else end ifs or if it was just the if then endifs... either way didn't work...

Which brings up another question, if the last timedgoto "fall_feetsoft" is overriding the above timedgotos, anyway to break a passage so it doesn't continue? kinda like a <<break>> command or something?

hmm.. just tested and i

hmm.. just tested and i fixed it...

<<set $k = 1>>
<<if $k eq 1>><<timedgoto "passage1" 0s>><<endiff>>
<<set $k += 1>>
<<if $k eq 2>><<timedgoto "passage2" 0s>><<endif>>
<<timedgoto "passage3" 0s>>

because of the way the code is, passage3 will always go first. It's based on LILO (last in, last out), a current fix is to default the timedgoto before checking... but does not help with if then else clauses... maybe it can be fixed with what I was thinking of with a <<break>>

<<timedgoto "passage3" 0s>>
<<set $k = 1>>
<<if $k eq 1>><<timedgoto "passage1" 0s>><<endiff>>
<<set $k += 1>>
<<if $k eq 2>><<timedgoto "passage2" 0s>><<endif>>