260 lines
8.6 KiB
GDScript
260 lines
8.6 KiB
GDScript
class_name Orte
|
|
## Gemeinsame Geometrie für beide Welten: Orte, Türen, Wege, Tätigkeiten.
|
|
|
|
static var DIR_VEC: Dictionary = {
|
|
"back": Vector3(0, 0, 1),
|
|
"forward": Vector3(0, 0, -1),
|
|
"left": Vector3(-1, 0, 0),
|
|
"right": Vector3(1, 0, 0),
|
|
"none": Vector3(0, 0, 0),
|
|
}
|
|
|
|
static var ACTIVITY_TEXT: Dictionary = {
|
|
# Erde
|
|
"schlaeft": "schläft",
|
|
"morgenroutine": "Morgenroutine",
|
|
"arbeitet": "arbeitet",
|
|
"pause": "macht Pause",
|
|
"essen": "isst",
|
|
"gruebelt": "grübelt",
|
|
"ruht": "ruht sich aus",
|
|
"angespannt": "ist angespannt",
|
|
"abendroutine": "Abendroutine",
|
|
"aufraeumen": "räumt auf",
|
|
"wartet": "wartet",
|
|
"muede": "ist müde",
|
|
"unterwegs": "geht spazieren",
|
|
"zoegert": "zögert",
|
|
# Traumwelt
|
|
"webt": "webt Traumfäden",
|
|
"sammelt": "sammelt Erinnerungen",
|
|
"sortiert": "sortiert, was verloren ging",
|
|
"beobachtet": "schaut zur Erde hinunter",
|
|
"wacht": "hält Wache am Tor",
|
|
"singt": "singt",
|
|
"wandert": "wandert über die Insel",
|
|
"traeumt": "träumt",
|
|
}
|
|
|
|
|
|
## Blocker tragen ihren Namen im Ursachen-Katalog, alles andere hier.
|
|
static func text(a: String) -> String:
|
|
if Ursachen.ist_blocker(a):
|
|
return str(Ursachen.BLOCKER[a]["name"])
|
|
return str(ACTIVITY_TEXT.get(a, a))
|
|
|
|
|
|
static func kennt(a: String) -> bool:
|
|
return ACTIVITY_TEXT.has(a) or Ursachen.ist_blocker(a)
|
|
|
|
|
|
const ETAGE := 3.0 # Höhe eines Stockwerks
|
|
|
|
|
|
static func etagen(places: Dictionary, key: String) -> int:
|
|
return maxi(1, int(places[key].get("etagen", 1)))
|
|
|
|
|
|
static func hoehe(e: int) -> float:
|
|
return float(e) * ETAGE
|
|
|
|
|
|
const TREPPE_LAUF := 6.0 # Abstand der Wendepodeste entlang der Wand
|
|
const TREPPE_TIEFE := 4.4 # Streifen an der Treppenwand: zwei Läufe nebeneinander
|
|
const PODEST := 0.9 # halbe Podestlänge
|
|
|
|
## Rahmen des Treppenhauses: an der längeren Wand, die nicht die Türwand ist.
|
|
## n zeigt von der Mitte zur Treppenwand, a läuft an ihr entlang.
|
|
static func treppen_rahmen(places: Dictionary, key: String) -> Dictionary:
|
|
var pl: Dictionary = places[key]
|
|
var c := center(places, key)
|
|
var d: Vector3 = DIR_VEC[pl["dir"]]
|
|
var size: Array = pl["size"]
|
|
var quer_ist := absf(d.z) > 0.0
|
|
var halb_d: float = (float(size[1]) if quer_ist else float(size[0])) * 0.5
|
|
var halb_q: float = (float(size[0]) if quer_ist else float(size[1])) * 0.5
|
|
var quer := Vector3(-d.z, 0, d.x)
|
|
if halb_q >= halb_d:
|
|
return {"c": c, "n": -d, "a": quer, "halb_n": halb_d, "halb_a": halb_q}
|
|
return {"c": c, "n": -quer, "a": -d, "halb_n": halb_q, "halb_a": halb_d}
|
|
|
|
|
|
static func _lauf(r: Dictionary) -> float:
|
|
return minf(TREPPE_LAUF, float(r["halb_a"]) * 2.0 - 2.8)
|
|
|
|
|
|
static func _podest_a(r: Dictionary, e: int) -> float:
|
|
var p0: float = float(r["halb_a"]) - 1.4
|
|
return p0 if e % 2 == 0 else p0 - _lauf(r)
|
|
|
|
|
|
## Wendepodest der Etage e: zwei Läufe liegen nebeneinander, das Podest
|
|
## verbindet sie. Der obere Lauf ist so nie die Decke des unteren.
|
|
static func treppe(places: Dictionary, key: String, e: int) -> Vector3:
|
|
var r := treppen_rahmen(places, key)
|
|
var p: Vector3 = r["c"] + r["n"] * (float(r["halb_n"]) - TREPPE_TIEFE * 0.5) \
|
|
+ r["a"] * _podest_a(r, e)
|
|
p.y = hoehe(e)
|
|
return p
|
|
|
|
|
|
## Ein Lauf: [Anfang auf Etage f, Ende auf Etage f + 1].
|
|
static func treppen_lauf(places: Dictionary, key: String, f: int) -> Array:
|
|
var r := treppen_rahmen(places, key)
|
|
var tiefe: float = float(r["halb_n"]) - (1.4 if f % 2 == 0 else 3.0)
|
|
var richtung := -1.0 if f % 2 == 0 else 1.0
|
|
var von: Vector3 = r["c"] + r["n"] * tiefe + r["a"] * (_podest_a(r, f) + richtung * PODEST)
|
|
var bis: Vector3 = r["c"] + r["n"] * tiefe + r["a"] * (_podest_a(r, f + 1) - richtung * PODEST)
|
|
von.y = hoehe(f)
|
|
bis.y = hoehe(f + 1)
|
|
return [von, bis]
|
|
|
|
|
|
## Wegpunkte durchs Treppenhaus von Etage a nach Etage b, ohne a selbst:
|
|
## Laufanfang, Laufende, Podest -- je Etage.
|
|
static func treppen_weg(places: Dictionary, key: String, a: int, b: int) -> Array:
|
|
var out: Array = []
|
|
if b > a:
|
|
for f in range(a, b):
|
|
var l := treppen_lauf(places, key, f)
|
|
out.append(l[0])
|
|
out.append(l[1])
|
|
out.append(treppe(places, key, f + 1))
|
|
else:
|
|
for f in range(a - 1, b - 1, -1):
|
|
var l := treppen_lauf(places, key, f)
|
|
out.append(l[1])
|
|
out.append(l[0])
|
|
out.append(treppe(places, key, f))
|
|
return out
|
|
|
|
|
|
## Deckenplatten einer oberen Etage: alles außer dem Treppenloch.
|
|
## Liefert [[mitte, groesse_xz], ...] ohne Höhe.
|
|
static func treppen_decke(places: Dictionary, key: String) -> Array:
|
|
var r := treppen_rahmen(places, key)
|
|
var c: Vector3 = r["c"]
|
|
var n: Vector3 = r["n"]
|
|
var a: Vector3 = r["a"]
|
|
var halb_n := float(r["halb_n"])
|
|
var halb_a := float(r["halb_a"])
|
|
var out: Array = []
|
|
# Hauptplatte: alles außer dem Streifen an der Treppenwand
|
|
out.append([c - n * (TREPPE_TIEFE * 0.5), _xz(a, halb_a * 2.0, halb_n * 2.0 - TREPPE_TIEFE)])
|
|
# Rest des Streifens jenseits des Lochs
|
|
var ende: float = _podest_a(r, 1) - PODEST
|
|
var rest := ende + halb_a
|
|
if rest > 0.3:
|
|
out.append([c + n * (halb_n - TREPPE_TIEFE * 0.5) + a * ((ende - halb_a) * 0.5),
|
|
_xz(a, rest, TREPPE_TIEFE)])
|
|
return out
|
|
|
|
|
|
## Kastenmaß in Weltachsen: laenge_a entlang a, laenge_n quer dazu.
|
|
static func _xz(a: Vector3, laenge_a: float, laenge_n: float) -> Vector2:
|
|
return Vector2(laenge_a, laenge_n) if absf(a.x) > 0.0 else Vector2(laenge_n, laenge_a)
|
|
|
|
|
|
## Rückt einen Punkt aus dem Treppenstreifen heraus (für Möbel).
|
|
static func frei_von_treppe(places: Dictionary, key: String, pos: Vector3, halb: float) -> Vector3:
|
|
var r := treppen_rahmen(places, key)
|
|
var n: Vector3 = r["n"]
|
|
var pn: float = (pos - r["c"]).dot(n)
|
|
var grenze: float = float(r["halb_n"]) - TREPPE_TIEFE - halb - 0.2
|
|
if pn > grenze:
|
|
pos -= n * (pn - grenze)
|
|
return pos
|
|
|
|
|
|
## Punkt gleich hinter der Tür, im Haus.
|
|
static func innen_tuer(places: Dictionary, key: String) -> Vector3:
|
|
var pl: Dictionary = places[key]
|
|
var c := center(places, key)
|
|
var d: Vector3 = DIR_VEC[pl["dir"]]
|
|
var size: Array = pl["size"]
|
|
var halb: float = (float(size[1]) if absf(d.z) > 0.0 else float(size[0])) * 0.5
|
|
return c + d * (halb - 1.2)
|
|
|
|
|
|
## Ein Ort ist ein Gebäude, wenn er Grundriss und Tür hat.
|
|
static func gebaeude(places: Dictionary, key: String) -> bool:
|
|
return places.has(key) and float(places[key]["size"][0]) > 0.0 \
|
|
and DIR_VEC[places[key]["dir"]] != Vector3.ZERO
|
|
|
|
|
|
## Route mit allem, was ein Körper braucht: aus der Etage runter, gerade durch
|
|
## die Tür, über das Netz, durch die nächste Tür und die Treppe hinauf.
|
|
## `etagen` sagt, in welcher Etage der Mensch an welchem Ort ist.
|
|
static func route_voll(places: Dictionary, a: String, b: String, offset: Vector3,
|
|
etagen: Dictionary, netz: Netz = null, anker: Dictionary = {},
|
|
war_unterwegs: bool = false) -> Array:
|
|
var pts := route(places, a, b, offset, netz, anker)
|
|
if pts.is_empty():
|
|
return pts
|
|
if gebaeude(places, a) and not war_unterwegs:
|
|
var e_von := int(etagen.get(a, 0))
|
|
var runter: Array = []
|
|
if e_von > 0:
|
|
runter.append(treppe(places, a, e_von))
|
|
runter.append_array(treppen_weg(places, a, e_von, 0))
|
|
runter.append(innen_tuer(places, a))
|
|
runter.append(door(places, a))
|
|
runter.append_array(pts)
|
|
pts = runter
|
|
if gebaeude(places, b):
|
|
var e_nach := int(etagen.get(b, 0))
|
|
var ziel: Vector3 = pts.pop_back()
|
|
pts.append(door(places, b))
|
|
pts.append(innen_tuer(places, b))
|
|
if e_nach > 0:
|
|
pts.append(treppe(places, b, 0))
|
|
pts.append_array(treppen_weg(places, b, 0, e_nach))
|
|
ziel.y = hoehe(e_nach)
|
|
pts.append(ziel)
|
|
return pts
|
|
|
|
|
|
static func center(places: Dictionary, key: String) -> Vector3:
|
|
var p: Array = places[key]["pos"]
|
|
return Vector3(p[0], 0.0, p[1])
|
|
|
|
|
|
## Punkt direkt vor der Türlücke, außerhalb des Gebäudes.
|
|
static func door(places: Dictionary, key: String) -> Vector3:
|
|
var pl: Dictionary = places[key]
|
|
var c := center(places, key)
|
|
var d: Vector3 = DIR_VEC[pl["dir"]]
|
|
if d == Vector3.ZERO:
|
|
return c
|
|
var size: Array = pl["size"]
|
|
var half: float = size[1] * 0.5 if absf(d.z) > 0.0 else size[0] * 0.5
|
|
return c + d * (half + 2.5)
|
|
|
|
|
|
## Route von Ort a nach Ort b. Gibt es ein Wegenetz, wird darauf gelaufen --
|
|
## sonst über den freien Platz in der Mitte.
|
|
static func route(places: Dictionary, a: String, b: String, offset: Vector3,
|
|
netz: Netz = null, anker: Dictionary = {}) -> Array:
|
|
var pts: Array = []
|
|
if a == b:
|
|
return pts
|
|
if netz != null and anker.has(a) and anker.has(b):
|
|
var weg := netz.pfad(int(anker[a]), int(anker[b]))
|
|
if not weg.is_empty():
|
|
for idx in weg:
|
|
var k: Vector3 = netz.knoten[idx]
|
|
if pts.is_empty() or pts[pts.size() - 1].distance_to(k) > 0.6:
|
|
pts.append(k)
|
|
pts.append(center(places, b) + offset)
|
|
return pts
|
|
var da := door(places, a)
|
|
var db := door(places, b)
|
|
pts.append(da)
|
|
if da.length() > 17.0:
|
|
pts.append(da.normalized() * 15.0)
|
|
if db.length() > 17.0:
|
|
pts.append(db.normalized() * 15.0)
|
|
pts.append(db)
|
|
pts.append(center(places, b) + offset)
|
|
return pts
|