extends Node var is_during_dialog = false var is_during_cinematic = false var variables := { } var options_visited_global := { } var options_visited_dialog := { } var time = 0 var gametime_offset = 0 var gametime_year = 1 @onready var gametime = epoch_to_game_time(time) func set_variable(var_name: String, var_value) -> void: variables[var_name] = var_value func get_variable(var_name: String, default = 0.0): if var_name in variables: return variables[var_name] else: return default func set_option_visited(option: DialogNodeOptionData, visited: bool): options_visited_global[option.resource_scene_unique_id] = visited options_visited_dialog[option.resource_scene_unique_id] = visited func get_option_visited_global(option: DialogNodeOptionData) -> bool: if not option.resource_scene_unique_id in options_visited_global: return false return options_visited_global[option.resource_scene_unique_id] func get_option_visited_dialog(option: DialogNodeOptionData) -> bool: if not option.resource_scene_unique_id in options_visited_dialog: return false return options_visited_dialog[option.resource_scene_unique_id] func reset_options_visited_dialog(): options_visited_dialog.clear() # ============================================================================== # LOCALE var default_locale := "en" var current_locale := "" func set_locale(locale_code: String): current_locale = locale_code if current_locale == default_locale: current_locale = "" func set_default_locale(locale_code: String): default_locale = locale_code if current_locale == default_locale: current_locale = "" func set_locale_automatic(def_locale: String = default_locale): default_locale = def_locale var locale = OS.get_locale_language() set_locale(locale) func set_locale_from_project(def_locale: String = default_locale): default_locale = def_locale var locale = TranslationServer.get_locale() if "_" in locale: locale = locale.left(locale.find("_")) set_locale(locale) # ============================================================================== # TIME func set_game_year(year: int) -> void: gametime_year = year var dt = { "year": year, "month": 1, "day": 1, "hour": 0, "minute": 0, "second": 0 } gametime_offset = Time.get_unix_time_from_datetime_dict(dt) gametime = epoch_to_game_time(time) ## # Returns datetime in game reference (that is, # start of game is 01/01/0001 00:00:00) # Can be seen as "elapsed gameplay time" func epoch_to_game_time(epoch_time: int) -> Dictionary: # Date time dictionary has the format: # { # "year": ..., # "month": ..., # "day": ..., # "weekday": ..., # "hour": ..., # "minute": ..., # "second": ... # } # Custom values added here are: # "time": String hour/minute in format HH:MM # "date": String day/month in format DD/MM # "date_inv": String day/month in format MM/DD var dt = Time.get_datetime_dict_from_unix_time(gametime_offset + epoch_time) dt["year"] -= gametime_year-1 # year - 1, so starts at year 1 dt["time"] = "%02d:%02d" % [dt["hour"], dt["minute"]] dt["date"] = "%02d/%02d" % [dt["day"], dt["month"]] dt["date_inv"] = "%02d/%02d" % [dt["month"], dt["day"]] dt["weekday_name"] = MTDefs.WeekdayNames[dt["weekday"]] dt["wday_name"] = MTDefs.WeekdayNamesShort[dt["weekday"]] return dt # Converts day, month, year to unix epoch time func game_time_to_epoch(p_gametime: Dictionary) -> int: p_gametime["year"] += gametime_year-1 # Year 1 is base, return Time.get_unix_time_from_datetime_dict(p_gametime) - gametime_offset func update_gametime_dict(): gametime = epoch_to_game_time(time) # Converts day, month, year to unix epoch time func date_to_int(day: int, month: int, year: int) -> int: return game_time_to_epoch({ "year": year, "month": month, "day": day, "hour": 0, "minute": 0, "second": 0 }) # Converts hour, minute to float fractional hour # Example: 2, 30 becomes 2.5 func time_to_float(hour: int, minute: int) -> float: return float(hour) + float(minute)/60.0 func time_to_string(epoch_time: int, simplified: bool = true) -> String: # Date time dictionary has the format: # { # "year": ..., # "month": ..., # "day": ..., # "weekday": ..., # "hour": ..., # "minute": ..., # "second": ... # } var dt = epoch_to_game_time(epoch_time) var res = "" # Simplified version is Weekday HH:MM if (simplified): res = MTDefs.WeekdayNames[dt['weekday']].left(3) res += " %02d:%02d" % [dt['hour'], dt['minute']] # Non-simplified is Weekday, DD of MonthName HH:MM else: res = MTDefs.WeekdayNames[dt['weekday']] res += ", "+str(dt['day']) res += " "+MTDefs.MonthNames[dt['month']] res += " %02d:%02d" % [dt['hour'], dt['minute']] return res func split_time(value: String) -> Array: # TODO: this is not very efficient code. To be rewritten to run faster var nums_psa = Array(str(value).split(':')) while nums_psa.size() < 2: nums_psa.append(0) var nums = [int(nums_psa[0]), int(nums_psa[1])] if (nums[0] < 0) or (nums[0] > 23): nums[0] = 0 if (nums[1] < 0) or (nums[1] > 59): nums[1] = 0 return [nums[0], nums[1]] func split_date(value: String) -> Array: # TODO: this is not very efficient code. To be rewritten to run faster var nums_psa = Array(str(value).split('/')) while nums_psa.size() < 2: nums_psa.append(1) var nums = [int(nums_psa[0]), int(nums_psa[1])] if (nums[0] < 1) or (nums[0] > 31): nums[0] = 1 if (nums[1] < 1) or (nums[1] > 12): nums[1] = 1 return [nums[0], nums[1]] func print_date(value: String) -> String: var nums = split_date(value) var day = "%02d" % nums[0] var month = MTDefs.MonthNames[nums[1]].left(3) return day+' '+month func print_weekday(value): while value > 6: value -= 7 return MTDefs.WeekdayNames[value] func split_string_autodetect_rn(value: String) -> Array: var result = [] value = str(value) if "\r\n" in value: # Windows style result = value.split("\r\n") elif "\r" in value: # MacOS style result = value.split("\r") else: # Unix style result = value.split("\n") return result func next_time_at_time(time_value: String) -> int: var asked_time = split_time(time_value) # We calculate epoch time value for the requested hour happening today # if we are before this time, this is what we want var ingame_time_as_today = game_time_to_epoch({ "year": gametime["year"], "month": gametime["month"], "day": gametime["day"], "hour": asked_time[0], "minute": asked_time[1], "second": 0 }) if time <= ingame_time_as_today: return ingame_time_as_today # If we are after this time, we want the same time but tomorrow # so we add 24 hours else: return ingame_time_as_today + 24*60*60 # seconds func next_time_at_weekday(weekday: int) -> int: # First we find the weekday delta handling when the requested weekday # is lower (or equal) than current one var asked_weekday = weekday if weekday > gametime["weekday"] else weekday + 7 var weekday_delta = asked_weekday - gametime["weekday"] # Find time for midnight of today var ingame_midnight_today = game_time_to_epoch({ "year": gametime["year"], "month": gametime["month"], "day": gametime["day"], "hour": 0, "minute": 0, "second": 0 }) # Finally we just offset the weekday_delta days into the future return ingame_midnight_today + weekday_delta*24*60*60 # seconds func export_game_data() -> Dictionary: var visited_options := {} for item_ui in options_visited_global: visited_options[item_ui] = "1" if options_visited_global[item_ui] else "0" var result = { "time": time, "gametime_offset": gametime_offset, "gametime_year": gametime_year, "variables": variables, "visited_options": visited_options, } return result func import_game_data(data: Dictionary) -> void: if ("time" in data): time = int(round(float(data["time"]))) if ("gametime_offset" in data): gametime_offset = int(round(float(data["gametime_offset"]))) if ("gametime_year" in data): gametime_year = int(round(float(data["gametime_year"]))) options_visited_global.clear() if "visited_options" in data: var visited_dict: Dictionary = data["visited_options"] for item_ui in visited_dict: # If coming from a saved file, item_ui will never be StringName # but this Dictionary might be coming from a serialized Resource (bad idea, but still) if (item_ui is String) or (item_ui is StringName): options_visited_global[item_ui] = (not visited_dict[item_ui] in [false, "false", 0, 0.0, "0", "0.0", "no"]) variables.clear() for variable_name in data["variables"]: if variable_name is String: var value = data["variables"][variable_name] if typeof(value) in [TYPE_INT, TYPE_FLOAT, TYPE_STRING]: # All numeric values can be safely assumed float (as per JSON) # since all methods using them do proper casting variables[variable_name] = value # Silently ignore everything else