docs: add tavern scene implementation plan

This commit is contained in:
2026-04-14 02:30:38 +02:00
parent 3d30664878
commit 332fa93db5

View File

@@ -0,0 +1,606 @@
# Taverne In-Game-Szene Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 2-stöckige In-Game-Taverne bauen (Blockout), Gastraum als Sub-Scene extrahieren, und nach `game_started` Spieler in ihre Zimmer und DM in eine Stub-Szene routen.
**Architecture:** `taproom.tscn` (Geometrie-Only) wird von `tavern_lobby.tscn` und `tavern.tscn` instanziert. `SceneManager` routet bei `game_started` Spieler zu `tavern.tscn` und DM zu `dm_view.tscn`. Room-Zuweisung wird als Parameter in `start_game` RPC mitgeschickt (verhindert Timing-Probleme zwischen RPC-Empfang und Scene-`_ready()`).
**Tech Stack:** Godot 4.x, GDScript, ENet Multiplayer, BoxMesh Placeholder-Geometrie, godot-mcp MCP Tools
---
## File Map
| Aktion | Pfad | Verantwortung |
|--------|------|---------------|
| Umbenennen | `scenes/tavern.tscn``scenes/tavern_lobby.tscn` | Lobby/Warteraum |
| Umbenennen | `scripts/tavern.gd``scripts/tavern_lobby.gd` | Lobby-Script |
| Erstellen | `scenes/taproom.tscn` | Gastraum-Geometrie (kein Script, kein UI) |
| Erstellen | `scenes/tavern.tscn` | In-Game-Taverne (Erd- + Obergeschoss) |
| Erstellen | `scenes/dm_view.tscn` | DM-Szene Stub |
| Erstellen | `scripts/tavern.gd` | Spawn-Logik: Spieler im richtigen Zimmer |
| Erstellen | `scripts/dm_view.gd` | DM-Stub-Script |
| Ändern | `scripts/scene_manager.gd` | SCENES dict, `_on_root_ready`, `_on_game_started`, `pending_room_index` |
| Ändern | `scripts/network_manager.gd` | `start_game(room_assignments)`, `_build_room_assignments()` |
Alle Pfade relativ zu `ruf-der-pilze/`.
---
## Task 1: Bestehende Tavern-Dateien umbenennen
**Files:**
- Rename: `scenes/tavern.tscn``scenes/tavern_lobby.tscn`
- Rename: `scripts/tavern.gd``scripts/tavern_lobby.gd`
- [ ] **Step 1: Dateien per git mv umbenennen**
```bash
cd ruf-der-pilze
git mv scenes/tavern.tscn scenes/tavern_lobby.tscn
git mv scripts/tavern.gd scripts/tavern_lobby.gd
```
- [ ] **Step 2: Script-Referenz in `tavern_lobby.tscn` aktualisieren**
`tavern_lobby.tscn` referenziert das Script noch als `res://scripts/tavern.gd`. Ändere die erste Zeile:
```
# ALT:
[ext_resource type="Script" path="res://scripts/tavern.gd" id="1"]
# NEU:
[ext_resource type="Script" path="res://scripts/tavern_lobby.gd" id="1"]
```
- [ ] **Step 3: Klassennamen in `tavern_lobby.gd` anpassen (optional, aber sauber)**
Datei `scripts/tavern_lobby.gd` — keine Änderung am Code nötig, `extends Node3D` bleibt.
- [ ] **Step 4: Verifizieren — Godot öffnen, Scene-Fehler prüfen**
Öffne Godot. Prüfe im Editor dass `tavern_lobby.tscn` keine Fehler im Script-Attachment zeigt.
Erwartung: Scene öffnet, JoinPanel sichtbar, keine Fehlermeldungen im Output.
- [ ] **Step 5: Committen**
```bash
git add scenes/tavern_lobby.tscn scripts/tavern_lobby.gd
git commit -m "refactor: rename tavern → tavern_lobby (scene + script)"
```
---
## Task 2: SceneManager aktualisieren
**Files:**
- Modify: `scripts/scene_manager.gd`
- [ ] **Step 1: SCENES dict, pending_room_index und `_on_root_ready` aktualisieren**
Ersetze den gesamten Inhalt von `scripts/scene_manager.gd`:
```gdscript
extends Node
const SCENES := {
"lobby": "res://scenes/tavern_lobby.tscn",
"tavern": "res://scenes/tavern.tscn",
"dm_view": "res://scenes/dm_view.tscn",
"entrance_hall": "res://scenes/entrance_hall.tscn",
"refectory": "res://scenes/refectory.tscn",
"library": "res://scenes/library.tscn",
"chapel": "res://scenes/chapel.tscn",
"cloister": "res://scenes/cloister.tscn",
"sanctum": "res://scenes/sanctum.tscn",
}
var pending_room_index: int = 0
var _current_scene_node: Node = null
func _ready() -> void:
NetworkManager.game_started.connect(_on_game_started)
get_tree().root.ready.connect(_on_root_ready, CONNECT_ONE_SHOT)
func _on_root_ready() -> void:
var args := OS.get_cmdline_args() + OS.get_cmdline_user_args()
var is_server := OS.has_feature("dedicated_server") or "--server" in args
if not is_server:
transition_to("lobby")
func transition_to(scene_name: String) -> void:
var path: String = SCENES.get(scene_name, "")
var packed := ResourceLoader.load(path, "PackedScene", ResourceLoader.CACHE_MODE_REUSE) as PackedScene
if packed == null:
push_error("[SceneManager] Scene not found: %s" % scene_name)
return
var container := get_node_or_null("/root/Main/CurrentScene")
if container == null:
push_error("[SceneManager] CurrentScene node not found in main.tscn")
return
if _current_scene_node != null:
_current_scene_node.get_parent().remove_child(_current_scene_node)
_current_scene_node.queue_free()
_current_scene_node = null
_current_scene_node = packed.instantiate()
container.add_child(_current_scene_node)
func _on_game_started() -> void:
var args := OS.get_cmdline_args() + OS.get_cmdline_user_args()
if OS.has_feature("dedicated_server") or "--server" in args:
return
var role: String = NetworkManager.players.get(NetworkManager.my_id, {}).get("role", "player")
if role == "dm":
transition_to("dm_view")
else:
transition_to("tavern")
```
- [ ] **Step 2: Verifizieren — Lobby lädt noch**
Starte das Spiel (kein Server). Erwartung: Lobby erscheint mit JoinPanel.
Console: `[SceneManager]` kein Fehler-Output.
- [ ] **Step 3: Committen**
```bash
git add scripts/scene_manager.gd
git commit -m "feat: update SceneManager — lobby/tavern/dm_view keys, game_started routing"
```
---
## Task 3: taproom.tscn erstellen und Lobby darauf umstellen
**Files:**
- Create: `scenes/taproom.tscn`
- Modify: `scenes/tavern_lobby.tscn`
Die bestehende Geometrie aus `tavern_lobby.tscn` (Floor, Ceiling, Wände) wird in `taproom.tscn` extrahiert. Der Gastraum bleibt atmosphärisch identisch.
- [ ] **Step 1: `taproom.tscn` erstellen**
Erstelle `scenes/taproom.tscn` mit folgender Node-Struktur (MCP-Tool oder manuell):
```
Node3D "Taproom" ← Root, kein Script
StaticBody3D "Floor"
MeshInstance3D mesh: BoxMesh(12, 0.1, 8)
CollisionShape3D shape: BoxShape3D(12, 0.1, 8)
StaticBody3D "Ceiling"
MeshInstance3D mesh: BoxMesh(12, 0.1, 8), transform.origin.y = 4.0
CollisionShape3D shape: BoxShape3D(12, 0.1, 8)
StaticBody3D "WallBack"
MeshInstance3D mesh: BoxMesh(12, 4, 0.1), transform.origin = (0, 2, -4)
CollisionShape3D
StaticBody3D "WallLeft"
MeshInstance3D mesh: BoxMesh(0.1, 4, 8), transform.origin = (-6, 2, 0)
CollisionShape3D
StaticBody3D "WallRight"
MeshInstance3D mesh: BoxMesh(0.1, 4, 8), transform.origin = (6, 2, 0)
CollisionShape3D
StaticBody3D "Bar" ← Tresen: Küchen-Grenze
MeshInstance3D mesh: BoxMesh(4, 1.1, 0.3), transform.origin = (4, 0.55, -3.5)
CollisionShape3D
OmniLight3D "Light"
transform.origin = (0, 2.5, 0)
light_color = Color(0.91, 0.643, 0.29)
light_energy = 1.2
omni_range = 10.0
WorldEnvironment "WorldEnvironment"
environment: (fog, warm ambient — gleich wie in bisheriger tavern.tscn)
```
Materialien: Braun-Töne wie in bisheriger `tavern.tscn` (StandardMaterial3D albedo_color ≈ Color(0.169, 0.102, 0.051)).
- [ ] **Step 2: `tavern_lobby.tscn` aktualisieren**
Ersetze die bestehende Geometrie in `tavern_lobby.tscn` durch eine Instanz von `taproom.tscn`. Die Szene behält Camera3D und CanvasLayer.
Neue Node-Struktur von `tavern_lobby.tscn`:
```
Node3D "TavernLobby" ← script = tavern_lobby.gd
[taproom.tscn instanziert als Child] ← Name: "Taproom"
Camera3D "Camera3D" ← bestehende Lobby-Kamera (transform bleibt)
CanvasLayer "CanvasLayer" ← JoinPanel + WaitPanel (unverändert)
```
- [ ] **Step 3: Verifizieren**
Starte das Spiel. Erwartung: Lobby sieht identisch aus wie vorher (gleicher Gastraum, gleiche UI).
Falls Geometrie fehlt oder falsch positioniert: Transform-Werte in taproom.tscn korrigieren.
- [ ] **Step 4: Committen**
```bash
git add scenes/taproom.tscn scenes/tavern_lobby.tscn
git commit -m "refactor: extract taproom as reusable sub-scene, update lobby"
```
---
## Task 4: `tavern.tscn` Erdgeschoss bauen
**Files:**
- Create: `scenes/tavern.tscn`
- Create: `scripts/tavern.gd` (Stub — Spawn-Logik kommt in Task 7)
Erdgeschoss: Taproom + sichtbare Küche (nicht betretbar) + Private Gemächer (Tür) + Ausgang + Myzelspur.
- [ ] **Step 1: `scripts/tavern.gd` Stub erstellen**
```gdscript
extends Node3D
func _ready() -> void:
print("[Tavern] Scene loaded. Room index: %d" % SceneManager.pending_room_index)
```
- [ ] **Step 2: `scenes/tavern.tscn` Erdgeschoss bauen**
Node-Struktur:
```
Node3D "Tavern" ← script = tavern.gd
[taproom.tscn instanziert] ← Name: "Taproom", transform.origin = (0,0,0)
Node3D "GroundFloor"
StaticBody3D "KitchenBack" ← Hinterwand Küche (sichtbar hinter Tresen)
MeshInstance3D mesh: BoxMesh(4, 3, 0.1), transform.origin = (4, 1.5, -5.9)
StaticBody3D "KitchenLeft"
MeshInstance3D mesh: BoxMesh(0.1, 3, 2.3), transform.origin = (2.05, 1.5, -4.85)
StaticBody3D "KitchenRight"
MeshInstance3D mesh: BoxMesh(0.1, 3, 2.3), transform.origin = (5.95, 1.5, -4.85)
StaticBody3D "PrivateRoomDoor" ← Tür zu Privatgemächern (geschlossen)
MeshInstance3D mesh: BoxMesh(0.1, 4, 2), transform.origin = (-6, 2, 2)
StaticBody3D "ExitDoor" ← Ausgang zur Myzelspur (später: interaktiv)
MeshInstance3D mesh: BoxMesh(0.1, 4, 2), transform.origin = (6, 2, 4)
Node3D "MyzelTrailGround" ← Myzelspur: Treppe → Ausgang
MeshInstance3D "TrailSegment1" mesh: BoxMesh(0.5, 0.01, 3), grünlich, transform.origin = (0, 0.06, 1.5)
MeshInstance3D "TrailSegment2" mesh: BoxMesh(0.5, 0.01, 4), transform.origin = (2, 0.06, 0)
# Weitere Segmente dem Weg entlang anpassen
```
Material Myzelspur: StandardMaterial3D, albedo_color = Color(0.2, 0.8, 0.3), emission_enabled = true, emission = Color(0.1, 0.4, 0.1).
- [ ] **Step 3: Verifizieren — Scene lädt ohne Fehler**
Öffne `tavern.tscn` im Godot Editor. Erwartung: Kein Parser-Fehler, Erdgeschoss sichtbar in 3D-Vorschau.
- [ ] **Step 4: Committen**
```bash
git add scenes/tavern.tscn scripts/tavern.gd
git commit -m "feat: tavern scene — ground floor blockout (taproom, kitchen, exit, myzel trail)"
```
---
## Task 5: `tavern.tscn` Obergeschoss bauen
**Files:**
- Modify: `scenes/tavern.tscn`
8 Gästezimmer + Annas Zimmer + Korridor + Treppe. Jedes Gästezimmer hat einen `Marker3D` SpawnPoint.
Maße: Gebäude ~16m breit, 8m tief. Korridor: 1.5m breit, Zimmer: 3m x 3.5m.
- [ ] **Step 1: Treppe einbauen**
In `tavern.tscn` unter `GroundFloor` hinzufügen:
```
StaticBody3D "Stairs"
MeshInstance3D mesh: BoxMesh(1.5, 0.2, 4) als Rampe — transform mit Rotation X ca. -25°
transform.origin = (0, 1, 3) ← verbindet EG mit OG
CollisionShape3D
```
- [ ] **Step 2: Obergeschoss-Struktur und Korridor bauen**
Füge zu `tavern.tscn` hinzu:
```
Node3D "UpperFloor"
StaticBody3D "Floor"
MeshInstance3D mesh: BoxMesh(16, 0.1, 8), transform.origin = (2, 4, 0)
CollisionShape3D
StaticBody3D "Ceiling"
MeshInstance3D mesh: BoxMesh(16, 0.1, 8), transform.origin = (2, 7, 0)
CollisionShape3D
StaticBody3D "WallBack"
MeshInstance3D mesh: BoxMesh(16, 3, 0.1), transform.origin = (2, 5.5, -4)
CollisionShape3D
StaticBody3D "WallFront"
MeshInstance3D mesh: BoxMesh(16, 3, 0.1), transform.origin = (2, 5.5, 4)
CollisionShape3D
StaticBody3D "WallLeft"
MeshInstance3D mesh: BoxMesh(0.1, 3, 8), transform.origin = (-6, 5.5, 0)
CollisionShape3D
StaticBody3D "WallRight"
MeshInstance3D mesh: BoxMesh(0.1, 3, 8), transform.origin = (10, 5.5, 0)
CollisionShape3D
StaticBody3D "CorridorWall" ← Korridor-Innenwand (trennt Zimmer von Korridor)
MeshInstance3D mesh: BoxMesh(16, 3, 0.1), transform.origin = (2, 5.5, 2)
CollisionShape3D
```
- [ ] **Step 3: 8 Gästezimmer mit SpawnPoints**
Pro Zimmer (i = 1..8, je 2m breit, nebeneinander):
```
Node3D "Room{i}" ← parent: UpperFloor
StaticBody3D "Bed"
MeshInstance3D mesh: BoxMesh(1.8, 0.5, 0.9), transform.origin lokal (0, 0.25, -2.5)
CollisionShape3D
Marker3D "SpawnPoint" ← Name MUSS "SpawnPoint" sein
transform.origin lokal (0, 1.0, -1) ← steht neben dem Bett
```
Zimmer-Positionen (global, je 2m Abstand in X):
- Room1: x = -5, z = 2.8, y = 4.1
- Room2: x = -3, z = 2.8, y = 4.1
- Room3: x = -1, z = 2.8, y = 4.1
- ... bis Room8: x = 9, z = 2.8, y = 4.1
- [ ] **Step 4: Annas Zimmer (Room9) mit Myzel-Dekoration**
```
Node3D "Room9" ← Annas Zimmer, ganz rechts (x = 9, oder eigener Bereich)
StaticBody3D "Bed"
MeshInstance3D mesh: BoxMesh(1.8, 0.5, 0.9) — Material: myzel-überzogen (grünlich)
StaticBody3D "OpenDoor" ← Tür steht offen (BoxMesh als Tür-Panel, seitlich gedreht)
MeshInstance3D mesh: BoxMesh(0.05, 2.5, 1.2), transform rotiert 90° in Y
Node3D "MyzelDecor"
MeshInstance3D "MyzelPatch1" ← Fleck auf dem Boden, grünlich
MeshInstance3D "MyzelPatch2" ← Fleck an der Wand
Node3D "MyzelTrailAnna" ← Spur aus Annas Zimmer in den Korridor
MeshInstance3D "TrailOut" mesh: BoxMesh(0.4, 0.01, 1.5), grünlich, transform.origin lokal (0, 0.06, 1.2)
```
Alle Myzel-Materialien: gleich wie in Task 4 (grünlich, leicht emissiv).
- [ ] **Step 5: Verifizieren — Obergeschoss in Editor prüfen**
Öffne `tavern.tscn`. Vergewissere dich im 3D-Viewport:
- Obergeschoss sichtbar über dem Taproom
- 9 Zimmer mit Betten erkennbar
- Room9 (Annas Zimmer) mit Myzel-Dekoration
- SpawnPoints als gelbe Marker sichtbar (Marker3D Icons im Editor)
- [ ] **Step 6: Committen**
```bash
git add scenes/tavern.tscn
git commit -m "feat: tavern scene — upper floor blockout (8 rooms + Anna's room, SpawnPoints)"
```
---
## Task 6: NetworkManager — Room-Zuweisung in start_game
**Files:**
- Modify: `scripts/network_manager.gd`
Room-Index wird als Dictionary-Parameter in `start_game` RPC mitgeschickt. Das vermeidet Timing-Probleme (SceneManager.pending_room_index ist gesetzt bevor `game_started` emittiert wird).
- [ ] **Step 1: `_build_room_assignments()` hinzufügen**
Füge diese Methode am Ende von `network_manager.gd` hinzu:
```gdscript
func _build_room_assignments() -> Dictionary:
var result := {}
var player_peers: Array = players.keys().filter(
func(id: int) -> bool: return players[id].role == "player"
)
for i in player_peers.size():
result[player_peers[i]] = i % 8 # 8 Gästezimmer (Index 07)
return result
```
- [ ] **Step 2: `start_game` RPC um room_assignments erweitern**
Ändere die bestehende `start_game` Funktion:
```gdscript
@rpc("authority", "call_local", "reliable")
func start_game(room_assignments: Dictionary) -> void:
if my_id in room_assignments:
SceneManager.pending_room_index = room_assignments[my_id]
game_started.emit()
```
- [ ] **Step 3: `request_start_game` anpassen — Assignments bauen und mitschicken**
Ändere die bestehende `request_start_game` Funktion:
```gdscript
@rpc("any_peer", "call_remote", "reliable")
func request_start_game() -> void:
if not multiplayer.is_server():
return
var requester_id := multiplayer.get_remote_sender_id()
if players.get(requester_id, {}).get("role", "") != "dm":
return
var assignments := _build_room_assignments()
start_game.rpc(assignments)
```
- [ ] **Step 4: Verifizieren — Script-Syntax prüfen**
Öffne Godot. Erwartung: Kein GDScript-Fehler in `network_manager.gd`.
Alternativ: `godot --check-only` im `ruf-der-pilze/` Verzeichnis ausführen.
- [ ] **Step 5: Committen**
```bash
git add scripts/network_manager.gd
git commit -m "feat: include room assignments in start_game RPC"
```
---
## Task 7: `tavern.gd` — Spawn-Logik implementieren
**Files:**
- Modify: `scripts/tavern.gd`
Liest `SceneManager.pending_room_index` und platziert einen minimalen PlayerController (Node3D + Camera3D) am zugehörigen SpawnPoint.
- [ ] **Step 1: `tavern.gd` implementieren**
Ersetze den Stub-Inhalt von `scripts/tavern.gd`:
```gdscript
extends Node3D
const ROOM_COUNT := 8
func _ready() -> void:
var args := OS.get_cmdline_args() + OS.get_cmdline_user_args()
if OS.has_feature("dedicated_server") or "--server" in args:
return
var room_index := SceneManager.pending_room_index
_spawn_player(room_index)
func _spawn_player(room_index: int) -> void:
var room_num := (room_index % ROOM_COUNT) + 1 # Zimmer heißen Room1..Room8
var spawn_path := "UpperFloor/Room%d/SpawnPoint" % room_num
var spawn := get_node_or_null(spawn_path) as Marker3D
if spawn == null:
push_error("[Tavern] SpawnPoint nicht gefunden: %s" % spawn_path)
return
var controller := Node3D.new()
controller.name = "PlayerController"
var camera := Camera3D.new()
camera.name = "Camera3D"
camera.current = true
controller.add_child(camera)
add_child(controller)
controller.global_transform = spawn.global_transform
print("[Tavern] Spieler gespawnt in %s" % spawn_path)
```
- [ ] **Step 2: Verifizieren — Solo-Test**
Starte das Spiel ohne Multiplayer. Verbinde mit Server und starte das Spiel als DM.
Als Spieler-Client: Erwartung: Szene wechselt zu `tavern.tscn`, Kamera steht im zugewiesenen Zimmer.
Console: `[Tavern] Spieler gespawnt in UpperFloor/Room1/SpawnPoint`
- [ ] **Step 3: Committen**
```bash
git add scripts/tavern.gd
git commit -m "feat: tavern.gd — spawn player at assigned room SpawnPoint"
```
---
## Task 8: `dm_view.tscn` Stub erstellen
**Files:**
- Create: `scenes/dm_view.tscn`
- Create: `scripts/dm_view.gd`
Minimale Platzhalter-Szene für den DM. Wird in Schritt 7 (DM Regiepult) vollständig ausgebaut.
- [ ] **Step 1: `scripts/dm_view.gd` erstellen**
```gdscript
extends Node
func _ready() -> void:
print("[DmView] DM-Szene geladen (Stub)")
```
- [ ] **Step 2: `scenes/dm_view.tscn` erstellen**
Node-Struktur:
```
Node "DmView" ← script = dm_view.gd
SubViewportContainer "ViewportContainer"
SubViewport
Camera3D "Camera3D" ← top-down, transform.origin = (0, 20, 0), rotation_degrees.x = -90
current = true
CanvasLayer "UI"
Label "StubLabel"
text = "DM View — Stub\n(wird in Schritt 7 ausgebaut)"
horizontal_alignment = CENTER
anchors_preset = CENTER
```
- [ ] **Step 3: Verifizieren**
Starte als DM-Client, starte das Spiel. Erwartung: DM sieht Label "DM View — Stub".
- [ ] **Step 4: Committen**
```bash
git add scenes/dm_view.tscn scripts/dm_view.gd
git commit -m "feat: dm_view stub scene"
```
---
## Task 9: End-to-End Test
**Files:** keine Änderungen
Vollständiger Durchlauf: Server + 2 Spieler-Clients + 1 DM-Client.
- [ ] **Step 1: Server starten**
```bash
cd ruf-der-pilze
godot --headless -- --server
```
- [ ] **Step 2: Spieler-Client 1 starten und verbinden**
Starte Godot-Client 1. Lobby erscheint, verbinden als "Spieler1" (Rolle: Spieler).
Erwartung: JoinPanel verschwindet, WaitPanel zeigt Spielerliste.
- [ ] **Step 3: Spieler-Client 2 starten und verbinden**
Starte Godot-Client 2. Verbinden als "Spieler2" (Rolle: Spieler).
Erwartung: Beide Clients sehen beide Spieler in der WaitPanel-Liste.
- [ ] **Step 4: DM-Client starten, verbinden und Spiel starten**
Starte Godot-Client 3. Verbinden als "DM1" (Rolle: DM). StartButton wird sichtbar.
Klicke StartButton.
- [ ] **Step 5: Ergebnis prüfen**
Erwartungen:
- Spieler-Client 1: Szene wechselt zu `tavern.tscn`, Kamera steht in Room1
- Spieler-Client 2: Szene wechselt zu `tavern.tscn`, Kamera steht in Room2
- DM-Client: Szene wechselt zu `dm_view.tscn`, Label "DM View — Stub" sichtbar
- Console (Server): Keine Fehler, `[Server] game_started` verarbeitet
- Console (Clients): `[Tavern] Spieler gespawnt in UpperFloor/Room1/SpawnPoint` etc.
- [ ] **Step 6: MCP Screenshot für visuelle Verifikation**
Nutze `mcp__godot-mcp__scene` Screenshot-Tool um die Spieler-Perspektive und DM-Ansicht zu dokumentieren.
- [ ] **Step 7: docs/STATUS.md und CLAUDE.md updaten**
In `docs/STATUS.md`:
- Schritt 5 (Szenen-Wechsel nach Spielstart) auf ✅ setzen
- "In Arbeit" leeren
- Schritt 6 (Refectorium) als "Als nächstes" eintragen
In `ruf-der-pilze/CLAUDE.md`:
- Entwicklungs-Reihenfolge: Schritt 5 auf ✅
- [ ] **Step 8: Finaler Commit**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark scene switching complete, update STATUS"
```