This commit is contained in:
Team3
2026-09-05 10:25:55 +02:00
parent 8b60164592
commit 124a55a03e
16 changed files with 659 additions and 92 deletions

View File

@@ -13,7 +13,6 @@ const RESIST_SEKUNDEN := 18.0
## nicht der Faktor — Stufe 2 läuft dreifach, Stufe 3 siebenfach.
const TEMPO_FAKTOR := [1.0, 3.0, 7.0]
const TECHNIK_COOLDOWN := 30.0 # eine Technik braucht Luft, bevor sie wieder greift
const FEHLVERSUCH_VERLUST := 14.0 # ein Fehlschlag wirft den Traum zurück
# Der Verlust ist mit Absicht so hoch, dass sich nur eine Technik lohnt, die
# Thema UND Moment trifft. Wer eine Regel blind auf jede Tätigkeit hängt,
# verliert unterm Strich — die Wahl muss aus der Technik gelesen werden.
@@ -26,6 +25,11 @@ var systeme: Dictionary = {} # human_id -> {slot -> {tech, guete}}
var erkannt_slots: Dictionary = {} # human_id -> {slot -> true}
var gesehen: Dictionary = {} # human_id -> {slot -> true}, wo man dabei war
var notiz_sperre: float = 0.0 # nach einem Fehlgriff kurz gesperrt
var situation: Dictionary = {} # laufende Situation: mensch, key, rest
var situation_pause: float = 0.0 # bis die nächste kommen darf
var probleme_bekannt: Dictionary = {} # human_id -> {problem -> true}
var problem_stand: Dictionary = {} # "human:problem" -> gelungene Anwendungen
var ueberwunden: Dictionary = {} # human_id -> {problem -> true}
var completed: Array = []
var time_h: float = 7.0
var day: int = 1
@@ -344,6 +348,24 @@ func sehen(human_id: String, nr: int) -> void:
state_changed.emit()
## Der Zustand einer Stunde. HUD und Panel zeichnen denselben -- zwei
## Auslegungen würden mit der Zeit auseinanderlaufen.
enum Stunde { UNBEKANNT, GESEHEN, SCHLAF, UNGEKLAERT, BENANNT, GEBAUT }
func slot_zustand(human_id: String, nr: int) -> int:
if not gesehen_slot(human_id, nr):
return Stunde.UNBEKANNT
if not system_in(human_id, nr).is_empty():
return Stunde.GEBAUT
var grund := slot_grund(human_id, nr)
if Ursachen.ist_blocker(grund):
return Stunde.BENANNT if erkannt(human_id, nr) else Stunde.UNGEKLAERT
if grund == "schlaeft":
return Stunde.SCHLAF
return Stunde.GESEHEN
func slot_grund(human_id: String, nr: int) -> String:
var r := slots(human_id)
return str(r[nr][2]) if nr >= 0 and nr < r.size() else ""
@@ -501,6 +523,8 @@ func system_anzahl(human_id: String) -> int:
func traum_voranbringen(stunden: float) -> void:
if active_mission == "":
return
if situation_bei(active_mission):
return # im Moment geht nichts voran
var p: float = progress.get(active_mission, 0.0) \
+ traum_tempo(active_mission) * stunden / 24.0
progress[active_mission] = minf(p, MISSION_ZIEL)
@@ -514,6 +538,151 @@ func traum_voranbringen(stunden: float) -> void:
state_changed.emit()
# ------------------------------------------------------- Probleme und Momente
# Die zweite Ebene. Eine Gewohnheit sitzt im Tagesablauf und läuft ohne dich
# weiter, sobald ein System steht. Ein Problem sitzt in keiner Stunde -- es
# bricht in Situationen auf. Solange eine läuft, kommt der Traum nicht voran.
# Du kannst sie aussitzen oder mit der passenden Technik beenden.
const SITUATION_DAUER := 22.0 # so lange steht der Traum still
const SITUATION_PAUSE := 40.0 # Luft zwischen zwei Situationen
const PROBLEM_UEBERWINDEN := 3 # so oft muss eine Technik greifen
const SITUATION_GEWINN := 6.0 # Prozent, wenn sie früh beendet wird
func probleme_von(human_id: String) -> Array:
var h := HumanDB.by_id(human_id)
return h["probleme"] if h.has("probleme") else []
func problem_bekannt(human_id: String, problem: String) -> bool:
return probleme_bekannt.get(human_id, {}).has(problem)
func problem_ueberwunden(human_id: String, problem: String) -> bool:
return ueberwunden.get(human_id, {}).has(problem)
func problem_fortschritt(human_id: String, problem: String) -> int:
return int(problem_stand.get("%s:%s" % [human_id, problem], 0))
func situation_laeuft() -> bool:
return not situation.is_empty()
func situation_bei(human_id: String) -> bool:
return situation_laeuft() and str(situation["mensch"]) == human_id
func situation_problem() -> String:
return str(situation["problem"]) if situation_laeuft() else ""
## Läuft die Uhr weiter, kommt irgendwann die nächste Situation -- aber nur
## bei einem wachen Menschen, dem man gerade hilft.
func situationen_ticken(delta: float, wach: bool) -> void:
if situation_laeuft():
situation["rest"] = float(situation["rest"]) - delta
if float(situation["rest"]) <= 0.0:
var p := situation_problem()
notified.emit("Der Moment ist vorbei — %s bleibt." % Probleme.name_von(p),
Color(1, 0.75, 0.55))
situation = {}
situation_pause = SITUATION_PAUSE
state_changed.emit()
return
situation_pause = maxf(0.0, situation_pause - delta)
if active_mission == "" or not wach or situation_pause > 0.0:
return
_situation_starten()
func _situation_starten() -> void:
var offen: Array = []
for p in probleme_von(active_mission):
if not problem_ueberwunden(active_mission, str(p)):
offen.append(str(p))
if offen.is_empty():
situation_pause = SITUATION_PAUSE
return
var problem: String = str(offen[randi() % offen.size()])
var moeglich := Probleme.situationen_von(problem)
if moeglich.is_empty():
situation_pause = SITUATION_PAUSE
return
situation = {
"mensch": active_mission,
"key": str(moeglich[randi() % moeglich.size()]),
"problem": problem,
"rest": SITUATION_DAUER,
}
state_changed.emit()
## Dabeisein zeigt, welches Problem dahintersteckt.
func situation_sehen() -> void:
if not situation_laeuft():
return
var id := str(situation["mensch"])
var p := situation_problem()
if problem_bekannt(id, p):
return
if not probleme_bekannt.has(id):
probleme_bekannt[id] = {}
probleme_bekannt[id][p] = true
notified.emit("Dahinter steckt: %s — %s" %
[Probleme.name_von(p), Probleme.LISTE[p]["kurz"]], Color(0.8, 0.95, 1))
state_changed.emit()
## Eine Technik im Moment anwenden. Passt sie zum Problem, ist die Situation
## vorbei; oft genug, und das Problem kommt nicht wieder.
func situation_anwenden(tech_id: String) -> Dictionary:
var res := {"ok": false, "grund": "", "treffer": false, "ueberwunden": false}
if not situation_laeuft():
res["grund"] = "Gerade ist kein Moment offen."
return res
if not known.has(tech_id):
res["grund"] = "Diese Technik kennst du nicht."
return res
if not bereit(tech_id):
res["grund"] = "%s braucht noch %.0f s." % [TechDB.by_id(tech_id)["name"],
cooldown_rest(tech_id)]
return res
var id := str(situation["mensch"])
var problem := situation_problem()
cooldown[tech_id] = TECHNIK_COOLDOWN
res["ok"] = true
if not Probleme.hilft(tech_id, problem):
add_xp(tech_id, 1)
notified.emit("%s greift hier nicht." % TechDB.by_id(tech_id)["name"],
Color(1, 0.7, 0.5))
state_changed.emit()
return res
res["treffer"] = true
add_xp(tech_id, 2)
var schluessel := "%s:%s" % [id, problem]
problem_stand[schluessel] = problem_fortschritt(id, problem) + 1
situation_sehen()
situation = {}
situation_pause = SITUATION_PAUSE
if id == active_mission:
progress[id] = minf(mission_progress(id) + SITUATION_GEWINN, MISSION_ZIEL)
notified.emit("%s trägt durch den Moment. (+%d %%)" %
[TechDB.by_id(tech_id)["name"], int(SITUATION_GEWINN)], Color(0.6, 1, 0.7))
if problem_fortschritt(id, problem) >= PROBLEM_UEBERWINDEN:
if not ueberwunden.has(id):
ueberwunden[id] = {}
ueberwunden[id][problem] = true
res["ueberwunden"] = true
notified.emit("%s ist überwunden — dieser Moment kommt nicht wieder." %
Probleme.name_von(problem), Color(1, 0.85, 0.4))
state_changed.emit()
return res
# --------------------------------------------------- Erreichbarkeit
## Schlafende erreicht niemand.