docs: add plans for Schritt 10-11 (spore overlay, slider) + full parallel execution plan

This commit is contained in:
2026-04-14 22:01:13 +02:00
parent 53889052d1
commit d3afa129f3
3 changed files with 669 additions and 0 deletions

View File

@@ -0,0 +1,200 @@
# Parallel Agent Implementation — Schritt 711
> **For agentic workers:** Use superpowers:subagent-driven-development to execute this plan task-by-task.
**Goal:** Implement Schritt 711 using parallel agents where file overlap allows, minimizing wall-clock time.
---
## Parallelism Analysis
| Schritt | Dateien (schreibend) |
|---------|---------------------|
| 7 — Lighting | `taproom.tscn`, `tavern.tscn` |
| 8 — Dice Roller | `network_manager.gd`, `tavern.gd`, `dm_view.tscn`, `dm_view.gd` |
| 9 — Player Interaction | `project.godot`, `player_controller.gd`★, `interactable.gd`★, `test_interactable.gd`★, `tavern.gd`, `tavern.tscn` |
| 10 — Spore Overlay | `spore_overlay.gdshader`★, `network_manager.gd`, `tavern.gd` |
| 11 — Sporennebel Slider | `spore_level.gd`★, `project.godot`, `network_manager.gd`, `dm_view.tscn`, `dm_view.gd`, `tavern.gd` |
★ = neue Datei, kein Merge-Conflict möglich
**Conflict-Matrix:**
| | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|
| 7 | — | ✅ | ⚠️ tscn | ✅ | ✅ |
| 8 | ✅ | — | ⚠️ tavern.gd | ⚠️ nm.gd+tavern | ⚠️ nm.gd+dm_view+tavern |
| 9 | ⚠️ tscn | ⚠️ tavern.gd | — | ⚠️ tavern.gd | ⚠️ tavern.gd+proj |
| 10 | ✅ | ⚠️ | ⚠️ | — | ⚠️ nm.gd+tavern |
| 11 | ✅ | ⚠️ | ⚠️ | ⚠️ | — |
**Fazit:** Nur 7+8 sind konfliktfrei parallel. Alle anderen haben Überschneidungen in tavern.gd oder network_manager.gd → sequential nach Merge.
---
## Ausführungs-Reihenfolge
```
Phase 1 (parallel): 7 + 8
Phase 2 (merge): merge 7 + 8 → main
Phase 3 (sequenz.): 9
Phase 4 (merge): merge 9 → main
Phase 5 (sequenz.): 10
Phase 6 (merge): merge 10 → main
Phase 7 (sequenz.): 11
Phase 8 (merge): merge 11 → main
```
---
## Phase 1: Agents 7 + 8 parallel dispatchen
Beide Agents **gleichzeitig** starten (single message, two Agent tool calls).
### Agent A — Tavern Lighting (`feat/tavern-lighting`)
**Prompt:**
> Implement the plan at `docs/plans/2026-04-14-tavern-lighting.md` in the Godot 4 project at `ruf-der-pilze/`. Work on branch `feat/tavern-lighting` (create from current `main`). Use superpowers:executing-plans.
>
> Do NOT update STATUS.md — that happens after merge. Push the branch when done and report which commits were created.
### Agent B — Dice Roller (`feat/dice-roller`)
**Prompt:**
> Implement the plan at `docs/plans/2026-04-14-dice-roller.md` in the Godot 4 project at `ruf-der-pilze/`. Work on branch `feat/dice-roller` (create from current `main`). Use superpowers:executing-plans.
>
> Do NOT update STATUS.md — that happens after merge. Push the branch when done and report which commits were created.
---
## Phase 2: Review + Merge 7 + 8
- [ ] **Agent A output reviewen** — Godot öffnen, Screenshot der beleuchteten Taverne
- [ ] **Agent B output reviewen** — Würfelwurf mit zwei Clients testen, DM DC-Anzeige prüfen
- [ ] **Lighting branch mergen**
```bash
git checkout main
git merge feat/tavern-lighting --no-ff -m "feat: merge Schritt 7 — tavern lighting"
```
- [ ] **Dice branch mergen**
```bash
git merge feat/dice-roller --no-ff -m "feat: merge Schritt 8 — dice roller"
```
- [ ] **STATUS.md updaten**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Schritt 7 + 8 complete"
```
---
## Phase 3: Agent C — Player Interaction (`feat/player-interaction`)
**Prompt:**
> Implement the plan at `docs/plans/2026-04-14-player-interaction.md` in the Godot 4 project at `ruf-der-pilze/`. Work on branch `feat/player-interaction` (create from current `main`).
>
> Use superpowers:executing-plans.
>
> **Critical context (already merged into main):**
> - `tavern.gd._ready()` endet jetzt mit `_setup_dice_ui()` — das ist der letzte Aufruf (von Schritt 8). Wenn du `_spawn_player()` ersetzt (Task 4), berühre `_ready()` NICHT.
> - `tavern.tscn` hat neue Licht-Nodes von Schritt 7. Beim Hinzufügen des Test-Interactables (Task 5) nur neue Nodes ergänzen, keine vorhandenen Nodes anfassen.
>
> Do NOT update STATUS.md. Push when done.
---
## Phase 4: Review + Merge 9
- [ ] **Agent C output reviewen** — WASD Bewegung, Maus-Look, E-Taste Interaktion testen
- [ ] **Interaction branch mergen**
```bash
git checkout main
git merge feat/player-interaction --no-ff -m "feat: merge Schritt 9 — player interaction"
```
- [ ] **STATUS.md updaten**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Schritt 9 complete"
```
---
## Phase 5: Agent D — Spore Overlay (`feat/spore-overlay`)
**Prompt:**
> Implement the plan at `docs/plans/2026-04-14-spore-overlay.md` in the Godot 4 project at `ruf-der-pilze/`. Work on branch `feat/spore-overlay` (create from current `main`).
>
> Use superpowers:executing-plans.
>
> **Critical context (already in main):**
> - `tavern.gd._ready()` endet mit `_setup_dice_ui()` — nur APPEND, kein Rewrite.
> - `network_manager.gd` hat bereits: `broadcast_roll`, `_relay_roll` (Schritt 8), `sync_player_position` (Schritt 6). Füge `overlay_changed` Signal und die Änderung in `set_overlay` hinzu ohne andere Funktionen zu ändern.
>
> Do NOT update STATUS.md. Push when done.
---
## Phase 6: Review + Merge 10
- [ ] **Agent D output reviewen** — DM togglet `spore_active`, Spieler sieht Shader-Effekt
- [ ] **Overlay branch mergen**
```bash
git checkout main
git merge feat/spore-overlay --no-ff -m "feat: merge Schritt 10 — spore overlay shader"
```
- [ ] **STATUS.md updaten**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Schritt 10 complete"
```
---
## Phase 7: Agent E — Sporennebel Slider (`feat/spore-slider`)
**Prompt:**
> Implement the plan at `docs/plans/2026-04-14-spore-level-slider.md` in the Godot 4 project at `ruf-der-pilze/`. Work on branch `feat/spore-slider` (create from current `main`).
>
> Use superpowers:executing-plans.
>
> **Critical context (already in main from Schritt 10):**
> - `tavern.gd` hat bereits: `var _spore_mat: ShaderMaterial`, `_setup_spore_overlay()`, `_on_overlay_changed(overlay_name: String)`.
> - Task 5 dieses Plans ersetzt `_on_overlay_changed()` — das ist beabsichtigt und notwendig.
> - `network_manager.gd` hat bereits `overlay_changed` Signal (Schritt 10). Füge `request_spore_level` und `_relay_spore_level` am Ende hinzu ohne bestehende Funktionen zu ändern.
> - `dm_view.tscn` SidePanel hat bereits Würfelwurf-Sektion (Schritt 8). Sporennebel-Slider unterhalb davon ergänzen.
>
> Do NOT update STATUS.md. Push when done.
---
## Phase 8: Review + Merge 11
- [ ] **Agent E output reviewen** — DM Slider bewegen → Spieler Shader-Intensität ändert sich live
- [ ] **Slider branch mergen**
```bash
git checkout main
git merge feat/spore-slider --no-ff -m "feat: merge Schritt 11 — sporennebel slider"
```
- [ ] **STATUS.md updaten — alle Mechanics complete**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Schritt 11 complete — all mechanics done, next: Refectorium"
```
---
## Zusammenfassung
```
main
├── [parallel] feat/tavern-lighting → Agent A
├── [parallel] feat/dice-roller → Agent B
│ [merge beide]
└── feat/player-interaction → Agent C
[merge]
feat/spore-overlay → Agent D
[merge]
feat/spore-slider → Agent E
[merge]
→ Alle Mechanics abgeschlossen → weiter mit Refectorium
```

View File

@@ -0,0 +1,256 @@
# Sporennebel Slider 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:** DM can control spore density (0.01.0) via a slider in the Regiepult. The value is broadcast to all clients and scales the spore overlay shader intensity continuously (instead of binary on/off).
**Architecture:** New `SporeLevel` Autoload holds the current density with a `level_changed` signal. Two new RPCs in NetworkManager sync the value from DM → server → all clients. A slider is added to `dm_view.tscn` SidePanel. In `tavern.gd`, the overlay intensity calculation is updated: intensity = `SporeLevel.current_level` when `spore_active`, 0.0 otherwise. This plan depends on Schritt 10 (spore overlay shader + `_spore_mat` variable must exist in `tavern.gd`).
**Tech Stack:** Godot 4.x GDScript, MultiplayerAPI RPC, HSlider UI
---
## Context
After Schritt 10, `tavern.gd` has:
- `var _spore_mat: ShaderMaterial` — the overlay shader material
- `func _on_overlay_changed(overlay_name: String)` — sets intensity to 0.0 or 1.0
This plan:
1. Adds `SporeLevel` Autoload (replaces the hardcoded 1.0 with a dynamic level)
2. Modifies `_on_overlay_changed` to use `SporeLevel.current_level`
3. Connects `SporeLevel.level_changed` so intensity updates when slider moves
**RPC pattern:** Same server-relay as dice roller — DM sends to server via `rpc_id(1)`, server validates DM role and relays to all.
## Files
| File | Action |
|------|--------|
| `scripts/spore_level.gd` | Create — SporeLevel Autoload |
| `project.godot` | Add SporeLevel to `[autoload]` section |
| `scripts/network_manager.gd` | Add `request_spore_level` + `_relay_spore_level` RPCs |
| `scenes/dm_view.tscn` | Add slider to SidePanel |
| `scripts/dm_view.gd` | Add `_setup_spore_slider()` |
| `scripts/tavern.gd` | Update `_on_overlay_changed()`, add `_on_spore_level_changed()` |
---
## Task 1: Create SporeLevel Autoload
**Files:**
- Create: `scripts/spore_level.gd`
- Modify: `project.godot` — add autoload entry
- [ ] **Step 1: Create scripts/spore_level.gd**
```gdscript
extends Node
signal level_changed(new_level: float)
var current_level: float = 0.0:
set(value):
current_level = clampf(value, 0.0, 1.0)
level_changed.emit(current_level)
```
- [ ] **Step 2: Add to project.godot autoload section**
In the `[autoload]` section, add alongside the existing entries:
```ini
SporeLevel="*res://scripts/spore_level.gd"
```
Alternatively: use Godot editor Project Settings → Autoload → add `SporeLevel` pointing to `res://scripts/spore_level.gd`.
- [ ] **Step 3: Open Godot, verify SporeLevel appears in Project Settings → Autoload**
- [ ] **Step 4: Commit**
```bash
git add ruf-der-pilze/scripts/spore_level.gd ruf-der-pilze/project.godot
git commit -m "feat: add SporeLevel autoload — spore density with level_changed signal"
```
---
## Task 2: Add spore level RPCs to NetworkManager
**Files:**
- Modify: `scripts/network_manager.gd` — append two RPCs at end of file
Same server-relay pattern as `broadcast_roll` / `_relay_roll` from Schritt 8.
- [ ] **Step 1: Add two RPCs at end of network_manager.gd**
```gdscript
# DM calls this on server only via rpc_id(1, level)
@rpc("any_peer", "call_remote", "reliable")
func request_spore_level(level: float) -> void:
if not multiplayer.is_server(): return
var requester_id := multiplayer.get_remote_sender_id()
if players.get(requester_id, {}).get("role", "") != "dm": return
_relay_spore_level.rpc(level)
# Server broadcasts to all clients including itself
@rpc("authority", "call_local", "reliable")
func _relay_spore_level(level: float) -> void:
SporeLevel.current_level = level
```
- [ ] **Step 2: Open Godot, check for parse errors**
- [ ] **Step 3: Commit**
```bash
git add ruf-der-pilze/scripts/network_manager.gd
git commit -m "feat: network_manager — add request_spore_level + _relay_spore_level RPCs"
```
---
## Task 3: Add slider to dm_view.tscn
**Files:**
- Modify: `scenes/dm_view.tscn` — add nodes to SidePanel
In the SidePanel (`RootLayout/TopSection/SidePanel`), add below `OverlayScroll` (or below `SepDice` if the dice roller plan has already added nodes there):
```
HSeparator "SepSpore"
Label "LblSpore" — text = "Sporennebel"
HBoxContainer "SporeLevelRow"
HSlider "SporeSlider"
min_value = 0.0
max_value = 1.0
step = 0.05
value = 0.0
size_flags_horizontal = SIZE_EXPAND_FILL
Label "SporeValueLabel" — text = "0%"
custom_minimum_size = Vector2(35, 0)
```
- [ ] **Step 1: Add the nodes to dm_view.tscn via Godot editor**
Open `dm_view.tscn`. Navigate to `RootLayout/TopSection/SidePanel`. Add the nodes listed above in order.
- [ ] **Step 2: Verify layout in Godot editor**
SidePanel should show: Overlays section → (dice section if Schritt 8 merged) → Sporennebel label → slider + percentage label.
- [ ] **Step 3: Commit**
```bash
git add ruf-der-pilze/scenes/dm_view.tscn
git commit -m "feat: dm_view — add sporennebel slider to SidePanel"
```
---
## Task 4: Wire slider in dm_view.gd
**Files:**
- Modify: `scripts/dm_view.gd` — add `_setup_spore_slider()`, call in `_ready()`
- [ ] **Step 1: Add _setup_spore_slider() to dm_view.gd**
```gdscript
func _setup_spore_slider() -> void:
var slider := $RootLayout/TopSection/SidePanel/SporeLevelRow/SporeSlider as HSlider
var value_label := $RootLayout/TopSection/SidePanel/SporeLevelRow/SporeValueLabel as Label
slider.value_changed.connect(func(val: float) -> void:
value_label.text = "%d%%" % roundi(val * 100.0)
NetworkManager.request_spore_level.rpc_id(1, val)
)
```
- [ ] **Step 2: Call _setup_spore_slider() in dm_view.gd _ready()**
Append to end of `_ready()`:
```gdscript
_setup_spore_slider()
```
- [ ] **Step 3: Open Godot, check for parse errors**
- [ ] **Step 4: Commit**
```bash
git add ruf-der-pilze/scripts/dm_view.gd
git commit -m "feat: dm_view — wire sporennebel slider to request_spore_level RPC"
```
---
## Task 5: Update tavern.gd to use SporeLevel
**Files:**
- Modify: `scripts/tavern.gd` — update `_on_overlay_changed()`, add `_on_spore_level_changed()`, connect in `_setup_spore_overlay()`
**Prerequisite:** This task requires Schritt 10 to be merged — `_spore_mat`, `_setup_spore_overlay()`, and `_on_overlay_changed()` must already exist in `tavern.gd`.
The intensity should now be: `SporeLevel.current_level` when overlay is `spore_active`, else `0.0`. Both the overlay toggle and the slider need to update the shader.
- [ ] **Step 1: Replace _on_overlay_changed() in tavern.gd**
Find the existing method:
```gdscript
func _on_overlay_changed(overlay_name: String) -> void:
var intensity := 1.0 if overlay_name == "spore_active" else 0.0
_spore_mat.set_shader_parameter("intensity", intensity)
```
Replace with:
```gdscript
func _on_overlay_changed(overlay_name: String) -> void:
_apply_spore_intensity()
func _on_spore_level_changed(_level: float) -> void:
_apply_spore_intensity()
func _apply_spore_intensity() -> void:
var overlay_name := GameState.get_overlay(NetworkManager.my_id)
var intensity := SporeLevel.current_level if overlay_name == "spore_active" else 0.0
_spore_mat.set_shader_parameter("intensity", intensity)
```
- [ ] **Step 2: Connect SporeLevel.level_changed in _setup_spore_overlay()**
In `_setup_spore_overlay()`, after `NetworkManager.overlay_changed.connect(_on_overlay_changed)`, add:
```gdscript
SporeLevel.level_changed.connect(_on_spore_level_changed)
```
- [ ] **Step 3: Open Godot, check for parse errors**
- [ ] **Step 4: Run end-to-end test**
Start server + DM client + player client.
- DM: toggle player overlay to `spore_active`
- DM: move sporennebel slider from 0 → 1.0
- Player: shader intensity should increase smoothly
- DM: slider back to 0.3 → player sees reduced effect
- DM: toggle overlay back to `default` → player effect disappears even at 0.3 level
- [ ] **Step 5: Commit**
```bash
git add ruf-der-pilze/scripts/tavern.gd
git commit -m "feat: tavern — spore overlay intensity driven by SporeLevel (continuous slider control)"
```
---
## Task 6: Update STATUS.md
- [ ] **Step 1: Mark Schritt 11 ✅ in docs/STATUS.md and ruf-der-pilze/CLAUDE.md**
- [ ] **Step 2: Commit**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Sporennebel Slider complete"
```

View File

@@ -0,0 +1,213 @@
# Spore Overlay 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:** When the DM toggles a player to `spore_active`, that player sees a fullscreen screen-space shader effect (green tint, vignette, subtle distortion). Toggling back to `default` removes it.
**Architecture:** A new `shaders/spore_overlay.gdshader` (CanvasItem shader sampling the screen texture) is applied to a fullscreen ColorRect on a CanvasLayer. `NetworkManager` emits a new `overlay_changed` signal from the existing `set_overlay` RPC. `tavern.gd._setup_spore_overlay()` creates the overlay UI and connects to that signal. DM clients skip this (early return in `_ready()`). Intensity is binary (0.0 / 1.0) in this plan — Schritt 11 adds continuous slider control.
**Tech Stack:** Godot 4.x GDScript, GLSL (Godot canvas_item shader), CanvasLayer, ShaderMaterial
---
## Context
Existing RPC chain (already implemented):
```
DM: request_set_overlay.rpc_id(1, peer_id, "spore_active")
→ Server validates DM role, calls set_overlay.rpc_id(peer_id, "spore_active")
→ Player client: GameState.set_overlay_local(my_id, "spore_active")
```
`set_overlay` in `network_manager.gd` currently only calls `GameState.set_overlay_local` — no visual effect fires. This plan adds:
1. `signal overlay_changed(overlay_name: String)` to NetworkManager, emitted from `set_overlay`
2. The actual shader + CanvasLayer in `tavern.gd`
The overlay intensity in this plan is binary: 1.0 when `spore_active`, 0.0 for `default`. Schritt 11 extends this to use `SporeLevel.current_level` as the multiplier.
## Files
| File | Action |
|------|--------|
| `shaders/spore_overlay.gdshader` | Create — screen-space spore effect shader |
| `scripts/network_manager.gd` | Add `overlay_changed` signal + emit in `set_overlay` |
| `scripts/tavern.gd` | Add `_setup_spore_overlay()`, call in `_ready()` |
---
## Task 1: Create the spore overlay shader
**Files:**
- Create: `shaders/spore_overlay.gdshader`
The shader samples the screen texture and applies: green tint, edge vignette, subtle time-based distortion. The `intensity` uniform drives all effects (0.0 = invisible, 1.0 = full effect).
- [ ] **Step 1: Create ruf-der-pilze/shaders/ directory and spore_overlay.gdshader**
```glsl
shader_type canvas_item;
uniform float intensity : hint_range(0.0, 1.0) = 0.0;
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
void fragment() {
vec2 uv = SCREEN_UV;
// Subtle distortion — wavy lines, stronger at higher intensity
float distort_x = sin(uv.y * 35.0 + TIME * 1.8) * 0.003 * intensity;
float distort_y = cos(uv.x * 28.0 + TIME * 1.2) * 0.002 * intensity;
// Sample screen with slight RGB split for chromatic aberration feel
float split = 0.003 * intensity;
vec4 r = texture(screen_texture, uv + vec2(distort_x + split, distort_y));
vec4 g = texture(screen_texture, uv + vec2(distort_x, distort_y));
vec4 b = texture(screen_texture, uv + vec2(distort_x - split, distort_y));
vec4 screen = vec4(r.r, g.g, b.b, 1.0);
// Vignette — darken edges
vec2 center = uv - 0.5;
float vignette = 1.0 - smoothstep(0.25, 0.75, length(center) * 1.6);
screen.rgb *= mix(1.0, vignette, intensity * 0.6);
// Green spore tint
vec3 spore_tint = vec3(0.05, 0.45, 0.12);
screen.rgb = mix(screen.rgb, screen.rgb * spore_tint * 2.2, intensity * 0.35);
// Slight brightness pulse
float pulse = 1.0 + sin(TIME * 1.5) * 0.04 * intensity;
screen.rgb *= pulse;
COLOR = screen;
}
```
The shader uses `hint_screen_texture` to capture the rendered scene. The ColorRect must cover the full screen and use this shader — Godot automatically provides the screen texture.
- [ ] **Step 2: Open Godot, verify shader parses without errors**
Open Project → any scene → check Output for shader compilation errors.
- [ ] **Step 3: Commit**
```bash
git add ruf-der-pilze/shaders/spore_overlay.gdshader
git commit -m "feat: add spore_overlay.gdshader — screen-space tint, vignette, distortion"
```
---
## Task 2: Add overlay_changed signal to NetworkManager
**Files:**
- Modify: `scripts/network_manager.gd` — add signal declaration + emit in `set_overlay`
- [ ] **Step 1: Add signal declaration near top of network_manager.gd**
Add alongside the other signal declarations:
```gdscript
signal overlay_changed(overlay_name: String)
```
- [ ] **Step 2: Emit the signal in set_overlay RPC**
Find the `set_overlay` function (currently at end of file):
```gdscript
@rpc("authority", "call_remote", "reliable")
func set_overlay(overlay_name: String) -> void:
GameState.set_overlay_local(my_id, overlay_name)
```
Add one line:
```gdscript
@rpc("authority", "call_remote", "reliable")
func set_overlay(overlay_name: String) -> void:
GameState.set_overlay_local(my_id, overlay_name)
overlay_changed.emit(overlay_name)
```
- [ ] **Step 3: Open Godot, check for parse errors**
- [ ] **Step 4: Commit**
```bash
git add ruf-der-pilze/scripts/network_manager.gd
git commit -m "feat: network_manager — emit overlay_changed signal from set_overlay RPC"
```
---
## Task 3: Add spore overlay CanvasLayer to tavern.gd
**Files:**
- Modify: `scripts/tavern.gd` — add member variable, `_setup_spore_overlay()`, `_on_overlay_changed()`
The DM client already returns early in `_ready()` before reaching the player setup block, so no DM guard is needed here.
- [ ] **Step 1: Add member variable to tavern.gd**
Near the top of the script (alongside other member variables):
```gdscript
var _spore_mat: ShaderMaterial
```
- [ ] **Step 2: Add _setup_spore_overlay() and _on_overlay_changed() to tavern.gd**
```gdscript
func _setup_spore_overlay() -> void:
var canvas := CanvasLayer.new()
canvas.name = "SporeOverlay"
canvas.layer = 10 # renders above dice UI (layer 0)
add_child(canvas)
var rect := ColorRect.new()
rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
_spore_mat = ShaderMaterial.new()
_spore_mat.shader = load("res://shaders/spore_overlay.gdshader") as Shader
rect.material = _spore_mat
canvas.add_child(rect)
NetworkManager.overlay_changed.connect(_on_overlay_changed)
func _on_overlay_changed(overlay_name: String) -> void:
var intensity := 1.0 if overlay_name == "spore_active" else 0.0
_spore_mat.set_shader_parameter("intensity", intensity)
```
- [ ] **Step 3: Call _setup_spore_overlay() in _ready()**
Add at the very end of `_ready()`, after the existing `_setup_dice_ui()` call:
```gdscript
_setup_spore_overlay()
```
**Important:** do NOT modify any other part of `_ready()`. The DM early-return at the top already skips this. Only append — do not rewrite the method.
- [ ] **Step 4: Open Godot, check for parse errors**
- [ ] **Step 5: Run as player client**
Log in as Spieler. Have DM toggle overlay to `spore_active` in the Regiepult.
Expected: green tinted, slightly distorted, vignette'd screen visible to the player.
Expected: toggling back to `default` clears the effect.
- [ ] **Step 6: Commit**
```bash
git add ruf-der-pilze/scripts/tavern.gd
git commit -m "feat: tavern — add spore overlay CanvasLayer + shader driven by overlay_changed signal"
```
---
## Task 4: Update STATUS.md
- [ ] **Step 1: Mark Schritt 10 ✅ in docs/STATUS.md and ruf-der-pilze/CLAUDE.md**
- [ ] **Step 2: Commit**
```bash
git add docs/STATUS.md ruf-der-pilze/CLAUDE.md
git commit -m "docs: mark Spore Overlay complete"
```