refactor
This commit is contained in:
152
CLAUDE.md
152
CLAUDE.md
@@ -1,92 +1,98 @@
|
||||
# MMO Projekt
|
||||
|
||||
## Überblick
|
||||
Community-MMO in Godot 4.6 (Forward+, Jolt Physics). Ziel: Einsamkeit bekämpfen durch geographische Nähe der Spieler. Stilles Designprinzip — nicht als "Anti-Einsamkeits-Spiel" vermarktet.
|
||||
Community-MMO in Godot 4.6 (Forward+, Jolt Physics). Vision in `doc/_core.md`, Features in `doc/features.md`.
|
||||
|
||||
## Sprache
|
||||
Der User kommuniziert auf Deutsch. Code und Variablen auf Englisch. Kommentare nur wo nötig.
|
||||
|
||||
## Code-Style
|
||||
- GDScript mit 2 Spaces Einrückung (Godot Editor auf Spaces/2 eingestellt)
|
||||
- Explizite Typen bei Variablen die von Variant-Funktionen kommen (z.B. `var dist: float = ...` statt `var dist := ...` bei `distance_to()`, `min()`, `get_node_or_null()`)
|
||||
- Keine Debug-Prints im finalen Code (nur temporär zum Testen)
|
||||
- GDScript mit 2 Spaces Einrückung
|
||||
- Explizite Typen wo der Inferenzer scheitert (Ergebnisse von Variant-Funktionen, Helper-Returns die Node sein könnten)
|
||||
- Keine Debug-Prints im finalen Code
|
||||
- Keine emoji
|
||||
|
||||
## Architektur
|
||||
- **Stats (Model)**: Autoload, zentrale Datenhaltung aller Entity-Attribute. Basiswerte aus Resources.
|
||||
- **Systeme (Controller)**: Scene-Nodes in world.tscn/dungeon.tscn, lesen/schreiben über Stats.
|
||||
- **Szenen (Views)**: Rendern, Input senden, Events empfangen. Kein Gameplay-State.
|
||||
- **EventBus (Signals)**: Autoload, Kommunikation zwischen Szenen und Systemen.
|
||||
- **Event-Flow**: Szene → Input → EventBus → System → Stats → EventBus → Szene
|
||||
- **Zwischen Szenen**: Kommunikation über EventBus. Szenen kennen sich nicht.
|
||||
- **Innerhalb einer Szene**: Zugriff auf Geschwister-Nodes erlaubt.
|
||||
- **Autoloads**: EventBus (Signals), Stats (Entity-Daten), GameState (Szene + Position)
|
||||
- **Gruppen**: "player", "enemies", "portals", "boss", "cooldown_system"
|
||||
- **Resources** für Basiswerte (Stats, Abilities), **Stats Autoload** für Laufzeitwerte
|
||||
|
||||
## Projektstruktur
|
||||
Drei Grundordner nach Verantwortung. Resources liegen bei ihren Skripten.
|
||||
- `scenes/` — Darstellung + Input
|
||||
- `player/` — Spieler + player_stats + role/ (Rollen + Abilities)
|
||||
- `enemy/` — Gegner + enemy_stats + boss/ (Boss + boss_stats)
|
||||
- `portal/` — Portal + Gate + portal_stats
|
||||
- `dungeon/` — Dungeon + dungeon_manager
|
||||
- `hud/` — HUD
|
||||
- `world/` — Hauptszene + portal_spawner
|
||||
- `effect_icon_factory.gd` — Shared Utility (Effekt-Icons)
|
||||
- `healthbar*.gd` — Healthbar-Komponenten (health, shield, status, effects)
|
||||
- `systems/` — Spiellogik
|
||||
- 12 Systeme (health, shield, ability, auto_attack, cooldown, enemy_ai, respawn, spawn, effect, element, aura, buff_calc)
|
||||
- `effect.gd` — Effect Resource (Buff/Debuff/Aura Daten)
|
||||
- `aggro/` — AggroSystem (system, tracker, decay, events) + aggro_config
|
||||
- `autoloads/` — Globaler Zustand
|
||||
- event_bus, game_state
|
||||
- `stats/` — stats + base_stats
|
||||
### Autoloads (`autoloads/`)
|
||||
- `EventBus` — alle Signals (Combat, Wave, Inventory, Dialog, Chat, …)
|
||||
- `Net` — ENet P2P Multiplayer-Manager (Singleplayer = OfflineMultiplayerPeer)
|
||||
- `Stats` — zentrale Registry: `register(entity, base_resource)` / `get_stat` / `set_stat`
|
||||
- `GameState` — Wave#, Scene-Pfade, Run-Seed, Pause, Dungeon-Seed
|
||||
- `SaveLoad` — JSON-basierte Persistenz (Stub für später)
|
||||
|
||||
## Planungsdokument
|
||||
`plan.md` enthält die vollständige Projektstruktur: Szenenbaum, Szenen mit Nodes, Skripte, Components, Stats, Aggro-Regeln, Abilities und Events. Dieses Dokument ist die Wahrheit für den Soll-Zustand.
|
||||
### Resources (`resources/`)
|
||||
- `stats/` — BaseStats + Player/Enemy/Boss/Portal/Gate/Village/Building Stats
|
||||
- `abilities/` — Ability + AbilitySet (3 Klassen × 5 Abilities, im RoleSystem in Code aufgebaut)
|
||||
- `items/` — Item, Recipe (Crafting in CraftingSystem in Code)
|
||||
- `buildings/` — Building Resource (Blueprints in BuildingSystem in Code)
|
||||
- `npcs/` — NpcProfile (Lore + Personality für Ollama)
|
||||
- `effects/` — Effect Resource + Element (NONE, FIRE)
|
||||
|
||||
## Core Loop
|
||||
1. Portale spawnen dynamisch auf der Karte (PortalSpawner, max 3, 20-40m vom Zentrum)
|
||||
2. Spieler greift Portal an → Gegner spawnen bei Lebensschwellen (85%/70%/55%/40%/25%/10%)
|
||||
3. Spieler bekämpft Gegner mit Abilities (Single, AOE, Utility, Ult) + Auto-Attack
|
||||
4. Portal bei 0 HP → Gate spawnt, Gegner werden entfernt
|
||||
5. Spieler betritt Gate → Dungeon (separate Szene, 4 Gegnergruppen + Boss)
|
||||
6. Spieler kann zwischen Welt und Dungeon hin und her (beide Gates aktiv solange Boss lebt)
|
||||
7. Boss stirbt → 2s Delay → Spieler wird zur Taverne teleportiert, Gates verschwinden
|
||||
8. Tod → 3s Respawn bei Taverne
|
||||
### Szenen (`scenes/`)
|
||||
- `menu/` — main_menu, lobby, options_menu
|
||||
- `world/` — world.tscn (Dorf-Welt mit Village + alle Systeme als Children)
|
||||
- `dungeon/` — dungeon.tscn (procedural generation via dungeon_generator.gd)
|
||||
- `entities/` — player, enemy, gate, portal, building, loot, npc, village
|
||||
- `hud/` — hud.tscn (alles-in-einem: vitals, abilities, chat, minimap, inventory, crafting, build, dialog, map, pause, game over)
|
||||
|
||||
## Kampfsystem
|
||||
- Auto-Attack: Rollenspezifisch (D: 10 Schaden/10m, T: 5 Schaden/3m, H: 1 Heilung/20m), 0.5s CD
|
||||
- 5 Abilities pro Rolle: Single, AOE, Utility, Ult, Passive — jede Rolle hat eigene Werte
|
||||
- GCD 0.5s (gilt für 1, 2, 4), Utility ignoriert GCD
|
||||
- Heilung: Heiler heilt sich selbst (Singleplayer), is_heal Flag auf Ability
|
||||
- Passive: Schadens-Boost (D), Schild-Boost (T), Heal-Boost (H) — je 50%, als Aura (50m Radius)
|
||||
- Targeting: Klick, TAB (cyclet "enemies" + "portals"), Auto-Target (Gegner > Portal)
|
||||
- Aggro-System: 1:1 Schaden, Tank 2x, Heilung 0.5x, verfällt -1/s, exponentiell außerhalb Portal-Radius
|
||||
### Systeme (`systems/`)
|
||||
Alle als Children unter `World/Systems` und `Dungeon/Systems` instanziert:
|
||||
- Combat: HealthSystem, ShieldSystem, RespawnSystem, CooldownSystem, AbilitySystem, AutoAttackSystem
|
||||
- Effects: EffectSystem, ElementSystem, AggroSystem, RoleSystem
|
||||
- World: SpawnSystem, WaveSystem, InvasionSystem, XpSystem, LootSystem
|
||||
- Player: InventorySystem, CraftingSystem, BuildingSystem
|
||||
- Social: NpcSystem, DialogSystem (Ollama HTTP), ChatSystem, MapSystem, AudioSystem
|
||||
|
||||
## Rollen
|
||||
- Tank (T), Schaden (D), Heiler (H) — wechselbar mit ALT+1/2/3
|
||||
- Jede Rolle hat eigenes AbilitySet mit unterschiedlichen Werten und Mechaniken
|
||||
- Tank: Weniger Schaden, Nahkampf, Schild-Ult (300%), Schild-Passive
|
||||
- Heiler: Heilt statt schadet (Single, AOE, Ult), Heal-Passive, AOE macht Schaden
|
||||
### Multiplayer-Pattern
|
||||
- ENet P2P, Host-Authoritative
|
||||
- Singleplayer = `Net.host_singleplayer()` (OfflineMultiplayerPeer)
|
||||
- Player-Entities tragen Authority des jeweiligen Peers (`_enter_tree() → set_multiplayer_authority(name.to_int())`)
|
||||
- Stats/Damage/Spawn/Wave/XP/Inventory laufen nur am Host (`if not multiplayer.is_server() and multiplayer.multiplayer_peer != null: return`)
|
||||
- Client-Aktionen via RPC zum Host: `_request_*.rpc_id(1, ...)` → Host validiert + sync via `MultiplayerSpawner` und `MultiplayerSynchronizer`
|
||||
- Sync-Felder pro Entity über `MultiplayerSynchronizer` mit `SceneReplicationConfig`
|
||||
|
||||
## Effekte & Elemente
|
||||
- **EffectSystem**: Verwaltet Buffs, Debuffs, Auras auf allen Entities. Kein Stacking (gleicher Name → Refresh)
|
||||
- **Effect Resource**: effect_name, type (BUFF/DEBUFF/AURA), stat, value, duration (-1=permanent), is_multiplier, aura_radius, tick_interval, element
|
||||
- **Auras**: Passive-Abilities werden als AURA-Effekte erstellt. Propagieren Buffs auf Spieler im aura_radius. Verlässt man Radius → Buff sofort weg
|
||||
- **ElementSystem**: Verwaltet Elementar-Zustände auf Enemies + Portalen. Aktuell: Feuer (DoT 3/Tick, 2s Interval, 6s)
|
||||
- **Abilities**: `element` Feld (0=NONE, 1=FIRE). Schadens-Abilities der Damage-Rolle haben element=1 (Feuer)
|
||||
- **Effekt-Icons**: Auf Healthbars (Enemies, Boss, Portal) und Spieler-HUD. Aura=blau, Buff=grün, Debuff=rot
|
||||
### Input-Map
|
||||
- WASD + Space: Move + Jump
|
||||
- 1–4: Abilities (im Build-Mode: Bauteil-Auswahl)
|
||||
- ALT+1/2/3: Tank/Damage/Healer
|
||||
- Tab: Cycle target | LMB: Click target | RMB: Camera drag (capture mouse)
|
||||
- I: Inventory | C: Crafting | B: Build mode | M: Map | Y: Chat | E: Interact (NPC)
|
||||
- R: Rotate building preview
|
||||
- Escape: Pause / Cancel UI
|
||||
|
||||
## Szenenwechsel
|
||||
- Stats Autoload cached Spieler-Werte automatisch bei Szenenwechsel
|
||||
- GameState speichert Rolle + Position
|
||||
- Gate (Eingang): save_player → Dungeon laden
|
||||
- Gate (Exit): returning_from_dungeon → Welt laden, Spieler bei Gate-Position
|
||||
- Boss-Tod: dungeon_cleared → Welt laden, Cache geleert, Spieler bei Taverne mit vollen HP
|
||||
### Dialog (Ollama)
|
||||
- HTTP `localhost:11434/api/generate`, Modell `llama3.2`
|
||||
- Pro NPC: System-Prompt aus `lore` + `personality`
|
||||
- Fallback: `npc.fallback_text` wenn Ollama nicht erreichbar — Spiel bleibt voll spielbar
|
||||
|
||||
### Bauen
|
||||
- Grid-Snap 1m, 4 Bauteile (Floor, Wall, Door, Roof)
|
||||
- LMB im Build-Mode platziert, MMB entfernt
|
||||
- Material-Verbrauch aus Crafting-Items (alle aus `wood`, das aus `essence` gecrafted wird)
|
||||
- Persistenz via Host (Buildings sind echte Nodes unter `EntityRoot/Buildings`, MultiplayerSpawner repliziert)
|
||||
|
||||
### Wave-Loop
|
||||
1. WaveSystem startet 10-min Timer, spawnt 3 normale + 1 rotes Gate
|
||||
2. Gate stirbt → spawnt Portal an gleicher Position
|
||||
3. Spieler betritt Portal → Dungeon (procedural, 5–8 Räume + Boss)
|
||||
4. Boss-Tod → Welt-Rückkehr; rotes Portal → Wave++ + alle Stats skalieren
|
||||
5. Timer 0 ohne rotes Portal → Invasion (8+wave×2 Mobs zur Village)
|
||||
6. Village 0 HP → Game Over → Hauptmenü
|
||||
|
||||
## Workflow mit dem User
|
||||
- **plan.md ist zentral** — User will Änderungen zuerst in plan.md dokumentiert haben, dann implementieren
|
||||
- **Modularer Aufbau** — Jede Szene/Skript hat eine Aufgabe
|
||||
- **Schrittweise** — Erst planen, dann Code zeigen, dann implementieren
|
||||
- **Godot-Eigenheiten**: Nach Änderungen an Autoloads/Scripts Godot neu starten. Godot überschreibt .tscn beim Speichern — Szene im Editor schließen vor externen Edits.
|
||||
- Erst planen (`doc/` lesen), dann implementieren
|
||||
- Schrittweise, modulares Aufbauen — nicht alles auf einmal umbauen
|
||||
- Nach Änderungen: `godot-4 --headless --quit-after 60 res://scenes/world/world.tscn` um Parse-/Runtime-Fehler zu sehen
|
||||
- `doc/` nicht anfassen — das ist die User-Spec
|
||||
|
||||
## Smoke-Test
|
||||
- `godot-4 --headless --import` → Kein Error
|
||||
- `godot-4 --headless --quit-after 600 res://scenes/world/world.tscn` → Kein Error
|
||||
- `godot-4 --headless --quit-after 600 res://scenes/dungeon/dungeon.tscn` → Kein Error
|
||||
|
||||
## Bekannte Lücken / TODOs
|
||||
- Ollama muss installiert werden (Modell `llama3.2` erwartet) — Stub-Fallback funktioniert sonst
|
||||
- Save/Load Slots im Hauptmenü (Autoload existiert, UI fehlt)
|
||||
- Multiplayer Late-Join: Building-/Wave-State wird beim spätem Beitritt nicht synchronisiert
|
||||
- Damage Numbers / Hit FX / Particle Effects fehlen (rein Polish)
|
||||
|
||||
Reference in New Issue
Block a user