Explosion_der_Spiele/scripts/autoload/game_state.gd
copilot 938cc4bc82 Initial scaffold: Godot 4.3 scenes, systems, and placeholders.
Wire all twelve levels with billboard prefabs, autoload systems (inventory, achievements, mock shop, DE/EN/BY), and satire audio locks so the Title→End flow is playable with placeholder assets.
2026-09-14 18:36:02 +02:00

161 lines
4.5 KiB
GDScript

extends Node
## Global game flow, HP, death, playtime, save/load.
## TODO: Expand save schema when real progression exists.
signal hp_changed(hp: int, max_hp: int)
signal died(cause_key: String)
signal scene_changed(scene_id: String)
const SAVE_PATH := "user://save.json"
const SCENE_ORDER: Array[String] = [
"title_screen",
"intro_cutscene",
"village",
"shoe_boss",
"meadow",
"massage_studio",
"farm_path",
"farm",
"moon",
"final_boss",
"end_screen",
]
const SCENE_PATHS := {
"title_screen": "res://scenes/title_screen.tscn",
"intro_cutscene": "res://scenes/intro_cutscene.tscn",
"village": "res://scenes/village.tscn",
"shoe_boss": "res://scenes/shoe_boss.tscn",
"meadow": "res://scenes/meadow.tscn",
"massage_studio": "res://scenes/massage_studio.tscn",
"farm_path": "res://scenes/farm_path.tscn",
"farm": "res://scenes/farm.tscn",
"moon": "res://scenes/moon.tscn",
"final_boss": "res://scenes/final_boss.tscn",
"end_screen": "res://scenes/end_screen.tscn",
"death_screen": "res://scenes/death_screen.tscn",
}
var current_scene_id: String = "title_screen"
var max_hp: int = 5
var hp: int = 5
var death_count: int = 0
var last_death_cause_key: String = "death_default"
var playtime_seconds: float = 0.0
var house_built: bool = false
var flags: Dictionary = {}
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
load_game()
func _process(delta: float) -> void:
if get_tree().paused:
return
if current_scene_id in ["title_screen", "death_screen"]:
return
playtime_seconds += delta
if playtime_seconds >= 3600.0:
Achievements.unlock("played_hour")
func goto_scene(scene_id: String) -> void:
if not SCENE_PATHS.has(scene_id):
push_error("Unknown scene: %s" % scene_id)
return
current_scene_id = scene_id
scene_changed.emit(scene_id)
if scene_id == "moon":
Achievements.unlock("moon_cheese")
save_game()
get_tree().change_scene_to_file(SCENE_PATHS[scene_id])
func goto_next() -> void:
var idx := SCENE_ORDER.find(current_scene_id)
if idx < 0:
goto_scene("village")
return
if idx >= SCENE_ORDER.size() - 1:
goto_scene("end_screen")
return
goto_scene(SCENE_ORDER[idx + 1])
func skip_to_final_boss() -> void:
Achievements.unlock("milk_skip")
flags["milk_skip_used"] = true
goto_scene("final_boss")
func start_new_game() -> void:
hp = max_hp
flags.clear()
house_built = false
goto_scene("intro_cutscene")
func heal_full() -> void:
hp = max_hp
hp_changed.emit(hp, max_hp)
func take_damage(amount: int = 1, cause_key: String = "death_default") -> void:
hp = max(0, hp - amount)
hp_changed.emit(hp, max_hp)
if hp <= 0:
die(cause_key)
func die(cause_key: String = "death_default") -> void:
last_death_cause_key = cause_key
death_count += 1
died.emit(cause_key)
if death_count >= 100:
Achievements.unlock("died_100")
save_game()
goto_scene("death_screen")
func set_flag(key: String, value: Variant = true) -> void:
flags[key] = value
save_game()
func get_flag(key: String, default_value: Variant = false) -> Variant:
return flags.get(key, default_value)
func save_game() -> void:
var data := {
"hp": hp,
"max_hp": max_hp,
"death_count": death_count,
"last_death_cause_key": last_death_cause_key,
"playtime_seconds": playtime_seconds,
"current_scene_id": current_scene_id,
"house_built": house_built,
"flags": flags,
"inventory": Inventory.serialize(),
"achievements": Achievements.serialize(),
"shop": Shop.serialize(),
"settings": Settings.serialize(),
}
var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
if file == null:
push_warning("Could not write save file")
return
file.store_string(JSON.stringify(data, "\t"))
func load_game() -> void:
if not FileAccess.file_exists(SAVE_PATH):
return
var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
if file == null:
return
var parsed: Variant = JSON.parse_string(file.get_as_text())
if typeof(parsed) != TYPE_DICTIONARY:
return
var data: Dictionary = parsed
hp = int(data.get("hp", max_hp))
max_hp = int(data.get("max_hp", max_hp))
death_count = int(data.get("death_count", 0))
last_death_cause_key = str(data.get("last_death_cause_key", "death_default"))
playtime_seconds = float(data.get("playtime_seconds", 0.0))
current_scene_id = str(data.get("current_scene_id", "title_screen"))
house_built = bool(data.get("house_built", false))
flags = data.get("flags", {})
Inventory.deserialize(data.get("inventory", {}))
Achievements.deserialize(data.get("achievements", {}))
Shop.deserialize(data.get("shop", {}))
Settings.deserialize(data.get("settings", {}))