# Projektstruktur ## Szenenbaum - Welt - Systems (HealthSystem, ShieldSystem, RespawnSystem, CombatSystem, AggroSystem, EnemyAISystem, SpawnSystem) - Taverne - Player - Portale (dynamisch) - Gegner - HUD ## Architektur - Zwischen Szenen: Kommunikation über EventBus (Szenen kennen sich nicht) - Innerhalb einer Szene: Modulare Skripte, Zugriff auf Geschwister-Nodes erlaubt - Systeme berechnen und entscheiden, Szenen rendern und senden/empfangen - Event-Flow: Input → Intention-Event → System → Ergebnis-Event → Node - Systeme sind Scene-Nodes (nicht Autoloads), gefunden über Gruppen # Systeme - Systems-Node in jeder Root-Szene (world.tscn, dungeon.tscn) - Entities registrieren sich bei Systemen in _ready(), deregistrieren in _exit_tree() - Systeme ownen State in Dictionaries (entity → Daten) - scripts/systems/ — System-Skripte ### HealthSystem (health_system.gd) - Leben (health) und Lebensregeneration (regeneration) berechnen - Tod bei 0 HP - Listener: damage_requested, heal_requested - Event: health_changed, regeneration_changed, entity_died ### ShieldSystem (shield_system.gd) - Schild (shield) und Schildregeneration (shield_regeneration) berechnen - Wie zweite Lebensleiste - Event: shield_changed, shield_broken, shield_regenerated ### RespawnSystem (respawn_system.gd) - Respawn bei Taverne mit vollen Leben und Schild - Tod-Timer (3s) - Listener: entity_died - Event: respawn_tick, player_respawned ### AbilitySystem (ability_system.gd) - Single, AOE, Utility, Ult - Auto-Attack - Listener: ability_use_requested, auto_attack_tick - Event: attack_executed ## BuffSystem (buff_system.gd) - Passive - Listener: role_changed - Event: buff_changed ### CooldownSystem (cooldown_system.gd) - Cooldown-Tracking, GCD - Listener: attack_executed - Event: cooldown_tick ### DamageSystem (damage_system.gd) - Schadensberechnung - Listener: attack_executed - Event: damage_requested, heal_requested ### AggroSystem (aggro_system.gd) - Aggro-Tabellen, Decay, Zielwahl, Kampfstatus, Nearby-Alerting - Listener: damage_dealt, heal_requested, entity_died, enemy_detected, target_requested - Event: target_changed, combat_state_changed, enemy_target_changed, enemy_engaged ### EnemyAISystem (enemy_ai_system.gd) - Gegner-States (Idle/Chase/Attack/Return), Bewegungsbefehle - Listener: enemy_target_changed, entity_died - Event: enemy_state_changed ### SpawnSystem (spawn_system.gd) - Entity-Erstellung, Portal/Gate-Spawning, Dungeon-Clear - Export: mode ("world" / "dungeon") - Listener: entity_died, health_changed - Event: portal_spawn, portal_defeated, dungeon_cleared # Szenen ## Welt - world.tscn — Hauptszene (100x100m) - NavigationRegion3D (Wegfindung für Gegner) - Boden (MeshInstance3D, 100x100m PlaneMesh, Gras-Noise-Textur) - Kollision (StaticBody3D, WorldBoundaryShape3D) - Licht (DirectionalLight3D, 45°, Schatten) - Taverne (StaticBody3D, BoxMesh, Mitte der Karte, Spieler-Spawn/Respawn) - Spieler (Instanz von player.tscn, Spawn bei Taverne) - HUD (Instanz von hud.tscn) ## Spieler - player.tscn — CharacterBody3D - Gruppe (player) - Kollision (CapsuleShape3D, 1.8m x 0.3m) - Mesh (CapsuleMesh) - CameraPivot (Node3D, Kopfhöhe, camera.gd) - Camera3D (hinter/über Spieler)w - Movement (Node, movement.gd) - Combat (Node, combat.gd) - Role (Node, role.gd) - Targeting (Node, targeting.gd) - Health (Node, health.gd) - Shield (Node, shield.gd) - player.gd — Kern, verbindet Komponenten, Sichtbarkeit bei Tod/Respawn - camera.gd — LMB freies Umsehen, RMB Kamera + Laufrichtung anpassen - movement.gd — Bewegung (WASD relativ zur Kamera), Springen, Schwerkraft - Stats: player_stats.tres (→ Resources) ## Kampf - combat.gd — Input-Handler: emittiert ability_use_requested, auto_attack_tick (Logik → CombatSystem) - targeting.gd — Raycast/Klick/TAB: emittiert target_requested, speichert Ziel aus Events (Logik → AggroSystem) - role.gd — Rollenwechsel ALT+1 bis ALT+3 (Tank/Schaden/Heiler), tauscht AbilitySet - Auto-Attack: Automatisch bei anvisiertem Gegner im Kampf - Jede Rolle hat ein eigenes AbilitySet (→ Resources) - Beim Rollenwechsel wird das AbilitySet getauscht - Elemente und Modifikatoren verändern Abilities nachträglich ## Gegner - enemy.tscn — CharacterBody3D - Gruppe (enemies) - Kollision (CapsuleShape3D) - Mesh (SphereMesh, Platzhalter) - Health (Node, health.gd) - Shield (Node, shield.gd) - HitArea (Area3D, Trefferbereich des Gegners) - CollisionShape3D (CapsuleShape3D) - DetectionArea (Area3D, Erkennungsradius) - CollisionShape3D (SphereShape3D) - NavigationAgent3D (Wegfindung) - EnemyMovement (Node, enemy_movement.gd) - Healthbar (Sprite3D + SubViewport, über dem Gegner, healthbar.gd) - SubViewport - Border (ColorRect, gelb, sichtbar bei Anvisierung) - HealthBar (ProgressBar, grün) - ShieldBar (ProgressBar, blau) - enemy.gd — Daten-Holder (state, target, spawn_position, portal), Detection-Area → enemy_detected, Gruppe "enemies" (State Machine → EnemyAISystem) - enemy_movement.gd — Empfängt Bewegungsbefehle, führt NavAgent + move_and_slide aus (Entscheidungen → EnemyAISystem) - Stats: enemy_stats.tres (→ Resources) - Aggro-Regeln: - Schaden = Aggro (1:1) - Heilung = Aggro (0.5x) - Tank = Aggro-Multiplikator (2x) - Aggro verfällt -1/s - Spieler im Portal-Radius: Aggro bleibt bei mindestens 1 - Außerhalb 10m Portal-Radius: Aggro verfällt 1% * 2 je s (1%, 2%, 4%, 8%, ...) - Ohne Aggro: Gegner kehrt zum Portal zurück, regeneriert 10% Leben/s bis 100%, dann 1%/s - Bei Spieler-Tod → Aggro auf 0 ## Portal - portal.tscn — StaticBody3D - Gruppe (portals) - Kollision (CylinderShape3D) - Mesh (CylinderMesh, blau) - Health (Node, health.gd) - HitArea (Area3D, Trefferbereich) - CollisionShape3D - DetectionArea (Area3D, 10m Radius, Auto-Targeting bei Betreten) - CollisionShape3D (SphereShape3D) - Healthbar (Sprite3D + SubViewport, healthbar.gd) - portal.gd — Gruppe "portals", Detection-Area Signal (Death-Handling → SpawnSystem) - Stats: portal_stats.tres (→ Resources) - Phase 1: Angreifbar, HP-Bar, spawnt 3 Gegner bei 85%/70%/55%/40%/25%/10% Leben - Portal = Spawnpunkt, 10m Aggro-Radius ## Gate - gate.tscn — StaticBody3D (keine Kollision) - Mesh (CylinderMesh, grün, leuchtend) - GateArea (Area3D, 3m Radius, Spieler-Erkennung) - CollisionShape3D (SphereShape3D) - gate.gd — Konfigurierbar: target_scene, is_exit - Eingangs-Gate: Prüft nach 0.5s ob Spieler bereits in GateArea steht, speichert Portal-Position - Exit-Gate: 1s Aktivierungsdelay (verhindert Re-Triggern bei Spawn) - Beide Gates bestehen solange Boss lebt, verschwinden bei dungeon_cleared ## Dungeon - dungeon.tscn — Geschlossener Raum (15x90m, Wände, dunkles Licht) - Systems (HealthSystem, CombatSystem, AggroSystem, EnemyAISystem, SpawnSystem mode="dungeon") - NavigationRegion3D (Wegfindung) - Boden (PlaneMesh, dunkle Textur) - 4 Wände (StaticBody3D + BoxMesh, 3m hoch) - Spieler (Instanz von player.tscn, Position 0/1/-5) - HUD (Instanz von hud.tscn) - Gegnergruppen bei (15x15, 15x30, 15x45, 15x60), je 4 Gegner - Boss (Instanz von boss.tscn) - Exit-Gate (Instanz von gate.tscn, is_exit=true, Ecke bei -6/0/-4) - DungeonManager (Node, dungeon_manager.gd) - dungeon_manager.gd — Stellt Spieler wieder her (Boss-Tod/Dungeon-Clear → SpawnSystem) ## Boss - boss.tscn — CharacterBody3D (boss.gd) - Gruppe (enemies, boss) - Kollision (CapsuleShape3D, größer als Enemy) - Mesh (SphereMesh, lila, 1.5x Größe) - Health (Node, health.gd) - Shield (Node, shield.gd) - HitArea, DetectionArea, NavigationAgent3D, EnemyMovement - Healthbar (Sprite3D + SubViewport, healthbar.gd) - boss.gd — Erbt von enemy.gd, Gruppe "boss" - Stats: boss_stats.tres (→ Resources) ## GameState - game_state.gd — Autoload, speichert Spielerzustand zwischen Szenenwechseln - save_player(player), restore_player(player), clear_player(), clear() - returning_from_dungeon — Spieler kommt aus Dungeon, spawnt bei Gate-Position - dungeon_cleared — Boss tot, Gates werden entfernt, Spieler spawnt bei Taverne - portal_position (Vector3, Position des Gates für Rückkehr + Wiederherstellung) ## Gemeinsame Komponenten - health.gd — Registriert Entity beim HealthSystem mit EntityStats, deregistriert bei _exit_tree - shield.gd — Registriert Entity beim HealthSystem mit EntityStats, deregistriert bei _exit_tree - healthbar.gd — Liest Health/Shield (optional) vom Parent, gelber Rand bei Anvisierung, blauer Lebensbalken wenn Spieler Ziel ist (nur bei Gegnern) ## Resources ### EntityStats (entity_stats.gd) - Felder: max_health, health_regen, max_shield, shield_regen_delay, shield_regen_time - player_stats.tres → Player — health=100, regen=1/s, shield=50, delay=3s, regen_time=5s - enemy_stats.tres → Enemy — health=100, regen=0, shield=50, delay=3s, regen_time=5s - boss_stats.tres → Boss — health=500, regen=0, shield=100, delay=5s, regen_time=8s - portal_stats.tres → Portal — health=500, regen=0, shield=0 ### Ability (ability.gd) - Felder: ability_name, type, damage, ability_range, cooldown, uses_gcd, aoe_radius, is_heal, passive_stat - Typen: Single, AOE, Utility, Ult, Passive - ability_modifier.gd — Verändert Ability (Element, Beruf, Prestige) - Schadens-Klasse: - AA: 25 Schaden, 10m - 1 Single: 30 Schaden, 20m Range, 2s CD, GCD - 2 AOE: 20 Schaden, 5m Range, 3s CD, GCD - 3 Utility: Schild sofort auf 100%, 5s CD, kein GCD - 4 Ult: 5x Single (50 Schaden) + 2x AOE 3m (20 Schaden), 20m Range, 15s CD, GCD - 5 Passive: 50% mehr Schaden Aura (permanent aktiv, kein CD) - Tank-Klasse: - AA: 5 Schaden, 3m - 1 Single: 15 Schaden, 3m Range, 2s CD, GCD - 2 AOE: 10 Schaden, 10m Range, 3s CD, GCD - 3 Utility: Schild sofort auf 100%, 5s CD, kein GCD - 4 Ult: Schild 300%, 20s CD, GCD - 5 Passive: 50% mehr Schild Aura (permanent aktiv, kein CD) - Heiler-Klasse: Kein Autotarget, Selfheal wenn kein Spieler anvisiert - AA: 1 Heilung, 20m - 1 Single: 15 Heilung, 20m Range, 2s CD, GCD - 2 AOE: 10 Heilung, 20m Range, 3s CD, GCD - 3 Utility: Schild sofort auf 100%, 5s CD, kein GCD - 4 Ult: 25 Heal Single + 10 AOE Heal 3m radius, 20m Range, 15s CD, GCD - 5 Passive: 50% mehr Heal Aura (permanent aktiv, kein CD) ### AbilitySet (ability_set.gd) - Felder: abilities (Array[Ability]), aa_damage, aa_range, aa_is_heal - damage_set.tres → Rolle Damage - tank_set.tres → Rolle Tank - healer_set.tres → Rolle Healer ## HUD - hud.tscn — CanvasLayer (hud.gd) - HealthBar (ProgressBar, links oben, Label "50/100") - ShieldBar (ProgressBar, links oben, unter HealthBar, Label "25/50") - RespawnTimer (Label, mitte, Countdown bei Tod) - AbilityBar (HBoxContainer, mitte unten) - RoleIcon (Label, T=Tank, D=Schaden, H=Heiler) - Abilities (Label, Fähigkeiten 1-4, Passive P) - hud.gd — Reagiert auf Events, aktualisiert HealthBar/ShieldBar/AbilityBar/RespawnTimer ## Events - event_bus.gd — Autoload-Singleton, globale Signals - Intentionen (Input → System): - ability_use_requested(player, ability_index) — Spieler will Ability nutzen - auto_attack_tick(attacker) — Auto-Attack bereit - target_requested(player, target) — Spieler will Ziel anvisieren - enemy_detected(enemy, player) — Spieler in Detection-Area - Ergebnisse (System → Node): - combat_state_changed(player, in_combat) — Kampfstatus geändert (AggroSystem) - enemy_state_changed(enemy, new_state) — Gegner-State geändert (EnemyAISystem) - enemy_target_changed(enemy, target) — Gegner-Ziel geändert (AggroSystem) - Kampf: - attack_executed(attacker, position, direction, damage) — Angriff wurde ausgeführt - damage_dealt(attacker, target, damage) — Schaden wurde verteilt - damage_requested(attacker, target, amount) — Schaden zwischen Szenen anfordern - Entity: - entity_died(entity) — Entity ist gestorben - health_changed(entity, current, max) — Leben hat sich verändert - shield_changed(entity, current, max) — Schild hat sich verändert - shield_broken(entity) — Schild ist auf 0 gefallen - shield_regenerated(entity) — Schild ist wieder voll - Spieler: - target_changed(player, target) — Spieler hat neues Ziel anvisiert - player_respawned(player) — Spieler ist respawnt - role_changed(player, role_type) — Spieler hat Rolle gewechselt - respawn_tick(timer) — Respawn-Countdown Update - cooldown_tick(cooldowns, max_cooldowns, gcd_timer) — Cooldown-Update für HUD - Gegner: - enemy_engaged(enemy, target) — Gegner hat Spieler anvisiert - Portal: - portal_spawn(portal, enemies) — Portal hat Gegner gespawnt - portal_defeated(portal) — Portal besiegt, wird Gate - Dungeon: - dungeon_cleared() — Boss tot, Dungeon gesäubert