0 votes
by (130 points)
I have been banging my head against the wall for a few days now and I haven't been able to figure out how to setup gametime in game, or how to change game time periodically. I found 2 macros in other player's stories, but I still can't figure out how to manipulate time. Below is the macro which I believe will work for what I'm requiring it to do.

If you have a better one, I'm all ears. If you can also post how to use your macro in twine, that would be most helpful. Thank you.

I'd like to be able to add 5 minutes here and there, or a few hours, and then also to reset time to a new day, with wakeup at 7AM.

I've seen some systems used in game that work on a 7 day time system, Monday to Sunday, but that's not going to work for me, since I'd like to have date specific events. So I really need a dynamic system. I don't want to use system time because my game is set in a specific period of time.

 

This is a macro I found to use in the JS part. I am not sure how to call this macro using Twine in Sugarcube 2.18.

 

macros.changeDate = {
   "handler" : function(place, macroname, params, parser)
    {setup.changeDate = function(date, interval, units)
    {
    var d = new Date(date); // Don't change original date.

    switch(interval.toLowerCase()) {
      case 'years':
        d.setFullYear(d.getFullYear() + units);
        break;
      case 'quarters':
        d.setMonth(d.getMonth() + 3 * units);
        break;
      case 'months':
        d.setMonth(d.getMonth() + units);
        break;
      case 'weeks':
        d.setDate(d.getDate() + 7 * units);
        break;
      case 'days':
        d.setDate(d.getDate() + units);
        break;
      case 'hours':
        d.setTime(d.getTime() + units * 3600000);
        break;
      case 'minutes':
        d.setTime(d.getTime() + units * 60000);
        break;
      case 'seconds':
        d.setTime(d.getTime() + units * 1000);
        break;
      default:
        break;
    }

    return d
  }
}
}

1 Answer

+1 vote
by (159k points)

There are a number of issues with your example:

1. It was written for the SugarCube 1.x series, the 2.x series uses a different method for creating custom macros which is described within the Macro API documentation, in particular the Macro.add() function.

2. The example is trying to do two things at the same time:
a. Create a custom function named changeDate on the special setup object that SugarCube supplies to Authors.
b. Create custom macro also named changeDate which uses the new custom function in point A.

3. The example includes no error catching code for checking if the parameters (if any) past actually exist or are of the correct data types. eg, a Date, a String, and an integer.

4. The example doesn't explain what the custom macro is meant to do with the new date created by the custom function. eg. Should it display the new Date in the page, and if so what format should it display it in?

The following prototype can be used as a starting point, it defines both the custom function and the custom macro. 

/* Create a new Date object based on an original.

	date - the existing Date object to base new object on.
	interval - the time interval type of the unit.
	units - the number of time interval usits to increase the original date by.
*/
setup.changeDate = function(date, interval, units) {
	// Don't change original date.	
	var d = new Date(date);
	switch(interval.toLowerCase()) {
		case 'years':
			d.setFullYear(d.getFullYear() + units);
			break;
		case 'quarters':
			d.setMonth(d.getMonth() + 3 * units);
			break;
		case 'months':
			d.setMonth(d.getMonth() + units);
			break;
		case 'weeks':
			d.setDate(d.getDate() + 7 * units);
			break;
		case 'days':
			d.setDate(d.getDate() + units);
			break;
		case 'hours':
			d.setTime(d.getTime() + units * 3600000);
			break;
		case 'minutes':
			d.setTime(d.getTime() + units * 60000);
			break;
		case 'seconds':
			d.setTime(d.getTime() + units * 1000);
			break;
		default:
			break;
	}
	return d
};

Macro.add("changedate", {
	skipArgs: false,
	handler: function() {
		// Check that we have enough parameters, there should be 3.
		if (this.args.length < 3) {
			return this.error('not enough paramaters passed');
		}

		// Check that the first parameter is a Date.
		// NOTE: This isn't as simple as it sounds.
		var date = this.args[0];
		if (!(date instanceof Date && !isNaN(date.valueOf()))) {
			return this.error('first paramater is not a valid Date');
		}

		// Check that the second parameter is a String.
		// NOTE: The custom function handles if the value isn't correct.
		var interval = this.args[1];
		if (typeof "foo" !== "string") {
			return this.error('second paramater is not a valid String');
		}
		
		// Check if the third parameter is a interger.
		var units = parseInt(this.args[2], 10);
		if (isNaN(units)) {
			return this.error('third paramater is not a valid integer');
		}

		// Use the custom function to create a new Date.
		var result = setup.changeDate(date, interval, units);
		
		// Display the new Date on the the page.
		new Wikifier(this.output, result);
	}
});

... and you could use TwineScript like the following to call the new custom macro.

<<set _date to new Date()>> /% Current date and time for current locale. %/

<<changedate _date "years" 5>>

 

...