Fictional Calendar System

I'm making a project that includes the passing of days, months and years with some events happening in certain days. However, these do not follow our 365 days-year with 12 months. It would be a much simplified system (probably something like Stardew Valley that has 4 months with 28 days each).

In my game, you would start a day in the morning. You would be able to do one or two main action (such as go on a date with X character) before it becomes dark. The only difference would be that you can't do anything when its dark other than sleep (which would progress to the next day).

Because I imagine players would play more than a few years, I'm unsure how to approach this the date system.


I do think I know how to implement the day-night part. It would probably be an attribute like "day.activity = 2" and doing a specific action would do day,activity = day.activity -1.
A different script would set that if day.activity = 0 then its nightime. Then during the sleep action, I could set day.activity = 2 again.

I think I would probably need to check pixies library on weather to show how the places react to being night/day.

But how would I make it to tracking the days/month/year + sleeping advacing the day?


But how would I make it to tracking the days/month/year + sleeping advacing the day?

For things like this, I would always recommend an epoch date. Basically, a variable holding the number of days since a fixed start point (usually the start of the year). You could put this number in an integer attribute, and then just put something like game.date = game.date + 1 in your "sleep" script.

If you use game.date, you could create a script attribute game.changeddate and it will run automatically whenever the date changes; which makes it so much easier to handle other stuff.
If you have the same number of days in every week, you could make it something like:

startyear = 1997
days_per_month = 29
months = Split("January;March;Tricember;Grune;Spoon")
weekdays = Split ("Mon;Tue;Wed;Fri;Sat")

this.year = startyear + (this.date % (days_per_month * ListCount (months)))
this.month_number = (this.date / days_per_month) % ListCount (months)
this.month = ListItem (months, this.month_number)
this.day_of_month = this.date & days_per_month + 1
switch (this.day_of_month) {
  case (1,21) {
    this.day_ordinal = this.day_of_month + "st"
  }
  case (2,22) {
    this.day_ordinal = this.day_of_month + "nd"
  }
  case (3,23) {
    this.day_ordinal = this.day_of_month + "rd"
  }
  default {
    this.day_ordinal = this.day_of_month + "th"
  }
}
this.weekday_number = this.date % ListCount (weekdays)
this.weekday = ListItem (weekdays, this.weekday_number)
this.fulldate = game.weekday + "day, " + game.month + " " + game.date_ordinal + ", " + game.year

This gives you a whole bunch of variables you can use to display different parts of the date. For example, you could include {game.fulldate} in some text you're printing and it could show "Friday, June 18th, 2004"

If you have different numbers of days in each month, it gets a little more complex; but it shouldn't be too hard.


First of all, thanks for the quick reply.

Now walk with me because I'm more writer than coder.
1- I assume I can just paste this at like, the beginning of the code?

2- If I change the name of the days or add extra week days (example from Friday to Fireday; or adding any other day) would this break anything?

3- How would I check things for events? For example:
I know how to check if it is the 28th of Spoon. Would I check this in the script of changing dates to activate events?


1- I assume I can just paste this at like, the beginning of the code?

You would need to create an attribute named changeddate on the same object that has the integer date attribute. (Or if you call it something different, just add "changed" to the beginning of the attribute name)

2- If I change the name of the days or add extra week days (example from Friday to Fireday; or adding any other day) would this break anything?

It should work. I put all the stuff you'd be likely to change at the beginning of the script, to make it easier.

3- How would I check things for events?

If you want to check the date, you can examine any of the variables in your code. For example, if you have an NPC who reacts differently on his birthday, you could write something like:

if (game.month_number = 4 and game.day_of_month = 28) {
  msg ("The old man grins and offers you a slice of birthday cake.")
}
else {
  msg ("The old man glares at you sullenly.")
}

You could include checks like that anywhere.
If you want specific events to happen when the player wakes up on a certain day, you could check for that date at the end of the changeddate script; or you could do it as part of your sleep script after changing the date. If you have a lot of these, I'd recommend putting them together in a switch statement:

switch (game.year + "-" + game.month + "-" + game.day_of_month) {
  case ("1998-January-7") {
    // do something that should happen on that day
  }
  case ("1999-March-21") {
    // do something that should happen on that day
  }
}

Alternatively, if there's really a lot of them, you could use an object. For example, you could add this to the end of the changeddate script:

shortdate = "event_" + this.year + "_" + this.month + "_" + this.day_of_month
if (HasScript (this, shortdate)) {
  do (this, shortdate)
}

Then, you can give the object script attributes named something like event_2004_January_3, and those events will automatically be run on the right day. This might be faster, if there's a lot of them.

Alternatively, thinking about it even more, it wouldn't be too hard to make something like a cron system, so that you can make an event trigger every friday the 13th, or every 5th day in January, or something like that. But I suspect that would be overkill, unless there's something you would like a system like that for.


Looks like something went awry. I tried to do.

" switch (result) {
case ("Yes.") {
msg ("You sleep")
wait {
do (game, "changeddate")
msg ("It is" + game.date + ".")
}
}
"
But the game crashed.

For reference, game.date is 1
and
game.changeddate is a script that says: game.date = game.date + 1


Nevermind. Seems to be working now that I changed the names and the object (it's in a random room named days instead of under game)


Oof. Triple post in a row. Anyway, I tried pasting the initial code you posted on my start script. When running the game, it said
Error running script: Error compiling expression 'startyear + (this.date % (days_per_month * ListCount (months)))': ArithmeticElement: Operation 'Mod' is not defined for types 'Object' and 'Int32'


I tried pasting the initial code you posted on my start script.

No. The script I posted is the changeddate script.

changeddate is called automatically whenever the date attribute changes, so there is no need to use do.

Your sleep script would look like:

Ask ("Ready to sleep?") {
  if (result) {
    msg ("You sleep")
    wait {
      game.date = game.date + 1
      msg ("It is" + game.fulldate + ".")
    }
  }
}

Error running script: Error compiling expression 'startyear + (this.date % (days_per_month * ListCount (months)))': ArithmeticElement: Operation 'Mod' is not defined for types 'Object' and 'Int32'

This is caused by the numeric date attribute either not being named date, or not being on the same object as the changeddate script I gave you.


(Also, I edited the previous code to fix a small error… The year no longer starts on January 0th. I'm typing this on my phone, so errors are always possible)


Could you perhaps utilize the "game" object's Turn Script to increment a global time/date/year variable based on the actions of the player taking 5 minutes in-game time for every action such as moving from room to room, performing any action in said room that causes a "turn" to increment?

I was thinking of this sort of system for a game where you have a time limit to complete it, a path of most efficiency to beat it with varying difficult settings to give extra overall time until gameover if they didn't finish before a specific number of actions (in-game time) taken.


Could you perhaps utilize the "game" object's Turn Script to increment a global time/date/year variable based on the actions of the player taking 5 minutes in-game time for every action such as moving from room to room, performing any action in said room that causes a "turn" to increment?

Yes, you could.

If you wanted to adapt this script to work with something like that, you would have the numeric datetime be the number of minutes from the start date, and have a turnscript to increment it.

To do something like that, your change script (game.changeddatetime) would look more like:

this.time_minutes = this.datetime % 60
this.time_hours = (this.datetime / 60 - 1) % 12 + 1
this.pm = (this.datetime / 60 / 12) % 2 = 1
if (this.pm) {
  this.string_time = this.hours + ":" + this.minutes + " PM"
}
else {
  this.string_time = this.hours + ":" + this.minutes + " AM"
}
this.date = this.datetime / 60 / 24

and then you could carry on with the rest of the code to calculate the date based on the time (or even have a separate changeddate script)


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums