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

@@ -12,8 +12,6 @@ var place: String = ""
var activity: String = ""
var resist_left: float = 0.0
var places: Dictionary = {}
var netz: Netz = null
var anker: Dictionary = {}
var mit_mission := false
var _visual: Node3D
@@ -28,18 +26,17 @@ var _path: Array = []
var _letzte_aktivitaet: String = ""
var boden: Callable = Callable() # Höhe des Bodens (x, z) -> y; leer heißt eben
var slot: int = 0
var spur: Array = [] # letzte Positionen -- der Geist folgt ihr durch Türen
var nav_map: RID # auf der Erde: Pfade vom Navigationsnetz
var nav_fehl := 0 # wie oft das Netz keinen Pfad wusste (Rückfall aufs Wegenetz)
var nav_fehl_info := ""
var _bob: float = 0.0
var _offset: Vector3
func setup(d: Dictionary, index: int, orte: Dictionary,
wegenetz: Netz = null, wegeanker: Dictionary = {}) -> void:
func setup(d: Dictionary, index: int, orte: Dictionary) -> void:
data = d
idx = index
places = orte
netz = wegenetz
anker = wegeanker
mit_mission = bool(d.get("mission", false))
name = "Bewohner_" + str(d["id"])
var winkel := float(index) * TAU / 4.0
@@ -85,20 +82,25 @@ func setup(d: Dictionary, index: int, orte: Dictionary,
place = start[0]
activity = start[1]
_letzte_aktivitaet = activity
global_position = Orte.center(places, place) + _offset + Vector3(0, Orte.hoehe(etage(place)), 0)
global_position = Orte.center(places, place) + _offset
## Punkt auf der Spur, der mindestens `abstand` hinter dem Menschen liegt.
func spur_punkt(abstand: float) -> Vector3:
for i in range(spur.size() - 1, -1, -1):
if (spur[i] as Vector3).distance_to(global_position) >= abstand:
return spur[i]
return spur[0] if not spur.is_empty() else global_position
## In welcher Etage dieser Mensch an einem Ort ist -- 0, wenn er dort nur unten ist.
func etage(ort: String) -> int:
return int((data.get("etage", {}) as Dictionary).get(ort, 0))
## Pfad über das Navigationsnetz zu einem Ort -- leer, wenn es keins gibt.
func _nav_route(nach: String) -> Array:
if not nav_map.is_valid():
return []
var ziel := Orte.center(places, nach) + _offset
var pts := NavigationServer3D.map_get_path(nav_map, global_position, ziel, true)
if pts.size() < 2:
nav_fehl += 1
nav_fehl_info = "%s: %s -> %s von %s nach %s (%d Punkte)" % [data["name"], place, nach,
str(global_position), str(ziel), pts.size()]
print(" [kein Weg] " + nav_fehl_info)
return []
var out: Array = []
for i in range(1, pts.size()):
out.append(pts[i])
return out
## Kopfbedeckung nach Tagestyp des Berufs -- so unterscheiden sich die Leute
@@ -166,11 +168,9 @@ func _process(roh: float) -> void:
var soll := _routine_at(Game.time_h)
slot = int(soll[2])
if soll[0] != place:
var war_unterwegs := not _path.is_empty()
_path = Orte.route_voll(places, place, soll[0], _offset,
data.get("etage", {}), netz, anker, war_unterwegs)
if war_unterwegs and _path.size() > 1:
_path.remove_at(0) # steht schon draußen, alte Tür überspringen
_path = _nav_route(soll[0])
if _path.is_empty(): # kein Netz oder kein Weg: Luftlinie, damit er ankommt
_path = [Orte.center(places, soll[0]) + _offset]
place = soll[0]
activity = "unterwegs"
elif _path.is_empty() and activity != soll[1]:
@@ -200,10 +200,6 @@ func _process(roh: float) -> void:
_haltung(delta, not _path.is_empty())
if boden.is_valid():
global_position.y = float(boden.call(global_position.x, global_position.z))
if spur.is_empty() or (spur.back() as Vector3).distance_to(global_position) > 0.4:
spur.append(global_position)
if spur.size() > 120:
spur.pop_front()
_visual.rotation.z = lerp_angle(_visual.rotation.z, PI * 0.5 if activity == "schlaeft" else 0.0,
1.0 - pow(0.01, delta))
@@ -224,7 +220,8 @@ func _process(roh: float) -> void:
_label.text = beschriftung()
# Auf der Erde tragen nur Fokus, Verfolgte, Mission und wer unter der Maus
# steht ein Schild -- sonst überdecken sich acht Namen im Café.
_label.visible = not mit_mission or Game.markiert.has(str(data["id"]))
_label.visible = (not mit_mission and not bool(data.get("stumm", false))) \
or Game.markiert.has(str(data["id"]))
_label.modulate = Color(0.55, 0.85, 0.6) if erledigt else (
Color(1, 0.9, 0.6) if aktiv else Color(1, 1, 1))