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

@@ -148,6 +148,8 @@ func beschriftung() -> String:
if data.has("rolle"):
s += ", " + str(data["rolle"])
s += "\n" + Orte.text(activity)
if mit_mission and Game.situation_bei(str(data["id"])):
s += "\n» %s «" % Probleme.SITUATIONEN[Game.situation["key"]]["name"]
if resist_left > 0.0:
s += " (macht dicht)"
if mit_mission:

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.

View File

@@ -391,6 +391,18 @@ static func _anker_setzen() -> void:
ANKER[key] = int(NETZ.andocken(tuer)["knoten"])
## Was diesen Menschen nicht im Tagesablauf aufhält, sondern in Momenten.
## Ein bis zwei Probleme -- die zweite Ebene neben den Ursachen.
static func probleme_von(i: int) -> Array:
var alle: Array = Probleme.LISTE.keys()
var out: Array = [str(alle[i % alle.size()])]
if i % 2 == 1:
var zweites: String = str(alle[(i + 2) % alle.size()])
if zweites != out[0]:
out.append(zweites)
return out
## Woran der Traum dieses Menschen scheitert. Zwei bis drei Ursachen, nie alle.
## Die erste hängt am Weg gleicher Nummer -- so ist der neueste Mensch immer
## mit dem neuesten Weg anzugehen.
@@ -462,6 +474,7 @@ static func _mensch(i: int) -> Dictionary:
"problem": str(anliegen["problem"]),
"tags": (anliegen["tags"] as Array).duplicate(),
"ursachen": ursachen_von(i),
"probleme": probleme_von(i),
"mission": true,
"heim": heim,
"farbe": Color.from_hsv(fmod(0.02 + float(i) * 0.191, 1.0), 0.5, 0.8),
@@ -495,15 +508,6 @@ static func _nachname(i: int) -> String:
return str(NACHNAMEN[(i / VORNAMEN.size() + i) % NACHNAMEN.size()])
## Die Tätigkeiten eines Menschen in der Reihenfolge seines Tages, ohne Dopplung.
static func aktivitaeten(id: String) -> Array:
var out: Array = []
for e in by_id(id)["routine"]:
if not out.has(e[2]):
out.append(e[2])
return out
static func by_id(id: String) -> Dictionary:
for h in LIST:
if h["id"] == id:

View File

@@ -73,6 +73,7 @@ func _process(delta: float) -> void:
ui.setze_hinweis("")
return
Game.notiz_sperre = maxf(0.0, Game.notiz_sperre - delta)
Game.situationen_ticken(dt, auf_erde and not Game.schlaeft_ziel())
_fokus_suchen()
_dabeisein()
_hinweis_setzen()
@@ -131,6 +132,9 @@ func _notiz_hinweis(mensch: Bewohner) -> String:
var tat := Orte.text(mensch.activity)
if str(mensch.data["id"]) != Game.active_mission:
return tat
if Game.situation_bei(str(mensch.data["id"])):
return "%s · [E] jetzt eine Technik" % \
Probleme.SITUATIONEN[Game.situation["key"]]["name"]
if Game.notiz_sperre > 0.0:
return "%s (%.0f s)" % [tat, Game.notiz_sperre]
if Game.erkannt(str(mensch.data["id"]), int(mensch.slot)):
@@ -181,6 +185,8 @@ func _dabeisein() -> void:
var id: String = str(_fokus_mensch.data["id"])
if id == Game.active_mission:
Game.sehen(id, int(_fokus_mensch.slot))
if Game.situation_bei(id):
Game.situation_sehen()
## Den Moment benennen: hier läuft etwas schief. Das ist der Kern des
@@ -227,7 +233,11 @@ func _verfolgen() -> void:
func _interagieren() -> void:
if _fokus_mensch != null:
ui.anwenden_panel(_fokus_mensch)
# Der offene Moment geht vor: er ist gleich wieder vorbei
if Game.situation_bei(str(_fokus_mensch.data["id"])):
ui.situation_panel(_fokus_mensch)
else:
ui.anwenden_panel(_fokus_mensch)
return
if _fokus == null:
return

102
scripts/probleme.gd Normal file
View File

@@ -0,0 +1,102 @@
class_name Probleme
## Die zweite Ebene: was einen Menschen nicht im Tagesablauf aufhält, sondern
## in einzelnen Momenten. Eine Gewohnheit hat einen Platz im Tag -- ein
## psychisches Problem hat keinen. Es zeigt sich in Situationen, und die
## kommen, wann sie wollen.
##
## Darum die andere Mechanik: Gewohnheiten pflanzt man ein und sie laufen ohne
## dich weiter. Bei einer Situation musst du dabei sein und im Moment die
## Technik wählen, die zu diesem Problem passt.
static var LISTE: Dictionary = {
"angst": {
"name": "Angst", "kurz": "der Körper macht dicht, bevor der Kopf mitredet",
},
"selbstzweifel": {
"name": "Selbstzweifel", "kurz": "die innere Stimme redet es klein",
},
"stress": {
"name": "Stress", "kurz": "alles gleichzeitig, nichts zu Ende",
},
"ueberforderung": {
"name": "Überforderung", "kurz": "der Berg ist zu groß zum Ansehen",
},
"erschoepfung": {
"name": "Erschöpfung", "kurz": "der Akku ist leer, bevor der Tag anfängt",
},
"einsamkeit": {
"name": "Einsamkeit", "kurz": "hängt allein an dem, was zu zweit ginge",
},
}
## Situationen: was im Moment sichtbar wird. Jede gehört zu einem Problem.
static var SITUATIONEN: Dictionary = {
"blackout": {
"name": "wird starr", "was": "Ihr wird schwarz vor Augen.",
"problem": "angst",
},
"aufschieben_angst": {
"name": "meldet sich ab", "was": "Sie sagt den Termin wieder ab.",
"problem": "angst",
},
"kleinreden": {
"name": "redet es klein", "was": "»Das kann doch jeder besser.«",
"problem": "selbstzweifel",
},
"vergleich": {
"name": "vergleicht sich", "was": "Sie sieht, was andere schaffen.",
"problem": "selbstzweifel",
},
"alles_gleichzeitig": {
"name": "fängt drei Dinge an", "was": "Alles gleichzeitig, nichts zu Ende.",
"problem": "stress",
},
"noch_ein_ja": {
"name": "sagt schon wieder ja", "was": "Noch eine Bitte, noch ein Ja.",
"problem": "stress",
},
"erstarrt": {
"name": "erstarrt vor dem Berg", "was": "Sie sieht die Aufgabe und macht nichts.",
"problem": "ueberforderung",
},
"ausgebrannt": {
"name": "sackt zusammen", "was": "Sie sitzt da und starrt.",
"problem": "erschoepfung",
},
"allein": {
"name": "hängt allein fest", "was": "Sie kommt nicht weiter und fragt niemanden.",
"problem": "einsamkeit",
},
}
static func problem_da(schluessel: String) -> bool:
return LISTE.has(schluessel)
static func name_von(schluessel: String) -> String:
return str(LISTE[schluessel]["name"]) if LISTE.has(schluessel) else schluessel
## Alle Situationen, in denen sich dieses Problem zeigt.
static func situationen_von(problem: String) -> Array:
var out: Array = []
for key in SITUATIONEN:
if SITUATIONEN[key]["problem"] == problem:
out.append(key)
return out
## Techniken, die gegen dieses Problem etwas ausrichten -- erkennbar am Feld
## `tags` der Technik.
static func techniken_gegen(problem: String) -> Array:
var out: Array = []
for t in TechDB.LIST:
if (t["tags"] as Array).has(problem):
out.append(str(t["id"]))
return out
static func hilft(tech_id: String, problem: String) -> bool:
var t := TechDB.by_id(tech_id)
return not t.is_empty() and (t["tags"] as Array).has(problem)

1
scripts/probleme.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://cchkx60v1a0e2

View File

@@ -14,7 +14,6 @@ static var LIST: Array = [
"belohnung": "erfolg",
"ersatz": "arbeitet in Blöcken",
"tags": ["prokrastination", "fokus"],
"momente": ["arbeitet", "zoegert"],
"farbe": Color(0.95, 0.45, 0.30),
},
{
@@ -28,7 +27,6 @@ static var LIST: Array = [
"belohnung": "erfolg",
"ersatz": "fängt zwei Minuten an",
"tags": ["prokrastination", "ueberforderung"],
"momente": ["zoegert", "aufraeumen", "arbeitet"],
"farbe": Color(0.98, 0.72, 0.25),
},
{
@@ -42,7 +40,6 @@ static var LIST: Array = [
"belohnung": "ordnung",
"ersatz": "folgt dem Wenn-Dann-Plan",
"tags": ["gewohnheit", "prokrastination"],
"momente": ["morgenroutine", "pause"],
"farbe": Color(0.45, 0.80, 0.55),
},
{
@@ -56,7 +53,6 @@ static var LIST: Array = [
"belohnung": "ordnung",
"ersatz": "hängt es an die Routine",
"tags": ["gewohnheit"],
"momente": ["morgenroutine", "essen", "abendroutine"],
"farbe": Color(0.40, 0.70, 0.85),
},
{
@@ -70,7 +66,6 @@ static var LIST: Array = [
"belohnung": "ordnung",
"ersatz": "zerlegt die Aufgabe",
"tags": ["ueberforderung", "prokrastination", "ziel"],
"momente": ["gruebelt", "arbeitet"],
"farbe": Color(0.75, 0.55, 0.95),
},
{
@@ -84,7 +79,6 @@ static var LIST: Array = [
"belohnung": "",
"ersatz": "hat es sich leicht gemacht",
"tags": ["ablenkung", "gewohnheit"],
"momente": ["aufraeumen", "arbeitet", "ruht"],
"farbe": Color(0.55, 0.85, 0.40),
},
{
@@ -98,7 +92,6 @@ static var LIST: Array = [
"belohnung": "einordnung",
"ersatz": "deutet den Gedanken um",
"tags": ["selbstzweifel", "angst"],
"momente": ["gruebelt", "ruht", "angespannt"],
"farbe": Color(0.95, 0.55, 0.75),
},
{
@@ -112,7 +105,6 @@ static var LIST: Array = [
"belohnung": "abschalten",
"ersatz": "atmet sich ruhig",
"tags": ["angst", "stress"],
"momente": ["angespannt", "wartet", "pause"],
"farbe": Color(0.40, 0.85, 0.95),
},
{
@@ -126,7 +118,6 @@ static var LIST: Array = [
"belohnung": "verbundenheit",
"ersatz": "ist freundlich mit sich",
"tags": ["selbstzweifel", "rueckschlag"],
"momente": ["gruebelt", "ruht", "angespannt"],
"farbe": Color(1.0, 0.80, 0.60),
},
{
@@ -140,7 +131,6 @@ static var LIST: Array = [
"belohnung": "zeit_fuer_sich",
"ersatz": "hält das Schlaffenster",
"tags": ["erschoepfung", "gesundheit"],
"momente": ["abendroutine", "muede", "ruht"],
"farbe": Color(0.45, 0.50, 0.90),
},
{
@@ -154,7 +144,6 @@ static var LIST: Array = [
"belohnung": "anschluss",
"ersatz": "bittet um Hilfe",
"tags": ["einsamkeit", "ueberforderung"],
"momente": ["wartet", "pause", "unterwegs"],
"farbe": Color(0.90, 0.90, 0.45),
},
{
@@ -168,7 +157,6 @@ static var LIST: Array = [
"belohnung": "anerkennung",
"ersatz": "sagt Nein mit Alternative",
"tags": ["stress", "grenzen"],
"momente": ["arbeitet", "angespannt", "unterwegs"],
"farbe": Color(0.85, 0.35, 0.45),
},
]

View File

@@ -16,6 +16,8 @@ var _ablauf: HBoxContainer
var _ablauf_titel: Label
var _ablauf_jetzt: Label
var _ablauf_grund: ColorRect
var _probleme: RichTextLabel
var _probleme_grund: ColorRect
var _zellen: Array = []
var _ticks: Array = []
var _dim: ColorRect
@@ -27,7 +29,6 @@ var _apply_human: Node3D
var _journal_seite := "techniken"
var _scroll_wunsch := 0
var _scroll_frames := 0
var _on_travel: Callable
func _ready() -> void:
@@ -54,6 +55,7 @@ func _baue_hud() -> void:
add_child(_hud)
_baue_ablauf()
_baue_probleme()
var steuerung := Label.new()
steuerung.text = "WASD Bewegen · Maus Umsehen · E Interagieren · F Folgen · " + \
@@ -151,16 +153,17 @@ func _baue_ablauf() -> void:
## Farbe je Stunde: unbekannt, gesehen, ungeklärt, benannt, gebaut.
func _ablauf_farbe(human_id: String, nr: int) -> Color:
if not Game.gesehen_slot(human_id, nr):
return Color(0.22, 0.23, 0.30)
if not Game.system_in(human_id, nr).is_empty():
return Color(0.44, 0.78, 0.50)
var grund := Game.slot_grund(human_id, nr)
if Ursachen.ist_blocker(grund):
return Color(0.85, 0.66, 0.32) if not Game.erkannt(human_id, nr) \
else Color(0.84, 0.42, 0.35)
if grund == "schlaeft":
return Color(0.30, 0.33, 0.44)
match Game.slot_zustand(human_id, nr):
Game.Stunde.UNBEKANNT:
return Color(0.22, 0.23, 0.30)
Game.Stunde.GEBAUT:
return Color(0.44, 0.78, 0.50)
Game.Stunde.UNGEKLAERT:
return Color(0.85, 0.66, 0.32)
Game.Stunde.BENANNT:
return Color(0.84, 0.42, 0.35)
Game.Stunde.SCHLAF:
return Color(0.30, 0.33, 0.44)
return Color(0.46, 0.50, 0.62)
@@ -193,6 +196,60 @@ func _ablauf_aktualisieren() -> void:
_ablauf_jetzt.text = "%02d Uhr %s" % [jetzt, _stunden_text(id, nr_jetzt)]
## Die zweite Ebene im HUD: bekannte Probleme und der offene Moment.
## Bewusst anders gezeichnet als der Tagesstreifen -- sie hängt nicht an Stunden.
func _baue_probleme() -> void:
_probleme_grund = ColorRect.new()
_probleme_grund.color = Color(0, 0, 0, 0.42)
_probleme_grund.set_anchors_preset(Control.PRESET_TOP_LEFT)
_probleme_grund.position = Vector2(ABLAUF_X - 8.0, ABLAUF_Y + 88.0)
_probleme_grund.custom_minimum_size = Vector2(414.0, 74.0)
_probleme_grund.size = _probleme_grund.custom_minimum_size
_probleme_grund.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(_probleme_grund)
_probleme = RichTextLabel.new()
_probleme.bbcode_enabled = true
_probleme.fit_content = true
_probleme.scroll_active = false
_probleme.set_anchors_preset(Control.PRESET_TOP_LEFT)
_probleme.position = Vector2(ABLAUF_X, ABLAUF_Y + 94.0)
_probleme.custom_minimum_size = Vector2(400, 64)
_probleme.size = Vector2(400, 64)
_probleme.mouse_filter = Control.MOUSE_FILTER_IGNORE
_probleme.add_theme_font_size_override("normal_font_size", 14)
_probleme.add_theme_font_size_override("bold_font_size", 14)
add_child(_probleme)
func _probleme_aktualisieren() -> void:
var id := Game.active_mission
var an := id != ""
_probleme.visible = an
_probleme_grund.visible = an
if not an:
return
var zeilen: Array = []
if Game.situation_laeuft() and Game.situation_bei(id):
var s: Dictionary = Probleme.SITUATIONEN[Game.situation["key"]]
zeilen.append("[color=#ffcc66][b]Jetzt: %s[/b][/color] %s [b]%.0f s[/b]" %
[s["name"], s["was"], float(Game.situation["rest"])])
else:
zeilen.append("[color=#8e93a8]Ihre Momente[/color]")
var bekannt: Array = []
for p in Game.probleme_von(id):
var key := str(p)
if not Game.problem_bekannt(id, key):
bekannt.append("[color=#55596b]?[/color]")
elif Game.problem_ueberwunden(id, key):
bekannt.append("[color=#88ff99]%s ✓[/color]" % Probleme.name_von(key))
else:
bekannt.append("[color=#ffb0a0]%s %d/%d[/color]" % [Probleme.name_von(key),
Game.problem_fortschritt(id, key), Game.PROBLEM_UEBERWINDEN])
zeilen.append(" · ".join(bekannt))
_probleme.text = "\n".join(zeilen)
func _baue_panel() -> void:
_dim = ColorRect.new()
_dim.color = Color(0, 0, 0, 0.62)
@@ -278,6 +335,7 @@ func _hud_aktualisieren() -> void:
zeilen.append("[color=#aaaaaa]Keine Mission. Schwarzes Brett am Dorfplatz.[/color]")
_hud.text = "\n".join(zeilen)
_ablauf_aktualisieren()
_probleme_aktualisieren()
func setze_hinweis(text: String) -> void:
@@ -531,18 +589,19 @@ func _tagesablauf(human_id: String) -> void:
func _stunden_text(human_id: String, nr: int) -> String:
if not Game.gesehen_slot(human_id, nr):
return "—"
var sys := Game.system_in(human_id, nr)
if not sys.is_empty():
return "%s ← %s" % [Game.slot_aktivitaet(human_id, nr),
TechDB.by_id(str(sys["tech"]))["name"]]
var grund := Game.slot_grund(human_id, nr)
if not Game.erkannt(human_id, nr):
return "?"
if Ursachen.ist_blocker(grund):
return "%s (%s)" % [Ursachen.BLOCKER[grund]["name"],
Ursachen.LISTE[Ursachen.BLOCKER[grund]["ursache"]]["name"]]
match Game.slot_zustand(human_id, nr):
Game.Stunde.UNBEKANNT:
return "—"
Game.Stunde.GEBAUT:
var sys := Game.system_in(human_id, nr)
return "%s ← %s" % [Game.slot_aktivitaet(human_id, nr),
TechDB.by_id(str(sys["tech"]))["name"]]
Game.Stunde.UNGEKLAERT:
return "?"
Game.Stunde.BENANNT:
return "%s (%s)" % [Ursachen.BLOCKER[grund]["name"],
Ursachen.LISTE[Ursachen.BLOCKER[grund]["ursache"]]["name"]]
return Orte.text(grund)
@@ -554,6 +613,49 @@ func _stunden_zeile(human_id: String, nr: int, von: int, bis: int, text: String)
func() -> void: slot_panel(human_id, nr), offen)
## Der offene Moment: hier zählt, welche Technik zu diesem Problem passt.
func situation_panel(mensch: Node3D) -> void:
_apply_human = mensch
var id: String = str(mensch.data["id"])
if not Game.situation_bei(id):
anwenden_panel(mensch)
return
var s: Dictionary = Probleme.SITUATIONEN[Game.situation["key"]]
var problem := Game.situation_problem()
_leeren("%s — %s" % [mensch.data["name"], s["name"]])
_text("[i]%s[/i]" % s["was"], 16)
if Game.problem_bekannt(id, problem):
_text("Dahinter steckt [b]%s[/b] — %s." %
[Probleme.name_von(problem), Probleme.LISTE[problem]["kurz"]], 15)
_text("[color=#aaaaaa]Überwunden nach %d von %d Malen.[/color]" %
[Game.problem_fortschritt(id, problem), Game.PROBLEM_UEBERWINDEN], 14)
else:
_text("[color=#ffcc66]Was dahintersteckt, weißt du noch nicht.[/color]", 15)
_text("[color=#aaaaaa]Noch %.0f Sekunden. Solange kommt ihr Traum nicht voran.[/color]" %
float(Game.situation["rest"]), 14)
_trenner()
if Game.known.is_empty():
_text("[color=#ffcc66]Du kennst keine Technik.[/color]", 16)
_zeigen("situation")
return
for tech_id in TechDB.ids():
if not Game.knows(tech_id):
continue
var t := TechDB.by_id(tech_id)
var wofuer: Array = []
for tag in t["tags"]:
wofuer.append(Probleme.name_von(str(tag)))
_text("[b]%s[/b] · Stufe %d\n[color=#cccccc]%s[/color]\n[color=#9fb6ff]Hilft bei:[/color] %s" %
[t["name"], Game.skill_of(tech_id), t["wann"], ", ".join(wofuer)], 15)
var frei := Game.bereit(tech_id)
var text := "Jetzt anwenden" if frei else "Noch %.0f s" % Game.cooldown_rest(tech_id)
_knopf(text, func() -> void:
Game.situation_anwenden(tech_id)
schliessen(), frei)
_trenner()
_zeigen("situation")
## Was soll in diesem Slot stehen?
func slot_panel(human_id: String, nr: int) -> void:
var h := HumanDB.by_id(human_id)
@@ -664,13 +766,14 @@ func brett_panel() -> void:
_text("Ausgehängt wird nur, wem du mit dem, was du kannst, auch helfen kannst. " +
"Das Tor zur Erde öffnet sich nur mit einer Mission.", 15)
_trenner()
var offen := Game.offene_missionen()
var gezeigt := 0
var verdeckt := 0
for h in HumanDB.LIST:
var id: String = h["id"]
if Game.completed.has(id):
continue
if Game.active_mission != id and not Game.machbar(id):
if not offen.has(id):
verdeckt += 1
continue
gezeigt += 1

View File

@@ -13,27 +13,22 @@ class_name Ursachen
static var LISTE: Dictionary = {
"anfang": {
"name": "Kein Anfang", "kurz": "kommt nie in Gang",
"symptom": "Sie setzt sich hin und tut dann etwas anderes.",
"faktor": 0.30,
},
"zeit": {
"name": "Keine Zeit", "kurz": "der Tag ist voll",
"symptom": "Der Tag ist voll mit dem, was andere wollen.",
"faktor": 0.30,
},
"kraft": {
"name": "Keine Kraft", "kurz": "abends ist nichts mehr übrig",
"symptom": "Am Abend reicht es nur noch für Berieselung.",
"faktor": 0.40,
},
"halt": {
"name": "Kein Halt", "kurz": "fängt an und hört wieder auf",
"symptom": "Angefangen wird oft, drangeblieben selten.",
"faktor": 0.50,
},
"grund": {
"name": "Kein Grund", "kurz": "glaubt nicht mehr daran",
"symptom": "Sie redet sich das Vorhaben selbst klein.",
"faktor": 0.40,
},
}