This commit is contained in:
Team3
2026-09-16 16:15:32 +02:00
parent e813b5f7aa
commit 7c4edaa439
19 changed files with 1244 additions and 636 deletions

View File

@@ -7,7 +7,11 @@ const REICHWEITE_MENSCH := 3.6
var player: Player
var ui: UI
var welt: Node3D
var welt: Node3D # die aktive Welt
var traum: DreamWorld = null # beide Welten bleiben bestehen und leben weiter
var erde: EarthWorld = null
var _traum_version := -1
var _erde_version := -1
var auf_erde := false
var _fokus: Node3D = null
var _fokus_mensch: Node3D = null
@@ -20,6 +24,7 @@ func _ready() -> void:
player.look_enabled = false)
ui.panel_closed.connect(func() -> void:
player.look_enabled = true)
ui.hinfahren.connect(hinfahren)
player = Player.new()
add_child(player)
@@ -34,28 +39,86 @@ func _ready() -> void:
func _traumwelt() -> void:
auf_erde = false
_setze_welt(DreamWorld.new())
if traum == null or _traum_version != Game.welt_version:
traum = _neu_bauen(traum, DreamWorld.new(), 1) as DreamWorld
_traum_version = Game.welt_version
_aktivieren(traum)
player.set_mode(Player.Mode.TRAUM)
player.global_position = (welt as DreamWorld).spawn
player.collision_mask = 1
player.global_position = traum.spawn
player.yaw = Player.CAM_YAW
func _erde() -> void:
auf_erde = true
_setze_welt(EarthWorld.new())
if erde == null or _erde_version != Game.welt_version:
erde = _neu_bauen(erde, EarthWorld.new(), 2) as EarthWorld
_erde_version = Game.welt_version
_aktivieren(erde)
player.set_mode(Player.Mode.GEIST)
player.global_position = (welt as EarthWorld).spawn
player.collision_mask = 2
player.global_position = erde.spawn
player.yaw = Player.CAM_YAW
if Game.active_mission != "":
zum_ziel(Game.active_mission, false) # wer mit Mission reist, landet vor der Tür seines Ziels
func _setze_welt(neu: Node3D) -> void:
if welt != null:
remove_child(welt)
welt.queue_free()
## Vor die Tür eines Menschen setzen -- steht er draußen, neben ihn. Der Fußweg
## quer durch den Bezirk war Leerlauf; das Gehen zählt in der Wohnung und beim Folgen.
func zum_ziel(id: String, melden: bool = true) -> void:
var wer: Bewohner = null
for h in erde.humans:
if str(h.data["id"]) == id:
wer = h
if wer == null:
return
var p: Vector3
var drinnen: bool = HumanDB.PLACES.has(wer.place) \
and float(HumanDB.PLACES[wer.place]["size"][0]) > 0.0 and wer._path.is_empty()
if drinnen:
p = Orte.door(HumanDB.PLACES, wer.place)
else:
p = wer.global_position + Vector3(2.0, 0, 0)
p = NavigationServer3D.map_get_closest_point(erde.nav_map, p)
player.global_position = p + Vector3(0, 0.3, 0)
player.velocity = Vector3.ZERO
player.folgt = null
Game.teleport_lock = 1.0
if melden:
Game.notified.emit("Du stehst %s %s." % ["vor der Tür von" if drinnen else "bei",
wer.data["name"]], Color(0.7, 0.9, 1))
## Knopf in der Akte: zur Erde und vor die Tür.
func hinfahren(id: String) -> void:
if not auf_erde:
_erde()
zum_ziel(id)
## Eine Welt neu bauen -- nur wenn Dorf oder Stadt sich geändert haben. Jede
## Welt liegt auf ihrer eigenen Kollisionsebene, denn beide teilen sich den Raum.
func _neu_bauen(alt: Node3D, neu: Node3D, ebene: int) -> Node3D:
if alt != null:
remove_child(alt)
alt.queue_free()
add_child(neu)
move_child(neu, 0)
for k in neu.find_children("*", "CollisionObject3D", true, false):
(k as CollisionObject3D).collision_layer = 1 << (ebene - 1)
return neu
## Die andere Welt bleibt da und lebt weiter, nur unsichtbar und ohne Himmel.
func _aktivieren(neu: Node3D) -> void:
for w in [traum, erde]:
if w == null:
continue
var an: bool = w == neu
w.visible = an
w.set("spieler", player if an else null)
w.call("aktiv_setzen", an)
welt = neu
add_child(welt)
move_child(welt, 0)
welt.set("spieler", player) # für den Etagenschnitt
Game.teleport_lock = 1.0
_fokus = null
_fokus_mensch = null
@@ -115,6 +178,8 @@ func _fokus_suchen() -> void:
var p := player.global_position
var best := REICHWEITE_OBJEKT
for n in get_tree().get_nodes_in_group("interactable"):
if not welt.is_ancestor_of(n):
continue # die andere Welt liegt im selben Raum
var d: float = p.distance_to((n as Node3D).global_position)
if d < best:
best = d
@@ -123,8 +188,6 @@ func _fokus_suchen() -> void:
var bestm := REICHWEITE_MENSCH
for m in (welt as EarthWorld).humans:
var mp: Vector3 = (m as Node3D).global_position + Vector3(0, 1.0, 0)
if absf(mp.y - p.y) > 2.0:
continue # andere Etage: durch die Decke sieht man nichts
var d: float = p.distance_to(mp)
if d < bestm:
bestm = d
@@ -156,6 +219,10 @@ func _hinweis_setzen() -> void:
ui.setze_hinweis("[E] %s — Techniken lernen" % titel)
"brett":
ui.setze_hinweis("[E] Schwarzes Brett — Mission annehmen")
"spur":
ui.setze_hinweis("[E] Spur: %s" % titel)
"wesen":
ui.setze_hinweis("[E] %s — zuhören" % titel)
_:
ui.setze_hinweis("[E] %s" % titel)
else:
@@ -298,3 +365,12 @@ func _interagieren() -> void:
ui.lehre_panel(str(_fokus.get_meta("arg")))
"brett":
ui.brett_panel()
"wesen":
Game.notified.emit(Game.wesen_fluestert(int(str(_fokus.get_meta("arg")))), Color(0.85, 0.8, 1))
"spur":
var wer := str(_fokus.get_meta("human"))
var u := str(_fokus.get_meta("arg"))
var neu := Game.spur_lesen(wer, u)
Game.notified.emit("%s%s — %s" % ["" if neu else "Schon gesehen: ",
Ursachen.LISTE[u]["spur"], Ursachen.LISTE[u]["spur_text"]],
Color(1, 0.9, 0.6) if neu else Color(0.8, 0.85, 1))