(MadExile's Gregorian date & time widgets) How might I advance this game clock to a certain day and time?

0 votes
asked Dec 7 by Charlie (4,530 points)

I just incorporated TheMadExile's excellent Gregorian date & time widgets, from this thread, into my game.  It works brilliantly and is very simple to use in game.

/*
	Date & Time Widget Setup
*/
<<set
	window.GameDays to [
		"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"
	];
	window.GameMonths to [
		"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
		"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
	];

	/*
		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(2019, 3, 5, 7, 2); /* 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>>

However, I'd really like to be able to advance the time to the next instance of a certain day.  For example, say Chess Club happens every Wednesday at 5PM.  If the player visits Chess Club, I'd like $gameDate to advance to 5PM on the next Wednesday.  I can't quite picture how to do this; can anyone help?

 

1 Answer

+1 vote
answered Dec 7 by greyelf (43,790 points)
selected Dec 7 by Charlie
 
Best answer

note: Based on the wording of your question I am assuming that the current Day of the Week of the Javascript Date object stored in the $gameDate story variable is Wednesday.

The solution to your issue can be broken down into two parts:

1. How to add 7 days to the existing Date object value.

<<adddays 7>>

2. How to change the current Hour of the Day of the existing Date object value to 5PM, which can be done using the Date object's setHours() function. (5PM is the 17th hour of the day)

<<set $gameDate.setHours(17)>>

 

commented Dec 7 by Charlie (4,530 points)

Thanks, Elf!  That wasn't quite what I meant to ask – I wanted to know how to advance to Wednesday dynamically, from any day of the week.

However, reading the way you broke down your answer made me realise I could do this with a widget and some <<if>> statements.

/* Advance to a certain day */
<<widget "cuNextMonday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 1>>\
<<elseif _today == 1>>\
<<adddays 7>>\
<<elseif _today == 2>>\
<<adddays 6>>\
<<elseif _today == 3>>\
<<adddays 5>>\
<<elseif _today == 4>>\
<<adddays 4>>\
<<elseif _today == 5>>\
<<adddays 3>>\
<<elseif _today == 6>>\
<<adddays 2>>\
<</if>>\
<</widget>>

<<widget "cuNextTuesday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 2>>\
<<elseif _today == 1>>\
<<adddays 1>>\
<<elseif _today == 2>>\
<<adddays 7>>\
<<elseif _today == 3>>\
<<adddays 6>>\
<<elseif _today == 4>>\
<<adddays 5>>\
<<elseif _today == 5>>\
<<adddays 4>>\
<<elseif _today == 6>>\
<<adddays 3>>\
<</if>>\
<</widget>>

<<widget "cuNextWednesday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 3>>\
<<elseif _today == 1>>\
<<adddays 2>>\
<<elseif _today == 2>>\
<<adddays 1>>\
<<elseif _today == 3>>\
<<adddays 7>>\
<<elseif _today == 4>>\
<<adddays 6>>\
<<elseif _today == 5>>\
<<adddays 5>>\
<<elseif _today == 6>>\
<<adddays 4>>\
<</if>>\
<</widget>>

<<widget "cuNextThursday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 4>>\
<<elseif _today == 1>>\
<<adddays 3>>\
<<elseif _today == 2>>\
<<adddays 2>>\
<<elseif _today == 3>>\
<<adddays 1>>\
<<elseif _today == 4>>\
<<adddays 7>>\
<<elseif _today == 5>>\
<<adddays 6>>\
<<elseif _today == 6>>\
<<adddays 5>>\
<</if>>\
<</widget>>

<<widget "cuNextFriday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 5>>\
<<elseif _today == 1>>\
<<adddays 4>>\
<<elseif _today == 2>>\
<<adddays 3>>\
<<elseif _today == 3>>\
<<adddays 2>>\
<<elseif _today == 4>>\
<<adddays 1>>\
<<elseif _today == 5>>\
<<adddays 7>>\
<<elseif _today == 6>>\
<<adddays 6>>\
<</if>>\
<</widget>>

<<widget "cuNextSaturday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 6>>\
<<elseif _today == 1>>\
<<adddays 5>>\
<<elseif _today == 2>>\
<<adddays 4>>\
<<elseif _today == 3>>\
<<adddays 3>>\
<<elseif _today == 4>>\
<<adddays 2>>\
<<elseif _today == 5>>\
<<adddays 1>>\
<<elseif _today == 6>>\
<<adddays 7>>\
<</if>>\
<</widget>>

<<widget "cuNextSunday">>\
<<set _today to $gameDate.getDay()>>\
<<if _today == 0>>\
<<adddays 7>>\
<<elseif _today == 1>>\
<<adddays 6>>\
<<elseif _today == 2>>\
<<adddays 5>>\
<<elseif _today == 3>>\
<<adddays 4>>\
<<elseif _today == 4>>\
<<adddays 3>>\
<<elseif _today == 5>>\
<<adddays 2>>\
<<elseif _today == 6>>\
<<adddays 1>>\
<</if>>\
<</widget>>

Now, using the widget <<cuNextWednesday>> will move the game calendar forward to the next Wednesday.

Thanks, Elf, you made me realise how I could do this.  :-)

 
commented Dec 7 by greyelf (43,790 points)

If you want a single widget that changes the DoW of the current Date forward to the next instance of a particular DoW then try the following.

/* Change DoW to the next instances of a particular DoW. */
<<widget "changeDoW">>\
	<<silently>>
		<<set _day to $args[0].toUpperCase()>>
		<<if GameDays.contains(_day)>>
			<<set _DoW to $gameDate.getDay()>>
			<<set _newDoW to GameDays.indexOf($args[0].toUpperCase())>>
			<<set _offset to _newDoW - _DoW>>
			<<if _newDoW <= _DoW>>
				<<set _offset += 7>>
			<</if>>
			<<adddays _offset>>
		<</if>>
	<</silently>>\
<</widget>>

The above changedow macro assumes you will pass it one of the Day Names defined in the window.GameDays variable, it then calculates the offset (number of days) between the current Day and the next Day with the required name.

The following example demonstrates the usage of the new macro, for simplicity sake the example resets the original date between calls to the new macro.

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
Original date: <<datetime>>

<<changedow "MONDAY">>\
next Monday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "TUESDAY">>\
next Tuesday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "WEDNESDAY">>\
next Wednesday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "THURSDAY">>\
next Thursday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "FRIDAY">>\
next Friday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "SATURDAY">>\
next Saturday: <<datetime>>

<<set $gameDate to new Date(2017, 11, 6, 17, 0, 0)>>\
<<changedow "SUNDAY">>\
next Sunday: <<datetime>>

 

commented Dec 7 by Charlie (4,530 points)

Wow, what took me 133 lines of code, you did in 15.  :-)  Thanks, Greyelf, that's so much more elegant than my solution.

 
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.
...