edc40f9008
- Touch controls: direct InputEventScreenTouch in shop_ui (bypass relay) - ItemDB: static preload list instead of DirAccess scan (export fix) - All 18 items with EN localisation (name_en, desc_en, category_en) - Ship playstyles: NOVA-1 shield, INFERNO ram, AURORA agile/tank - Quasar: SMBH visual, jet boost, merge, push, BH-eating - Atlas & UI text updated EN+DE Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
98 lines
3.5 KiB
GDScript
98 lines
3.5 KiB
GDScript
extends Node
|
|
|
|
var master_volume: float = 1.0
|
|
var sfx_muted: bool = false
|
|
var music_volume: float = 0.8
|
|
var fullscreen: bool = false
|
|
var nebula_enabled: bool = true
|
|
var star_density: int = 1 # 0=low 1=mid 2=high
|
|
var language: String = "de" # "de" or "en"
|
|
var touch_mode: int = 0 # 0=auto, 1=always on, 2=always off
|
|
|
|
# Runtime-only — not saved. Set by input detection in main.gd / touch_controls.gd.
|
|
var last_input_device: String = "keyboard" # "keyboard" | "pad" | "touch"
|
|
|
|
# Rebindable gameplay actions (P1 only).
|
|
const REBIND_ACTIONS: Array[String] = ["p1_thrust", "p1_left", "p1_right", "p1_shoot", "p1_wipe"]
|
|
|
|
# Stores physical keycodes (int) for rebound keys. Empty = use project defaults.
|
|
var key_bindings: Dictionary = {}
|
|
|
|
const PATH := "user://settings.cfg"
|
|
|
|
func _ready() -> void:
|
|
load_settings()
|
|
apply_all()
|
|
|
|
func apply_all() -> void:
|
|
apply_volume()
|
|
apply_key_bindings()
|
|
# Mobile always runs fullscreen — ignore the saved setting.
|
|
if OS.has_feature("android") or OS.has_feature("ios"):
|
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
|
elif fullscreen:
|
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
|
|
else:
|
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
|
|
|
|
func apply_volume() -> void:
|
|
var db := linear_to_db(master_volume) if not sfx_muted else -80.0
|
|
AudioServer.set_bus_volume_db(0, db)
|
|
|
|
func apply_music_volume() -> void:
|
|
var bus_idx := AudioServer.get_bus_index("Music")
|
|
if bus_idx != -1:
|
|
AudioServer.set_bus_volume_db(bus_idx,
|
|
linear_to_db(music_volume) if music_volume > 0.0 else -80.0)
|
|
|
|
func apply_key_bindings() -> void:
|
|
for action: String in key_bindings:
|
|
var keycode: int = key_bindings[action]
|
|
if keycode > 0 and InputMap.has_action(action):
|
|
# Remove existing keyboard events for this action
|
|
var events := InputMap.action_get_events(action)
|
|
for ev in events:
|
|
if ev is InputEventKey:
|
|
InputMap.action_erase_event(action, ev)
|
|
# Add the custom key
|
|
var new_ev := InputEventKey.new()
|
|
new_ev.physical_keycode = keycode as Key
|
|
InputMap.action_add_event(action, new_ev)
|
|
|
|
func reset_key_bindings() -> void:
|
|
InputMap.load_from_project_settings()
|
|
key_bindings.clear()
|
|
save_settings()
|
|
|
|
func save_settings() -> void:
|
|
var cfg := ConfigFile.new()
|
|
cfg.set_value("sound", "volume", master_volume)
|
|
cfg.set_value("sound", "muted", sfx_muted)
|
|
cfg.set_value("sound", "music", music_volume)
|
|
cfg.set_value("graphics", "fullscreen", fullscreen)
|
|
cfg.set_value("graphics", "nebula", nebula_enabled)
|
|
cfg.set_value("graphics", "stars", star_density)
|
|
cfg.set_value("game", "language", language)
|
|
cfg.set_value("game", "touch_mode", touch_mode)
|
|
for action: String in REBIND_ACTIONS:
|
|
if key_bindings.has(action):
|
|
cfg.set_value("bindings", action, key_bindings[action])
|
|
cfg.save(PATH)
|
|
|
|
func load_settings() -> void:
|
|
var cfg := ConfigFile.new()
|
|
if cfg.load(PATH) != OK:
|
|
return
|
|
master_volume = cfg.get_value("sound", "volume", 1.0)
|
|
sfx_muted = cfg.get_value("sound", "muted", false)
|
|
music_volume = cfg.get_value("sound", "music", 0.8)
|
|
fullscreen = cfg.get_value("graphics", "fullscreen", false)
|
|
nebula_enabled = cfg.get_value("graphics", "nebula", true)
|
|
star_density = cfg.get_value("graphics", "stars", 1)
|
|
language = cfg.get_value("game", "language", "de")
|
|
touch_mode = cfg.get_value("game", "touch_mode", 0)
|
|
key_bindings.clear()
|
|
for action: String in REBIND_ACTIONS:
|
|
if cfg.has_section_key("bindings", action):
|
|
key_bindings[action] = cfg.get_value("bindings", action)
|