Implement weather system and developer console features. Added functionality for setting weather conditions, temperature, and wind speed through a new developer console. Enhanced the vault scene to display current weather, temperature, and wind information, and updated game clock to allow time manipulation. Improved cloud rendering and introduced a new climate management system for seasonal temperature adjustments.

This commit is contained in:
Leonid Pershin
2026-08-11 11:37:56 +03:00
parent a81747781d
commit 3b886ab3ab
14 changed files with 928 additions and 63 deletions
+173 -1
View File
@@ -31,7 +31,10 @@ enum Mode { SELECT, BUILD, DEMOLISH }
@onready var _weather: WeatherSystem = $Weather
@onready var _sky: SkyView = $Sky
@onready var _surface: SurfaceView = $Surface
@onready var _weather_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Moment/WeatherLabel
@onready var _weather_icon: WeatherIcon = $Hud/Root/TopRight/Row/ClockBar/Body/Climate/Icon
@onready var _weather_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Climate/WeatherLabel
@onready var _temp_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Climate/TempLabel
@onready var _wind_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Climate/WindLabel
@onready var _stats: HBoxContainer = $Hud/Root/TopBar/Stats
@onready var _date_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Moment/DateLabel
@onready var _time_label: Label = $Hud/Root/TopRight/Row/ClockBar/Body/Moment/TimeLabel
@@ -76,6 +79,7 @@ func _ready() -> void:
_refresh_moment()
_refresh_flow()
_on_weather_changed(_weather.kind)
_register_console_commands()
_status.text = HINT
@@ -191,6 +195,163 @@ func _describe(room: Dictionary) -> String:
return " · ".join(parts)
# --- Команды консоли --------------------------------------------------------
## Команды живут здесь, а не в самой консоли: они управляют этой сценой и
## умирают вместе с ней — консоль сама выбросит их, когда Callable протухнет.
func _register_console_commands() -> void:
var console := get_node_or_null("/root/DevConsole")
if console == null:
return
console.register("stats", "текущее состояние партии", _cmd_stats)
console.register("time", "перевести часы", _cmd_time, "ЧЧ:ММ")
console.register("date", "сменить дату", _cmd_date, "ДД.ММ.ГГГГ")
console.register("speed", "скорость игры, 0 — пауза", _cmd_speed, "0..4")
console.register(
"weather", "поставить погоду", _cmd_weather,
"clear|cloudy|overcast|rain|storm|fog|snow"
)
console.register("temp", "задать температуру", _cmd_temp, "°C")
console.register("wind", "задать ветер", _cmd_wind, "м/с")
console.register("build", "построить комнату", _cmd_build, "тип этаж колонка")
console.register("wipe", "снести все комнаты", _cmd_wipe)
func _cmd_stats(_arguments: Array[String]) -> String:
var totals := _grid.totals()
return "\n".join(PackedStringArray([
"Время: %s, %s (%s, x%d)" % [
_clock.date_text(), _clock.time_text(),
"идёт" if _clock.running else "пауза", _clock.speed,
],
"Погода: %s, %s, ветер %s" % [
_weather.label(),
Climate.temperature_text(_weather.temperature),
Climate.wind_text(_weather.wind_speed),
],
"Облака: %.2f · осадки %.2f · дымка %.2f" % [
_weather.clouds, _weather.precipitation, _weather.fog,
],
"Комнат: %d" % _grid.rooms.size(),
"Ресурсы: питание %+d, вода %+d, еда %+d" % [
int(totals["power"]), int(totals["water"]), int(totals["food"]),
],
]))
func _cmd_time(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: time ЧЧ:ММ"
var parts := arguments[0].split(":")
if parts.size() != 2:
return "Не разобрал время: %s" % arguments[0]
var moment := _clock.now()
moment["hour"] = clampi(int(String(parts[0])), 0, 23)
moment["minute"] = clampi(int(String(parts[1])), 0, 59)
if not _clock.set_moment(moment):
return "Этот момент раньше начала партии."
_refresh_all()
return "Часы: %s" % _clock.time_text()
func _cmd_date(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: date ДД.ММ.ГГГГ"
var parts := arguments[0].split(".")
if parts.size() != 3:
return "Не разобрал дату: %s" % arguments[0]
var moment := _clock.now()
moment["day"] = clampi(int(String(parts[0])), 1, 31)
moment["month"] = clampi(int(String(parts[1])), 1, 12)
moment["year"] = int(String(parts[2]))
if not _clock.set_moment(moment):
return "Этот момент раньше начала партии."
_refresh_all()
return "Дата: %s" % _clock.date_text()
func _cmd_speed(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: speed 0..4"
var value := int(arguments[0])
if value <= 0:
_clock.pause()
return "Пауза."
_clock.set_speed(value)
return "Скорость x%d" % _clock.speed
func _cmd_weather(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: weather clear|cloudy|overcast|rain|storm|fog|snow"
# Понимаем и латинский ключ, и русское название — как удобнее.
var wanted := arguments[0].to_lower()
for kind: int in WeatherSystem.KINDS:
var entry: Dictionary = WeatherSystem.KINDS[kind]
if String(entry["key"]) != wanted and String(entry["label"]).to_lower() != wanted:
continue
_weather.force_kind(kind)
_refresh_all()
return "Погода: %s" % _weather.label()
return "Не знаю такой погоды: %s" % arguments[0]
func _cmd_temp(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: temp °C"
_weather.nudge_temperature(float(arguments[0]))
_refresh_all()
return "Температура: %s" % Climate.temperature_text(_weather.temperature)
func _cmd_wind(arguments: Array[String]) -> String:
if arguments.is_empty():
return "Нужен аргумент: wind м/с"
_weather.set_wind_speed(float(arguments[0]))
_refresh_all()
return "Ветер: %s" % Climate.wind_text(_weather.wind_speed)
func _cmd_build(arguments: Array[String]) -> String:
if arguments.size() < 3:
return "Нужно: build тип этаж колонка. Типы: %s" % ", ".join(VaultGrid.KINDS.keys())
var kind := arguments[0]
if not VaultGrid.KINDS.has(kind):
return "Нет такого типа: %s" % kind
var a_floor := int(arguments[1]) - 1
var column := int(arguments[2])
if not _grid.place(kind, a_floor, column):
return "Сюда не поставить: занято или вплотную к шахте."
_after_change("Построено из консоли: %s" % VaultGrid.KINDS[kind]["label"])
return "Готово: %s на этаже %d" % [VaultGrid.KINDS[kind]["label"], a_floor + 1]
func _cmd_wipe(_arguments: Array[String]) -> String:
var removed := _grid.rooms.size()
_grid.rooms.clear()
_after_change("Убежище очищено.")
return "Снесено комнат: %d" % removed
## После вмешательства извне проще обновить всё, чем вспоминать, что зависит
## от чего.
func _refresh_all() -> void:
_refresh_moment()
_refresh_environment()
_refresh_weather_hud()
_refresh_flow()
_refresh_stats()
# --- Ход времени ------------------------------------------------------------
func _build_flow_controls() -> void:
@@ -249,10 +410,21 @@ func _flow_style(background: String, border: String) -> StyleBoxFlat:
func _on_minute_passed(_total_minutes: int) -> void:
_refresh_moment()
_refresh_environment()
_refresh_weather_hud()
func _on_weather_changed(_kind: int) -> void:
_refresh_weather_hud()
func _refresh_weather_hud() -> void:
var hour := SkyCycle.hour_of(_clock.now())
var is_night := SkyCycle.sun_progress(hour) < 0.0
_weather_icon.set_state(_weather.kind, is_night)
_weather_label.text = _weather.label()
_temp_label.text = Climate.temperature_text(_weather.temperature)
_wind_label.text = Climate.wind_text(_weather.wind_speed)
func _refresh_moment() -> void: