Refactor game scripts and update vault scene structure. Enhanced organization of game logic by separating data and rendering responsibilities across multiple scripts. Removed unused background assets and updated vault scene to include new game clock and weather system functionalities.

This commit is contained in:
Leonid Pershin
2026-08-11 10:18:30 +03:00
parent 709776116b
commit a81747781d
48 changed files with 979 additions and 4509 deletions
+142
View File
@@ -0,0 +1,142 @@
class_name GameClock
extends Node
## Игровые дата и время.
##
## Отдельная сущность, а не поле сцены: ход времени понадобится производству,
## жителям и событиям, и сохранение обязано его восстанавливать.
##
## Пауза здесь своя, не движковая. `get_tree().paused` останавливает вообще всё
## и занята меню паузы; здесь же нужно останавливать только ход партии, оставляя
## интерфейс живым. При этом узел обычный, PAUSABLE, поэтому меню паузы
## замораживает время само собой.
## Старт партии: 1 апреля 2012 года, шесть утра.
const START := {"year": 2012, "month": 4, "day": 1, "hour": 6, "minute": 0, "second": 0}
## Сколько игровых минут проходит за секунду реального времени на скорости x1.
## Сутки при этом занимают 8 минут реального времени. Множители x2…x4
## умножают именно это значение, так что менять темп достаточно здесь.
const MINUTES_PER_SECOND := 3.0
## Доступные множители скорости.
const SPEEDS: Array[int] = [1, 2, 3, 4]
const MINUTES_PER_DAY := 24 * 60
const MONTHS: Array[String] = [
"января", "февраля", "марта", "апреля", "мая", "июня",
"июля", "августа", "сентября", "октября", "ноября", "декабря",
]
## Прошла игровая минута — сюда подключаются HUD, производство, события.
signal minute_passed(total_minutes: int)
## Сменились сутки.
signal day_passed(day_index: int)
## Изменились скорость или состояние паузы.
signal flow_changed
var running := true
var speed := 1
var _start_unix := int(Time.get_unix_time_from_datetime_dict(START))
var _elapsed_minutes := 0.0
var _last_whole_minute := 0
var _last_day := 0
func _process(delta: float) -> void:
if not running:
return
_advance(delta * MINUTES_PER_SECOND * float(speed))
# --- Текущий момент ---------------------------------------------------------
## Момент как словарь Time: year, month, day, hour, minute, second.
func now() -> Dictionary:
return Time.get_datetime_dict_from_unix_time(unix_time())
func unix_time() -> int:
return _start_unix + int(_elapsed_minutes) * 60
## «1 апреля 2012»
func date_text() -> String:
var moment := now()
return "%d %s %d" % [
int(moment["day"]), MONTHS[int(moment["month"]) - 1], int(moment["year"]),
]
## «06:00»
func time_text() -> String:
var moment := now()
return "%02d:%02d" % [int(moment["hour"]), int(moment["minute"])]
# --- Управление ходом -------------------------------------------------------
func set_speed(value: int) -> void:
speed = clampi(value, SPEEDS[0], SPEEDS[SPEEDS.size() - 1])
running = true
flow_changed.emit()
func play() -> void:
if running:
return
running = true
flow_changed.emit()
func pause() -> void:
if not running:
return
running = false
flow_changed.emit()
func toggle() -> void:
running = not running
flow_changed.emit()
# --- Сохранение -------------------------------------------------------------
func save_data() -> Dictionary:
return {"minutes": _elapsed_minutes, "speed": speed, "running": running}
func load_data(data: Dictionary) -> void:
_elapsed_minutes = maxf(float(data.get("minutes", 0.0)), 0.0)
speed = clampi(int(data.get("speed", 1)), SPEEDS[0], SPEEDS[SPEEDS.size() - 1])
running = bool(data.get("running", true))
_last_whole_minute = int(_elapsed_minutes)
_last_day = _day_index()
flow_changed.emit()
minute_passed.emit(_last_whole_minute)
# --- Внутреннее -------------------------------------------------------------
func _advance(minutes: float) -> void:
_elapsed_minutes += minutes
# Сигналим по целым минутам, а не каждый кадр: подписчикам нужен такт,
# а не дробное значение.
var whole := int(_elapsed_minutes)
if whole == _last_whole_minute:
return
_last_whole_minute = whole
minute_passed.emit(whole)
var day := _day_index()
if day == _last_day:
return
_last_day = day
day_passed.emit(day)
func _day_index() -> int:
return floori(_elapsed_minutes / float(MINUTES_PER_DAY))