From e811598920f1291cc1d6ed807be844e8904728c3 Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Thu, 16 Apr 2026 00:51:45 +0200 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20add=20CharacterPlaceholder=20scene?= =?UTF-8?q?=20=E2=80=94=20colored=20capsule=20+=20name=20label?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scenes/character_placeholder.tscn | 28 +++++++++++++++++++ .../scripts/character_placeholder.gd | 19 +++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 ruf-der-pilze/scenes/character_placeholder.tscn create mode 100644 ruf-der-pilze/scripts/character_placeholder.gd diff --git a/ruf-der-pilze/scenes/character_placeholder.tscn b/ruf-der-pilze/scenes/character_placeholder.tscn new file mode 100644 index 0000000..24197d7 --- /dev/null +++ b/ruf-der-pilze/scenes/character_placeholder.tscn @@ -0,0 +1,28 @@ +[gd_scene load_steps=5 format=3] + +[ext_resource type="Script" path="res://scripts/character_placeholder.gd" id="1"] + +[sub_resource type="CapsuleMesh" id="2"] +height = 1.8 +radius = 0.3 + +[sub_resource type="StandardMaterial3D" id="3"] +albedo_color = Color(0.65, 0.65, 0.65, 1) + +[sub_resource type="LabelSettings" id="4"] +font_size = 48 + +[node name="CharacterPlaceholder" type="Node3D"] +script = ExtResource("1") + +[node name="Capsule" type="MeshInstance3D" parent="."] +mesh = SubResource("2") +material_override = SubResource("3") + +[node name="NameLabel" type="Label3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 0) +text = "" +font_size = 48 +billboard = 1 +no_depth_test = true +label_settings = SubResource("4") diff --git a/ruf-der-pilze/scripts/character_placeholder.gd b/ruf-der-pilze/scripts/character_placeholder.gd new file mode 100644 index 0000000..5f5a4ae --- /dev/null +++ b/ruf-der-pilze/scripts/character_placeholder.gd @@ -0,0 +1,19 @@ +extends Node3D + +const CLASS_COLORS: Dictionary = { + "Krieger": Color(0.80, 0.20, 0.20), # Rot + "Magier": Color(0.20, 0.20, 0.90), # Blau + "Kleriker": Color(0.90, 0.85, 0.20), # Gelb + "Schurke": Color(0.20, 0.65, 0.20), # Grün + "Druide": Color(0.40, 0.75, 0.30), # Hellgrün + "Barbar": Color(0.75, 0.40, 0.10), # Orange +} +const DEFAULT_COLOR := Color(0.65, 0.65, 0.65) # Grau + +func set_color(class_name: String) -> void: + var mat := StandardMaterial3D.new() + mat.albedo_color = CLASS_COLORS.get(class_name, DEFAULT_COLOR) + ($Capsule as MeshInstance3D).material_override = mat + +func set_label(player_name: String) -> void: + ($NameLabel as Label3D).text = player_name From 8a47abda3f2b7d8631757994210e32065d0cc3d3 Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Thu, 16 Apr 2026 00:51:45 +0200 Subject: [PATCH 2/4] lobby: add 5 LobbySpot Marker3D for capsule placement --- ruf-der-pilze/scenes/tavern_lobby.tscn | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ruf-der-pilze/scenes/tavern_lobby.tscn b/ruf-der-pilze/scenes/tavern_lobby.tscn index e4fd68c..7870008 100644 --- a/ruf-der-pilze/scenes/tavern_lobby.tscn +++ b/ruf-der-pilze/scenes/tavern_lobby.tscn @@ -48,3 +48,18 @@ custom_minimum_size = Vector2(0, 150) [node name="StartButton" type="Button" parent="CanvasLayer/WaitPanel"] text = "Spiel starten" visible = false + +[node name="LobbySpot0" type="Marker3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.0, 0.0, 1.0) + +[node name="LobbySpot1" type="Marker3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.0, 0.0, 1.5) + +[node name="LobbySpot2" type="Marker3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0, 0.0, 1.8) + +[node name="LobbySpot3" type="Marker3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.0, 0.0, 1.5) + +[node name="LobbySpot4" type="Marker3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2.0, 0.0, 1.0) From 40297d9d4c3b293bdac29c082bdebce2a5cf744a Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Thu, 16 Apr 2026 00:51:45 +0200 Subject: [PATCH 3/4] lobby: spawn colored capsule avatars for each player at LobbySpots --- ruf-der-pilze/scripts/tavern_lobby.gd | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/ruf-der-pilze/scripts/tavern_lobby.gd b/ruf-der-pilze/scripts/tavern_lobby.gd index 6c7c3c4..e974db7 100644 --- a/ruf-der-pilze/scripts/tavern_lobby.gd +++ b/ruf-der-pilze/scripts/tavern_lobby.gd @@ -1,7 +1,11 @@ extends Node3D +const CharacterPlaceholder := preload("res://scenes/character_placeholder.tscn") + var _local_role: String = "" var _pending_player_name: String = "" +var _capsules: Dictionary = {} # peer_id: int → Node3D +var _lobby_spots: Array[Marker3D] = [] func _ready() -> void: @@ -17,6 +21,18 @@ func _ready() -> void: NetworkManager.player_left.connect(_on_player_left) NetworkManager.player_list_synced.connect(_rebuild_player_list) + _lobby_spots = [ + $LobbySpot0 as Marker3D, + $LobbySpot1 as Marker3D, + $LobbySpot2 as Marker3D, + $LobbySpot3 as Marker3D, + $LobbySpot4 as Marker3D, + ] + NetworkManager.player_joined.connect(_on_player_joined_capsule) + NetworkManager.player_left.connect(_on_player_left_capsule) + if NetworkManager.has_signal("character_updated"): + NetworkManager.character_updated.connect(_on_character_updated_capsule) + func _on_join_pressed() -> void: var player_name: String = ($CanvasLayer/JoinPanel/NameInput as LineEdit).text.strip_edges() @@ -40,6 +56,10 @@ func _exit_tree() -> void: NetworkManager.player_joined.disconnect(_on_player_joined) NetworkManager.player_left.disconnect(_on_player_left) NetworkManager.player_list_synced.disconnect(_rebuild_player_list) + NetworkManager.player_joined.disconnect(_on_player_joined_capsule) + NetworkManager.player_left.disconnect(_on_player_left_capsule) + if NetworkManager.has_signal("character_updated") and NetworkManager.character_updated.is_connected(_on_character_updated_capsule): + NetworkManager.character_updated.disconnect(_on_character_updated_capsule) func _on_connection_failed() -> void: @@ -66,3 +86,29 @@ func _rebuild_player_list() -> void: func _on_start_pressed() -> void: NetworkManager.request_start_game.rpc_id(1) + + +func _on_player_joined_capsule(peer_id: int, _player_name: String, _role: String) -> void: + if _capsules.has(peer_id): + return + var spot_index := _capsules.size() % _lobby_spots.size() + var capsule: Node3D = CharacterPlaceholder.instantiate() + add_child(capsule) + capsule.global_position = _lobby_spots[spot_index].global_position + var player_data: Dictionary = NetworkManager.players.get(peer_id, {}) + capsule.set_label(player_data.get("name", "???")) + capsule.set_color(player_data.get("char", {}).get("class", "")) + _capsules[peer_id] = capsule + + +func _on_player_left_capsule(peer_id: int) -> void: + if not _capsules.has(peer_id): + return + (_capsules[peer_id] as Node3D).queue_free() + _capsules.erase(peer_id) + + +func _on_character_updated_capsule(peer_id: int, data: Dictionary) -> void: + if not _capsules.has(peer_id): + return + (_capsules[peer_id] as Node3D).set_color(data.get("class", "")) From 21c03e2839fd070420592f3912b5fe2f4db1410f Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Thu, 16 Apr 2026 00:51:45 +0200 Subject: [PATCH 4/4] =?UTF-8?q?docs:=20mark=20Schritt=2013=20complete=20?= =?UTF-8?q?=E2=80=94=20Charakter-Capsules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/STATUS.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/STATUS.md b/docs/STATUS.md index d3f2449..b820ac2 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -1,6 +1,6 @@ # Ruf der Pilze — Projektstatus -Zuletzt aktualisiert: 2026-04-14 (Schritt 5 abgeschlossen) +Zuletzt aktualisiert: 2026-04-16 (Schritt 13 abgeschlossen) --- @@ -15,6 +15,8 @@ Zuletzt aktualisiert: 2026-04-14 (Schritt 5 abgeschlossen) - **Tavern Lobby** — 3D-Taverne ersetzt die flache Lobby-UI; SceneManager Autoload eingeführt - **Taverne + Szenen-Wechsel** — 2-stöckige In-Game-Taverne (Blockout), taproom.tscn als Sub-Scene, game_started → Spieler in zugewiesenem Zimmer (SpawnPoint), DM in dm_view.tscn Stub +- **Charakter-Capsules** — Farbige Capsule-Avatare (CharacterPlaceholder) für jeden Spieler in der Lobby; + 5 LobbySpot-Marker in tavern_lobby.tscn; Farbe aus Klasse (Fallback Grau); `character_updated`-Guard vorhanden ### 🔄 In Arbeit — (nichts aktiv) @@ -32,6 +34,7 @@ Zuletzt aktualisiert: 2026-04-14 (Schritt 5 abgeschlossen) 3. ✅ Lobby + Rollen (Spieler registrieren sich, DM kriegt Sonderrechte) 4. ✅ Tavern Lobby — 3D-Taverne als Warteraum, SceneManager Autoload 5. ✅ Szenen-Wechsel nach Spielstart — taproom Sub-Scene, 2 Etagen, SpawnPoints, dm_view Stub +13. ✅ Charakter-Capsules — farbige Capsule-Avatare in der Lobby, 5 LobbySpots, Farbe aus Klasse 6. ⏳ DM Regiepult Basics — Overlay-Toggle, Top-Down pro Etage, Player-Cams Plan: `docs/plans/2026-04-14-dm-regiepult-basics.md` 7. ⏳ Refectorium — asymmetrische Wahrnehmung (erster Raum)