0 votes
by (210 points)

Using twine 2.2.1 and SugarCube 2.27

All I want is to have a 24 hour clock that goes down and if you don't finish the game by the time 24 hours has passed you lose. Each passage takes away minutes from your timer and when the minutes hit 60 I want the 24 to go down by 1. I've set it up so when minutes is greater than 60 the variable for minutes goes down by 60. So something that took 70 minutes would cause the hours to go down by 1 and minutes would go to 10. I thought it would be easy but I can't seem to get it to work

 

<<set $time = 24>>
<<set $minute = 0>>
<<if ($minute gte 60)>><<set $minute to $minute-60>>
<</if>>
<<if ($minute gte 60)>><<set $time to $time-1>>
<</if>>

 

And then to practice I made a passage like this

 

<<set $minute to $minute+70>>

 

And I have a StoryCaption passage like this 

Time: $time
Minute: $minute

Except the minutes just go to 70, not 10 and the hours never go down from 24

Could you please help? I've almost finished story and this is the last thing I need to do to complete it. Thank you

I think there is something wrong with my ifstatements

 

1 Answer

0 votes
by (44.7k points)

The first problem is that you need to check the value of $minute every time you change it, the second problem is that, because you have two <<if>> statements, you're checking the value of $minute again after you've just changed the value of $minute, so the second <<if>> probably won't get triggered.  The correct way to do what you're asking for would be like this:

<<set $minute to $minute+70>>
<<if ($minute gte 60)>>
	<<set $time to $time-1>>
	<<set $minute to $minute-60>>
<</if>>

However, if you added 130 minutes, then that would only remove 60 of it.  That could be fixed like this:

<<set $minute to $minute+70>>
<<for $minute gte 60>>
	<<set $time to $time-1>>
	<<set $minute to $minute-60>>
<</for>>

The <<for>> macro will keep looping until $minute is less than 60.

That said, it's a bit weird that you're adding to minutes and subtracting from time.  You might make things a bit simpler by only subtracting minutes and using a JavaScript Date object, like this:

<<set $Time = new Date('1/3/1970 00:00:00')>>
Time remaining: 24:00:00
<<set $Time = new Date($Time.setMinutes($Time.getMinutes() - 15))>>(15 minutes later...)
Time remaining: <<= $Time.toLocaleString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" } )>>

This way you just have to subtract the minutes, like how it's done on the third line above, and the Date object will handle the rest.  Then, when $Time.getDate() == 1 you know that more than 24 hours have passed.  (Note: <<= "xyz">> is just a shorter way of doing <<print "xyz">>.)

If you want to show "24:00:00" instead of "00:00:00" you'll have to fake it like I did above.

Then, to make things easier, you can turn those commonly used lines into widgets.  Just create a passage, give it "widget" and "nobr" tags, and put this in it:

<<widget "PassTime">>
	<<set $Time = new Date($Time.setMinutes($Time.getMinutes() - $args[0]))>>
	<<if $Time.getDate() == 1>>
		<<goto "TimeOver">>
	<</if>>
<</widget>>

<<widget "ShowTime">>
	Time remaining: <<= $Time.toLocaleString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" } )>>
<</widget>>

Now you can make 15 minutes pass and show the time like this:

<<PassTime 15>>(15 minutes later...)
<<ShowTime>>

That will also send it to the "TimeOver" passage if time runs out using the <<goto>> macro.  (NOTE: Other code called in the current passage will still get executed after the <<goto>> is called and before going to the passage you told it to go to, so use <<goto>> macros with caution.)

Hope that helps!  :-)

by (210 points)
Thanks for the reply!

To be honest I don't need to do it my way, I just want the game to be over after 24 hours have passed. Not literal 24 hours but as you go to certain passages a certain amount of minutes are taken off. That way if a player goes to the same place they are punished by losing time.

I also want them to see how much time they have left. So you start at 24 hours and you start the game and make your way to a bus stop. I want to time to go to 23:55. You then have two locations you can go to. One takes 20 minutes the other takes 30 minutes. When you click either option the time will go down to 23:25 and 23:35 respectively.

Because time is in units of 60 it's really hard to just say $time - 0.05 because you'd you would get 23.95 not 23.55. That's why I had the minutes getting to 60 and then the hour going down.

I want to have the if statement somewhere that applies to every single passage so I don't have to copy and paste that code into every passage. I can get my way to work using your first suggestion but I have to post it into every single passage. I'll play around with your second idea for a bit. I'm new to twine so it'll take me a while to get my head around, I'll post further questions about it if I need to :)

 

Thanks
by (210 points)
Can you explain where to put the above scripts into what passages or if I have to put some of it into the  edit story javascript section. I have no idea how to get your idea to work because as of right now I can't. I just cut and paste your code into a new sugarcube story with no other passages and it didn't work because I'm sure I'm doing something wrong. If you could explain it to me in a simple way I'd appreciate that a lot
by (44.7k points)
edited by

In the passage where the timer should first appear, you can initialize it like this:

<<set $Time = new Date('1/3/1970 00:00:00')>>

You can name the passage for the widgets whatever you want.  I usually call it "Global Widgets", but really all that's important is that it has the "widget" and "nobr" tags (click the "+Tag" button at the top of the passage to add a tag).  Then put this code in it:

<<widget "PassTime">>
	<<set $Time = new Date($Time.setMinutes($Time.getMinutes() - $args[0]))>>
	<<if $Time.getDate() == 1>>
		<<goto "TimeOver">>
	<</if>>
<</widget>>

<<widget "ShowTime">>
	<<if def $Time>>
		<<if $Time.getDate() == 1>>
			Time remaining: 00:00:00
		<<elseif $Time.getDate() == 3>>
			Time remaining: 24:00:00
		<<else>>
			Time remaining: <<= $Time.toLocaleString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" } )>>
		<</if>>
	<</if>>
<</widget>>

You could then display the time remaining in the UI bar by putting the following in the "StoryCaption" passage:

<<ShowTime>>

That will cause the time remaining to be displayed and updated every time a passage changes.

Then, in any passage where time passes, just do:

<<PassTime 15>>

except replace "15" with however many minutes have passed in that passage.

Then just make a "TimeOver" passage for when the time runs out.

That should do it!

...