saumwacht-godot/scripts/autoload/preferences.gd
Martin Stickelbroeck 1b540f2a55 G3 (Zwischenstand): neues Ingame-HUD; Projekt wechselt nach Unity
Nicht abgenommen: Nach dem ersten Spieltest wurde entschieden, Champions of
Luneraria nach Unity 6 zu portieren. Dieser Stand ist die Referenz für das
HUD im Unity-Projekt (../luneraria-unity).

- HUD neu aus Komponenten mit eigenem Theme, Porträts aus den echten Modellen
  (einmal gerendert, zwischengespeichert), Lane-Übersicht mit deterministischer
  Bedrohung aus öffentlichem Zustand, Bossgrotte, nächste Welle, Ereignisse,
  Minimap mit zusammengefassten Armeen, Held/Items/Talente, Einheitendetails,
  Angriffschampions, Bereit-Sperre, UI-Größe, Team-Formen statt nur Farben
- Privatsphäre über LuneHudModel: fremdes Gold und fremde Entwürfe erscheinen nie
- Keine Regeländerung: Regeln 91/91, M2 73/73, Netz 43/43; verify_g3 715/715;
  verify_m1 38/38 und verify_m2 14/14 mit angepassten UI-Treibern
- Spieltest bis Welle 8 über die echte Oberfläche, Befunde in G3-HUD.md
- HELDEN-KONZEPT.md: vom Projektinhaber vorgegebene Helden (nicht umgesetzt)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:59:55 +02:00

63 lines
2.6 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
## Size of the in-match HUD (Luneraria); the HUD caps it so its layout always fits.
var ui_scale: float = 1.0
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))
ui_scale = clampf(float(config.get_value("display", "ui_scale", 1.0)), .75, 1.5)
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)
config.set_value("display", "ui_scale", ui_scale)
return config.save(storage_path)
func commit() -> void:
apply()
save_settings()