Having trouble with my Stardew Valley based time system

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Thallium

So everything in this time system works aside from my AM → PM function. This happens within my advanceHour() function. For some reason after 12AM at night it switches to 1PM rather than 1AM.

My time system should be going from 6AM-12PM-2AM. I plan on sharing the complete project once finished so please feel free to make any recommendations :slight_smile: Thank you!

var currentHour : int = 6
var currentMinute : int = 0
var currentPeriod : String = "AM"

var weekdays := ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
var currentDay : int = 0

@onready var timeLabel = $TimeLabel
var minuteTimer := Timer.new()

func _ready():
	minuteTimer.wait_time = 60.0 / 60  # 7 seconds per 10 minutes // 8.5
	minuteTimer.timeout.connect(_on_timer_timeout)
	add_child(minuteTimer)
	minuteTimer.start()

func _on_timer_timeout():
	advanceTime()
	updateUITime()

func advanceTime():
	currentMinute += 10
	if currentMinute >= 60:
		currentMinute = 0
		advanceHour()

func advanceHour():
	var isAM : bool = true
	var dayChange : bool = false
	currentHour += 1
	
	## MORNING 6AM -> 12PM ##
	if currentHour >= 12:
		if isAM == true && dayChange == false:
			isAM = false
			currentPeriod = "PM"
	
	## MORNING 12PM -> 1PM ##
	if currentHour >= 13:
		if isAM == false && dayChange == false:
			currentPeriod = "PM"
			currentHour = 1 
	
	## NIGHT 1PM -> 12AM ##
	if currentHour >= 12:
		if isAM == false && dayChange == false:
			currentPeriod = "AM"
			dayChange = true
	
	## NIGHT 12AM -> 1AM ##
	if  currentHour >= 13:
		if isAM == true && dayChange == true:
			currentPeriod = "AM"
			currentHour = 1
	
	## NIGHT 1AM -> 2AM ##
	if currentHour == 2:
		if isAM == true && dayChange == true:
			currentPeriod = "AM"
			dayChange = false
			advanceDay()

func advanceDay():
	currentHour = 6
	currentMinute = 0
	currentPeriod = "AM"
	currentDay = (currentDay + 1) % 7

func updateUITime():
	var timeString = str(currentHour).pad_zeros(2) + ":" + str(currentMinute).pad_zeros(2) + " " + currentPeriod
	var weekdayString = weekdays[currentDay]
	timeLabel.text = weekdayString + ", " + timeString
	print_debug(weekdayString + ", " + timeString)

For some reason after 12AM at night it switches to 1PM rather than 1AM.

Have you stepped through that code a line at a time with the debugger? The issue should be easy to spot like that. However, by eye, it seems that “hour 13” will fall through a number of those if checks in advanceHour() - probably unintentionally (?).

I also find it odd that each call to advanceHour() starts by assuming it’s currently AM and there is no need for a day change. I’d expect that logic to be driven directly by the timekeeping system and not “reset” on each call…

While I know nothing of the Stardew Valley time keeping system, the above looks way more complicated than I assume is necessary…

jgodfrey | 2023-05-26 19:04

I would absolutely agree and would even say myself that I have butchered the AM, PM system. I will try going through with debugger again after taking a little break and seeing if I can solve the issue. If you have any recommendations as to how I could go about this in a more simple manor then that would be appreciated.

I had thought of something like this while I was away from the project, just not sure where or how I should implement it or if it even works lol. Gonna do some more testing now though and hopefully discover a solution!

 var amPmString = if isAM: "AM" else: "PM"
    var timeString = str(currentHour).pad_zero(2) + ":" + str(currentMinute).pad_zero(2) + " " + amPmString

Thallium | 2023-05-26 19:18

I’m not sure why you even need to track something like isAm. Shouldn’t that be a given based on the value of your currentHour?

jgodfrey | 2023-05-26 19:23

Yeah I don’t think I do, although I am still getting the same problem even after removing them. It never wants to switch back to AM once it hits midnight. Not sure how I should go about this. The bool was simply to try and avoid it but it did not work.

Thallium | 2023-05-26 19:57

I’ve whacked together some code that (I think) mostly satisfies the needs here (just for a different take on how to approach this). However, it needs some cleanup before it’s ready for public consumption. I’ll try to do that soon and post it here…

jgodfrey | 2023-05-26 20:53

:bust_in_silhouette: Reply From: jgodfrey

Here’s a very quick stab at a more typical way of doing this kind of thing. First, this is FAR from production-level code and could use some serious refactoring (mostly, it’s hot garbage). However, I think (?) it works like the Stardew Valley time system (as I understand it based on some hasty research). I didn’t add any Weekday calculation code, but you could add something like you have in your original code.

Generally, it just tracks real time, but accelerates it to match the Stardew time scale. There are some complications, mostly due to a day starting at 6:00 am and ending at 2:00 am.

I’m sure there are lots of improvements and simplifications that could be made here, but this might give you some ideas…

For my test, I have this simple scene tree:

Node2D
    Label

The Node2D has the following script attached:

extends Node2D
var secs_per_hour = 60 * 60
var curr_time
var prev_time
var time_accelerator = 60.0 / 0.7 # 60 game seconds = 0.7 actual seconds
var day = 1

func _ready():
	curr_time = 6 * secs_per_hour # start at 6 am

func _process(delta):
	curr_time += delta * time_accelerator
	if update_ui_time():
		new_day()
	
func new_day():
	day += 1
	curr_time += 4 * secs_per_hour # add 4 hours (advance from 2am to 6am)
	
func update_ui_time() -> bool:
	var n = int(curr_time)
	if n == prev_time: return false
	prev_time = n
	n = n % (24 * secs_per_hour)
	var hour_24 = n / secs_per_hour
	n %= 3600
	var minute = n / 60 

	var am_pm = "am" if hour_24 < 12 else "pm"
	if hour_24 == 0: hour_24 = 12
	var hour_12 = hour_24
	if hour_12 > 12: hour_12 -= 12

	$Label.text = "Day %d, %02d:%02d %s" % [day, hour_12, minute, am_pm]
	return hour_24 == 2

You went above and beyond my expectations. I was able to learn a ton from this honestly. Works great for what I need a the moment! I am going to begin adding the day system and I will get back with you after that is all completed for the final code! Thank you!!

Thallium | 2023-05-27 03:21

Nice - glad you found something useful there. Let me know if you have questions or want additional input.

jgodfrey | 2023-05-27 14:41