308 lines
8.7 KiB
GDScript
308 lines
8.7 KiB
GDScript
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
|