extends Node ## Globaler Spielzustand: Wissen, Fertigkeiten, Missionen, Uhrzeit. signal state_changed signal notified(text: String, color: Color) signal mission_done(human_id: String) const DAY_SECONDS := 360.0 # eine Erdenrunde in Echtzeit-Sekunden const XP_LEVELS := [0, 4, 10, 18, 28] const MISSION_ZIEL := 100.0 const RESIST_SEKUNDEN := 18.0 var einsicht: int = 3 var known: Dictionary = {} # tech_id -> xp var active_mission: String = "" # human_id oder "" var progress: Dictionary = {} # human_id -> 0..100 var used: Dictionary = {} # "human:tech" -> Anzahl var completed: Array = [] var time_h: float = 7.0 var day: int = 1 var teleport_lock: float = 0.0 func _ready() -> void: _setup_input() func _setup_input() -> void: var binds := { "vor": [KEY_W, KEY_UP], "zurueck": [KEY_S, KEY_DOWN], "links": [KEY_A, KEY_LEFT], "rechts": [KEY_D, KEY_RIGHT], "steigen": [KEY_SPACE], "sinken": [KEY_SHIFT], "interagieren": [KEY_E], "kodex": [KEY_TAB], } for action in binds: if not InputMap.has_action(action): InputMap.add_action(action) for code in binds[action]: var ev := InputEventKey.new() ev.physical_keycode = code InputMap.action_add_event(action, ev) func advance_time(delta: float) -> void: time_h += delta * 24.0 / DAY_SECONDS while time_h >= 24.0: time_h -= 24.0 day += 1 func time_string() -> String: var h := int(time_h) var m := int((time_h - h) * 60.0) return "Tag %d · %02d:%02d" % [day, h, m] # ---------------------------------------------------------------- Fertigkeiten func knows(tech_id: String) -> bool: return known.has(tech_id) func skill_of(tech_id: String) -> int: if not known.has(tech_id): return 0 var xp: int = known[tech_id] var lvl := 1 for i in range(XP_LEVELS.size()): if xp >= XP_LEVELS[i]: lvl = i + 1 return lvl func xp_to_next(tech_id: String) -> String: var lvl := skill_of(tech_id) if lvl >= XP_LEVELS.size(): return "Meisterschaft" var need: int = XP_LEVELS[lvl] return "%d / %d EP" % [known[tech_id], need] func learn(tech_id: String) -> bool: if known.has(tech_id): return false if einsicht < 1: notified.emit("Dafür fehlt dir Einsicht. Hilf erst einem Menschen.", Color(1, 0.6, 0.4)) return false einsicht -= 1 known[tech_id] = 0 var t := TechDB.by_id(tech_id) notified.emit("Technik gelernt: %s" % t["name"], Color(0.6, 1, 0.7)) state_changed.emit() return true func add_xp(tech_id: String, amount: int) -> void: if not known.has(tech_id): return var before := skill_of(tech_id) known[tech_id] = int(known[tech_id]) + amount if skill_of(tech_id) > before: var t := TechDB.by_id(tech_id) notified.emit("%s ist jetzt Stufe %d." % [t["name"], skill_of(tech_id)], Color(0.7, 0.9, 1)) state_changed.emit() func deepen(tech_id: String) -> bool: if not known.has(tech_id): return false if einsicht < 1: notified.emit("Keine Einsicht übrig.", Color(1, 0.6, 0.4)) return false einsicht -= 1 add_xp(tech_id, 3) notified.emit("Vertieft: %s (+3 EP)" % TechDB.by_id(tech_id)["name"], Color(0.7, 0.9, 1)) return true # ------------------------------------------------------------------ Missionen func accept_mission(human_id: String) -> bool: if completed.has(human_id): return false if active_mission == human_id: return false active_mission = human_id if not progress.has(human_id): progress[human_id] = 0.0 var h := HumanDB.by_id(human_id) notified.emit("Mission angenommen: %s" % h["name"], Color(1, 0.9, 0.5)) state_changed.emit() return true func mission_progress(human_id: String) -> float: return progress.get(human_id, 0.0) # ----------------------------------------------------- Technik auf Mensch anwenden ## Bewertet eine Technik in genau dieser Situation, ohne sie anzuwenden. func evaluate(tech_id: String, human_id: String, activity: String, resisting: bool) -> Dictionary: var t := TechDB.by_id(tech_id) var h := HumanDB.by_id(human_id) var skill := skill_of(tech_id) var res := { "chance": 0.0, "tag": false, "moment": false, "blocked": false, "grund": "", "skill": skill, } if activity == "schlaeft": res["blocked"] = true res["grund"] = "Sie oder er schläft. Techniken erreichen nur wache Menschen." return res if skill == 0: res["blocked"] = true res["grund"] = "Technik nicht gelernt." return res for tag in t["tags"]: if h["tags"].has(tag): res["tag"] = true break res["moment"] = t["momente"].has(activity) var c := 0.08 + 0.11 * float(skill) if res["tag"]: c += 0.25 if res["moment"]: c += 0.22 if resisting: c -= 0.30 res["grund"] = "Der Mensch macht gerade dicht." res["chance"] = clampf(c, 0.05, 0.95) return res ## Wendet die Technik wirklich an: würfelt, verteilt EP und Fortschritt. func apply_technique(tech_id: String, human_id: String, activity: String, resisting: bool) -> Dictionary: var ev := evaluate(tech_id, human_id, activity, resisting) if ev["blocked"]: return {"ok": false, "grund": ev["grund"]} var roll := randf() var success: bool = roll < float(ev["chance"]) var key := "%s:%s" % [human_id, tech_id] var wiederholung: int = used.get(key, 0) used[key] = wiederholung + 1 var gain := 0.0 if success: var base := 8.0 + 2.0 * float(ev["skill"]) if ev["tag"]: base += 5.0 if ev["moment"]: base += 5.0 gain = base / (1.0 + 0.6 * float(wiederholung)) add_xp(tech_id, 2) else: add_xp(tech_id, 1) var done := false if human_id == active_mission and gain > 0.0: var p: float = progress.get(human_id, 0.0) + gain progress[human_id] = minf(p, MISSION_ZIEL) if progress[human_id] >= MISSION_ZIEL and not completed.has(human_id): completed.append(human_id) active_mission = "" einsicht += 3 done = true mission_done.emit(human_id) notified.emit("%s hat es geschafft. (+3 Einsicht)" % HumanDB.by_id(human_id)["name"], Color(1, 0.85, 0.4)) state_changed.emit() return { "ok": true, "success": success, "chance": ev["chance"], "gain": gain, "wiederholung": wiederholung, "mission_done": done, "tag": ev["tag"], "moment": ev["moment"], }