+3 votes
by (390 points)
Hello all, i'm completely new here, and twine in general.

The last two weeks i've been watching lots of tutorials on YT, and a whole bunch of threads explaining how to do certain things.

I have an idea to create a relatively big, open world management game, i already know how to use some macros, but right now i can't continue without having a decent, simple, easy to use date and calendar system that counts time (only hours and minutes).

The story format i'm using is Sugarcube 2.21.0, on Twine 2.2.1.

I never dabbled in JS before, or any kind of coding in general, hence my ignorance.

My other problem is that most of the threads i find about how to make a clock system, are either for twine 1 or earlier versions of sugarcube, and not applicable to my case.

What i'm looking for essentially is a timer that counts time as a normal clock would, but only counts time through entering passages, for example, a sleep passage makes time go by 8hours, another makes time pass by 1minute, and so forth. And if it could count days and months as well, that'd be perfect.

I know this question gets asked a lot, and i don't want to add to the pile, but i'm tired of banging my head against the wall.

Can someone help me, please?

3 Answers

+2 votes
by (8.6k points)
selected by
 
Best answer

In the simplest case, for Earth dates in the Gregorian calendar, just use the standard JavaScript Date object. Set some value to it at the beginning of your game (in StoryInit or your starting passage) and you can always refer to it later to add or change the "current" time.

<<set $now = new Date("2238-07-05T10:30:00Z")>>

The Date object, for all its faults, has the neat ability that its numbers "overflow". For example, if you'd add 20 hours to this particular date and print it, it would be the morning of the 6th July, not the 30th hour of the 5th July.

<<run $now.setHours($now.getHours() + 20)>>
<<= $now.toGMTString()>>
/* prints "Fri, 06 Jul 2238 06:30:00 GMT" */

You can add some macros around this, in particular for the display, and you can also look at the moment.js module if you want even better control over dates and times. But to know what exactly to suggest here we'd need way more specifics about your requirements for manipulating and displaying the date and time.

For an example of a bit of possible "chrome" to polish your game with, take a look at the dyClockJS module.

by (390 points)
Thanks a lot for the detailed explanation.

You cleared things a bit more for me, but now i see my greatest obstacle will be JavaScript, as everytime i see javascripts i get a small seizure, how big and complex they are, specially for me, one who never programed anything in my life.

This is all very new, and very different from anything i've done, but i'll get there in time.

Thanks a lot again.

Any kind of help is appreciated and welcome! =)
+2 votes
by (44.7k points)
by (390 points)
Thank you for your reply, but seeing as i'm still watching tutorials and learning to control Sugarcube, all of these leave me with more answers than questions. I'll learn eventually though, at least i have three links to some examples i can apply in the future.

 

Thank you again. =)
+3 votes
by (8.9k points)
  • Create a new passage called "Game Clock".
  • Add a widget tag to this passage.
  • Paste Mad Exile's Gregorian Date & Time Widgets into this passage:
/*
	Date & Time Widget Setup
*/
<<set
	window.GameDays to [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
	];
	window.GameMonths to [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	];

	/*
		Below we have to use the multi-parameter version of the Date
		constructor, rather than the date string version, because the
		date string version treats a missing timezone offset as UTC.
		While there are ways to determine players' timezone offsets,
		so they could be added to a date string, it's more convenient
		simply to use the multi-parameter constructor.

		The point of this is so that you can simply initialize the game
		world clock to whatever date and time you wish without having to
		worry about the players' timezone offsets, while still ensuring
		that they all see the same game world dates and times.
	*/
	/* params: year , month(0-based) , day , hour(24H) , minute [, second ] */
	$gameDate to new Date(2015, 2, 17, 3, 24); /* e.g. Mar 17, 2015 03:24 */
>>


/*
	Date & Time Advancement Widget Definitions
*/
/* Adds the specified number of minutes. */
<<widget "addmins">>\
<<run $gameDate.setMinutes($gameDate.getMinutes() + $args[0])>>\
<</widget>>

/* Adds the specified number of hours. */
<<widget "addhours">>\
<<run $gameDate.setHours($gameDate.getHours() + $args[0])>>\
<</widget>>

/* Adds the specified number of days. */
<<widget "adddays">>\
<<run $gameDate.setHours($gameDate.getHours() + $args[0] * 24)>>\
<</widget>>


/*
	Date & Time Printing Widget Definitions
*/
/* Prints the current date ("{weekday} {month} {day}, {year}"). */
<<widget "date">>\
<<print String.format("{0} {1} {2}, {3}",
	GameDays[$gameDate.getDay()],
	GameMonths[$gameDate.getMonth()],
	$gameDate.getDate(),
	$gameDate.getFullYear()
)>>\
<</widget>>

/* Prints the current time (12H). */
<<widget "time12hr">>\
<<if $gameDate.getHours() eq 0>>\
12\
<<elseif $gameDate.getHours() gt 12>>\
<<print $gameDate.getHours() - 12>>\
<<else>>\
<<print $gameDate.getHours()>>\
<</if>>:\
<<if $gameDate.getMinutes() lt 10>>0<</if>><<print $gameDate.getMinutes()>> \
<<if $gameDate.getHours() gte 12>>PM<<else>>AM<</if>>\
<</widget>>

/* Prints the current time (24H). */
<<widget "time24hr">>\
<<if $gameDate.getHours() lt 10>>0<</if>><<print $gameDate.getHours()>>:\
<<if $gameDate.getMinutes() lt 10>>0<</if>><<print $gameDate.getMinutes()>>\
<</widget>>

/* Prints the current date and time (12H). */
<<widget "datetime">><<date>> <<time12hr>> (<<time24hr>>)<</widget>>
  • To advance the time 5 minutes in a passage, type <<addmins 5>> somewhere into the passage.
  • To advance 7 hours, <<addhours 7>>
  • To advance 30 days, <<adddays 30>>
by (170 points)
I'm not sure exactly what part of the code I had was wrong- I recopied the widget that was posted above and replaced what I had, and it's working now.
by (120 points)
Well I did want this on the sidebar and but I didn't want to ring in months into this

Plus I want to make a timer, being able to detect the passage of days when activated

But I didn't see any way to add it to the sidebar

Just how to implement it
by (170 points)

I'm not sure I'm understanding you right but- to add something to the side bar, create a passage named StoryCaption

There, you can put all the info you want that's not in a button, like so-

 

Time: <<time12hr>>


Name: $name

etc.

by (120 points)
edited by
Yeah, confuses me too now that I read it back

I wanted to add the day count and time to the sidebar, which you (kinda) clarified

But I want to add a day timer, when it is triggered to begin, after so many days something happens

This 'should' be more understandable

And with the top answer, copy pasta in a Game Clock passage, I don't know how to display it in the sidebar as "setMinutes" and "setHours" is undefined
by (170 points)

I wasn't sure myself how to work it with the widget above. I have a bit of coding where, you go to bed, and it adds a day, outside of the widget.

I have a $days variable set up in storyinit, initially set to 1.

So, a basic set up I have is- 

::Home::

<<days>>
Blah blah.


<<button "Go to bed" "Home">>
<<set $gameDate.setHours(7)>>
<<set $gameDate.setMinutes(0)>>
<<set $days += 1>>
<</button>>

<<button "Leave" "Somewhere Else">>
<</button>>

(Hope this helps with the setminutes issue. The 7 sets it to 7 am, the 0 sets it to 00, so 7:00 am, to show it, you would just have it say <<time12hr>>)

Where <<days>> is a widget I set up, as below-

::days::

<<widget "days">>
	<<if $days == 2>>
		<<set $testtext to "It's day 2">>
	<<elseif $days == 3>>
		<<set $testtext to "It's day 3">>
	<</if>>
	
<</widget>>

(The $texttext is just something to help me see that it's actually being triggered). You can play around a bit if you were more interested in it being weekday (if $days == "Sunday") or something, rather than just 1 or 2. But, whatever it is, you would just put $days in the StoryCaption to show what you want for it.

Let me know if this isn't quite what you're looking for still!

...