saumwacht-godot/scripts/autoload/preferences.gd
Martin Stickelbroeck c27a0097c3 M1: spielbarer Drei-Lane-Kern mit Karte, HUD, Menü und Abnahme
Hauptszene scenes/luneraria.tscn, Saumwacht bleibt über --legacy und die
alten QA-Schalter erreichbar. Karte aus Bestandsassets plus neuem Turm,
HUD mit Planung, Lanes und Minimap, Menü umbenannt, Einstellungen werden
aus dem alten Benutzerordner übernommen. Simulation 6,6x schneller
(Raster, Caches, faire Staffelung) und exakt spiegelsymmetrisch.
Regeln 91/91, echte Anwendung 38/38, Legacy unverändert grün.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:37:23 +02:00

59 lines
2.3 KiB
GDScript

extends Node
## Local preferences only. Match rules and ownership are never saved here.
signal changed
var volume: float = .65
var muted: bool = false
var follow_camera: bool = true
var fullscreen: bool = false
## Menu camera travel, idle drift, particles and fades are skipped when set.
var reduced_motion: bool = false
var storage_path: String = "user://preferences.cfg"
func _ready() -> void:
read_settings()
apply()
## The project was renamed from "Saumwacht · Glutpakt"; its user folder changed with it.
const LEGACY_FOLDER := "Saumwacht · Glutpakt"
var migrated_from: String = ""
func _legacy_path() -> String:
var own: String = ProjectSettings.globalize_path("user://")
var parent: String = own.trim_suffix("/").get_base_dir()
return parent.path_join(LEGACY_FOLDER).path_join("preferences.cfg")
func read_settings() -> void:
var config := ConfigFile.new()
if storage_path == "user://preferences.cfg" and not FileAccess.file_exists(storage_path) and FileAccess.file_exists(_legacy_path()):
# One-time copy of the old options; the old file stays untouched.
if config.load(_legacy_path()) == OK and config.save(storage_path) == OK:
migrated_from = _legacy_path()
print("PREFERENCES: übernommen aus ", migrated_from)
if config.load(storage_path) != OK:
return
volume = clampf(float(config.get_value("audio", "volume", .65)), 0.0, 1.0)
muted = bool(config.get_value("audio", "muted", false))
follow_camera = bool(config.get_value("camera", "follow", true))
fullscreen = bool(config.get_value("display", "fullscreen", false))
reduced_motion = bool(config.get_value("display", "reduced_motion", false))
func apply() -> void:
AudioServer.set_bus_volume_db(0, linear_to_db(maxf(.001, volume)))
AudioServer.set_bus_mute(0, muted or volume <= 0.0)
if DisplayServer.get_name() != "headless":
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if fullscreen else DisplayServer.WINDOW_MODE_WINDOWED)
changed.emit()
func save_settings() -> Error:
var config := ConfigFile.new()
config.set_value("audio", "volume", volume)
config.set_value("audio", "muted", muted)
config.set_value("camera", "follow", follow_camera)
config.set_value("display", "fullscreen", fullscreen)
config.set_value("display", "reduced_motion", reduced_motion)
return config.save(storage_path)
func commit() -> void:
apply()
save_settings()