This commit is contained in:
Team3
2026-08-30 19:56:47 +02:00
parent a46eba4145
commit f936dd2b2a
13 changed files with 1681 additions and 444 deletions

View File

@@ -1,25 +1,23 @@
class_name DreamDB
## Die Traumwelt: ein Dorf. Jedes Wesen hat ein Haus und einen Tagesablauf.
## Die Traumwelt: ein Dorf, das mit jedem erfüllten Traum wächst.
## Fest sind nur Hörsaal, Dorfplatz und Tor zur Erde. Jedes Haus und sein
## Bewohner werden erzeugt — der Reihe nach, immer weiter nach außen.
static var PLACES: Dictionary = {
"haus_ailen": {
"name": "Ailens Webstube", "pos": [-28.0, -22.0], "size": [12.0, 10.0],
"dir": "back", "color": Color(0.72, 0.62, 0.92),
},
"haus_morr": {
"name": "Morrs Kammer", "pos": [28.0, -22.0], "size": [12.0, 10.0],
"dir": "back", "color": Color(0.58, 0.72, 0.90),
},
"haus_ivo": {
"name": "Ivos Unterstand", "pos": [-28.0, 22.0], "size": [12.0, 10.0],
"dir": "forward", "color": Color(0.88, 0.66, 0.80),
},
"haus_sela": {
"name": "Selas Turmstube", "pos": [28.0, 22.0], "size": [12.0, 10.0],
"dir": "forward", "color": Color(0.62, 0.82, 0.88),
const HAEUSER_JE_RING := 6
const RING_ERSTER := 30.0
const RING_ABSTAND := 24.0
## Häuser sitzen auf Achtelrichtungen. Die Achsen 0 (Hörsaal) und 4 (Tor)
## bleiben frei, damit der Weg vom Dorfplatz zu beiden offen bleibt.
const SLOTS := [1, 2, 3, 5, 6, 7]
static var FEST: Dictionary = {
"hoersaal": {
"name": "Hörsaal der Wege", "pos": [0.0, 34.0], "size": [16.0, 12.0],
"dir": "forward", "color": Color(0.66, 0.72, 0.94),
},
"lichtung": {
"name": "Die Lichtung", "pos": [0.0, 2.0], "size": [0.0, 0.0],
"name": "Der Dorfplatz", "pos": [0.0, 2.0], "size": [0.0, 0.0],
"dir": "none", "color": Color(0.60, 0.50, 0.85),
},
"tor": {
@@ -28,73 +26,145 @@ static var PLACES: Dictionary = {
},
}
static var LIST: Array = [
{
"id": "ailen",
"name": "Ailen",
"rolle": "Traumweberin",
"leuchtet": true,
"farbe": Color(0.78, 0.55, 0.95),
"routine": [
[0, "haus_ailen", "webt"],
[6, "lichtung", "ruht"],
[8, "haus_ailen", "webt"],
[14, "lichtung", "singt"],
[16, "haus_ailen", "webt"],
[20, "haus_ailen", "traeumt"],
],
},
{
"id": "morr",
"name": "Morr",
"rolle": "Erinnerungssammler",
"leuchtet": true,
"farbe": Color(0.45, 0.70, 0.95),
"routine": [
[0, "haus_morr", "traeumt"],
[5, "lichtung", "sammelt"],
[9, "haus_morr", "sortiert"],
[15, "lichtung", "sammelt"],
[19, "haus_morr", "sortiert"],
[22, "haus_morr", "traeumt"],
],
},
{
"id": "ivo",
"name": "Ivo",
"rolle": "Bote",
"leuchtet": true,
"farbe": Color(0.95, 0.60, 0.75),
"routine": [
[0, "haus_ivo", "traeumt"],
[4, "tor", "beobachtet"],
[8, "lichtung", "wandert"],
[10, "haus_ivo", "ruht"],
[13, "tor", "beobachtet"],
[18, "lichtung", "singt"],
[21, "haus_ivo", "traeumt"],
],
},
{
"id": "sela",
"name": "Sela",
"rolle": "Wächterin des Tors",
"leuchtet": true,
"farbe": Color(0.55, 0.95, 0.90),
"routine": [
[0, "tor", "wacht"],
[7, "lichtung", "ruht"],
[9, "tor", "wacht"],
[17, "haus_sela", "ruht"],
[19, "lichtung", "singt"],
[21, "haus_sela", "traeumt"],
],
},
## Wird von erzeuge() gefüllt und wächst mit dem Dorf.
static var PLACES: Dictionary = FEST.duplicate(true)
static var LIST: Array = []
static var FESTE_NAMEN: Array = ["Ailen", "Morr", "Ivo", "Sela"]
static var FESTE_ROLLEN: Array = ["Traumweberin", "Erinnerungssammler", "Bote",
"Wächterin des Tors"]
static var SILBE_A: Array = ["Nu", "Ta", "Es", "Wre", "O", "Ma", "Si", "Te"]
static var SILBE_B: Array = ["un", "lia", "kar", "n", "vin", "lu", "rin", "nne"]
static var ROLLEN: Array = ["Lichtgießer", "Kartenzeichnerin", "Schwellenhüter",
"Fadensucherin", "Stillenzähler", "Wegbereiterin", "Klangsammler", "Nachtgärtnerin"]
## Vier Tagesabläufe, alle mit reichlich Zeit zwischen den Stationen —
## auch ein Haus am äußeren Ring ist so bequem zu erreichen.
static var ABLAEUFE: Array = [
[[0, "haus", "traeumt"], [6, "lichtung", "ruht"], [10, "haus", "webt"],
[14, "lichtung", "singt"], [18, "haus", "sortiert"], [21, "haus", "traeumt"]],
[[0, "haus", "traeumt"], [6, "lichtung", "sammelt"], [10, "haus", "sortiert"],
[15, "tor", "beobachtet"], [19, "haus", "webt"], [21, "haus", "traeumt"]],
[[0, "tor", "wacht"], [7, "lichtung", "ruht"], [11, "haus", "sortiert"],
[15, "tor", "wacht"], [19, "lichtung", "singt"], [21, "haus", "traeumt"]],
[[0, "haus", "traeumt"], [4, "tor", "beobachtet"], [8, "lichtung", "wandert"],
[12, "haus", "ruht"], [16, "lichtung", "singt"], [20, "haus", "traeumt"]],
]
static func haus_key(i: int) -> String:
return "haus_%d" % i
## Baut Orte und Bewohner für ein Dorf mit so vielen Häusern neu auf.
static func erzeuge(haeuser: int) -> void:
PLACES = FEST.duplicate(true)
LIST = []
for i in range(maxi(haeuser, 0)):
PLACES[haus_key(i)] = _haus(i)
LIST.append(_bewohner(i))
## Wie weit reicht das Dorf hinaus?
static func aeusserster_ring(haeuser: int) -> float:
if haeuser <= 0:
return 0.0
var ring := (haeuser - 1) / HAEUSER_JE_RING
return RING_ERSTER + float(ring) * RING_ABSTAND
static func _haus(i: int) -> Dictionary:
var ring := i / HAEUSER_JE_RING
var winkel := float(SLOTS[i % HAEUSER_JE_RING]) * TAU / 8.0
var r := RING_ERSTER + float(ring) * RING_ABSTAND
var x := sin(winkel) * r
var z := cos(winkel) * r
var breite := 12.0 + float(i % 2) * 2.0
var tiefe := 10.0 + float(i % 3)
return {
"name": "%s Haus" % _besitz(_name(i)),
"pos": [x, z],
"size": [breite, tiefe],
"dir": _tuer_zur_mitte(x, z),
"color": Color.from_hsv(fmod(0.60 + float(i) * 0.137, 1.0), 0.34, 0.86),
}
## Die Tür zeigt zur Dorfmitte — auf die Seite, die ihr am nächsten liegt.
static func _tuer_zur_mitte(x: float, z: float) -> String:
if absf(x) > absf(z):
return "left" if x > 0.0 else "right"
return "forward" if z > 0.0 else "back"
static func _bewohner(i: int) -> Dictionary:
var haus := haus_key(i)
var ablauf: Array = []
for e in ABLAEUFE[i % ABLAEUFE.size()]:
ablauf.append([e[0], haus if e[1] == "haus" else e[1], e[2]])
return {
"id": "wesen_%d" % i,
"name": _name(i),
"rolle": _rolle(i),
"haus": haus,
"leuchtet": true,
"farbe": Color.from_hsv(fmod(0.72 + float(i) * 0.161, 1.0), 0.55, 0.95),
"routine": ablauf,
}
static func _name(i: int) -> String:
if i < FESTE_NAMEN.size():
return str(FESTE_NAMEN[i])
var j := i - FESTE_NAMEN.size()
return str(SILBE_A[j % SILBE_A.size()]) + str(SILBE_B[(j / SILBE_A.size()) % SILBE_B.size()])
## Genitiv: "Ailens", aber "Morrs" und "Esas'" — Apostroph nur nach Zischlaut.
static func _besitz(n: String) -> String:
var letzter := n.substr(n.length() - 1).to_lower()
return n + "'" if ["s", "z", "x", "ß"].has(letzter) else n + "s"
static func _rolle(i: int) -> String:
if i < FESTE_ROLLEN.size():
return str(FESTE_ROLLEN[i])
return str(ROLLEN[(i - FESTE_ROLLEN.size()) % ROLLEN.size()])
static func by_id(id: String) -> Dictionary:
for w in LIST:
if w["id"] == id:
return w
return {}
# ------------------------------------------------------------------ Lehrorte
## Der Hörsaal lehrt den ersten Weg. Jedes Haus bringt einen weiteren mit.
static func techniken_von(place_key: String) -> Array:
var nr := -1
if place_key == "hoersaal":
nr = 0
elif place_key.begins_with("haus_"):
nr = int(place_key.substr(5)) + 1
if nr < 0 or nr >= TechDB.LIST.size():
return []
return [TechDB.LIST[nr]["id"]]
## An welchem Ort wird diese Technik gelehrt? "" wenn nirgends.
static func ort_von_technik(tech_id: String) -> String:
for i in range(TechDB.LIST.size()):
if TechDB.LIST[i]["id"] == tech_id:
return "hoersaal" if i == 0 else haus_key(i - 1)
return ""
## Alle Orte, an denen im aktuellen Dorf gelehrt wird.
static func lehrorte() -> Array:
var out: Array = ["hoersaal"]
for i in range(LIST.size()):
if not techniken_von(haus_key(i)).is_empty():
out.append(haus_key(i))
return out