171 lines
5.6 KiB
GDScript
171 lines
5.6 KiB
GDScript
class_name DreamDB
|
|
## 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.
|
|
|
|
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": "Der Dorfplatz", "pos": [0.0, 2.0], "size": [0.0, 0.0],
|
|
"dir": "none", "color": Color(0.60, 0.50, 0.85),
|
|
},
|
|
"tor": {
|
|
"name": "Tor zur Erde", "pos": [0.0, -34.0], "size": [0.0, 0.0],
|
|
"dir": "none", "color": Color(0.50, 0.80, 1.0),
|
|
},
|
|
}
|
|
|
|
## 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
|