# Projektstruktur ## Ordnerstruktur ``` player/ — Spieler (.tscn + .gd) enemy/ — Gegner + Boss (.tscn + .gd) portal/ — Portal + Gate (.tscn + .gd) dungeon/ — Dungeon (.tscn + .gd) hud/ — HUD (.tscn + .gd) world/ — Hauptszene (.tscn + .gd) systems/ — 10 Gameplay-Systeme (.gd) autoload/ — EventBus, Stats, GameState (.gd) components/ — Shared UI: healthbar (.gd) resources/ stats/ — Stats-Klassen (.gd) + Daten (.tres) roles/ — Ability/AbilitySet-Klassen (.gd) + Rollen-Daten damage/ — set.tres + abilities/ tank/ — set.tres + abilities/ healer/ — set.tres + abilities/ ``` ## Szenenbaum - Welt - Systems (10 Systeme als Child-Nodes) - Taverne - Player - Portale (dynamisch) - Gegner - HUD ## Architektur - Resources (stats/, roles/) — Datenmodelle + Basiswerte, werden später zu Go-Structs + DB - Autoload (Stats) — Laufzeit-Datenhaltung, wird später zu Server-API-Client - Systeme — Spiellogik, lesen/schreiben über Stats - Szenen — Views, rendern + Input, kein Gameplay-State - EventBus — Signale zwischen Szenen und Systemen - Flow: Szene → Input → EventBus → System → Stats → EventBus → Szene - Szenen kennen sich nicht - Innerhalb einer Szene: direkter Zugriff auf Geschwister erlaubt # Autoload ## EventBus (autoload/event_bus.gd) - Intentionen (Input → System): - ability_use_requested(player, ability_index) - enemy_detected(enemy, player) - Kampf: - attack_executed(attacker, position, direction, damage) - damage_dealt(attacker, target, damage) - damage_requested(attacker, target, amount) - heal_requested(healer, target, amount) - Entity: - entity_died(entity) - health_changed(entity, current, max) - shield_changed(entity, current, max) - shield_broken(entity) - shield_regenerated(entity) - Spieler: - target_changed(player, target) - player_respawned(player) - role_changed(player, role_type) - respawn_tick(timer) - cooldown_tick(cooldowns, max_cooldowns, gcd_timer) - Buff: - buff_changed(entity, stat, value) - Gegner: - enemy_engaged(enemy, target) - Portal: - portal_spawn(portal, enemies) - portal_defeated(portal) - Dungeon: - dungeon_cleared() - Reserviert: - auto_attack_tick, target_requested, combat_state_changed, enemy_state_changed, enemy_target_changed, regeneration_changed ## Stats (autoload/stats.gd) - Speichert aktuelle Attribute aller Entities - Basiswerte aus BaseStats Resource - player_cache für Szenenwechsel ## GameState (autoload/game_state.gd) - Speichert Rolle + Position zwischen Szenenwechseln # Resources ## resources/stats/ ### BaseStats (base_stats.gd) - max_health, health_regen, max_shield, shield_regen_delay, shield_regen_time ### PlayerStats (player_stats.gd, extends BaseStats) - speed, jump_velocity, target_range, combat_timeout, respawn_time, gcd_time, aa_cooldown ### EnemyStats (enemy_stats.gd, extends BaseStats) - speed, attack_range, attack_cooldown, attack_damage, regen_fast, regen_slow, aggro_decay, portal_radius, alert_radius ### BossStats (boss_stats.gd, extends EnemyStats) ### PortalStats (portal_stats.gd, extends BaseStats) - spawn_count, thresholds ## resources/roles/ ### Ability (ability.gd) - ability_name, type, damage, ability_range, cooldown, uses_gcd, aoe_radius, icon, is_heal, passive_stat - Typen: Single, AOE, Utility, Ult, Passive ### AbilitySet (ability_set.gd) - abilities (Array[Ability]), aa_damage, aa_range, aa_is_heal ### AbilityModifier (geplant) - Verändert Ability (Element, Beruf, Prestige) ### Rollen-Ordner (damage/, tank/, healer/) - set.tres — AbilitySet der Rolle - abilities/ — 5 Ability .tres pro Rolle (single, aoe, utility, ult, passive) # Systeme (systems/) - In jeder Root-Szene instanziert (world.tscn, dungeon.tscn) - Entities registrieren/deregistrieren sich bei Stats - Systeme lesen/schreiben über Stats ### HealthSystem (health_system.gd) - Leben und Lebensregeneration berechnen, Tod bei 0 HP - Listener: damage_requested, heal_requested - Event: health_changed, entity_died ### ShieldSystem (shield_system.gd) - Schild und Schildregeneration berechnen - absorb(entity, amount) → remaining damage - Event: shield_changed, shield_broken, shield_regenerated ### RespawnSystem (respawn_system.gd) - Respawn bei Taverne mit vollen Leben und Schild - Listener: entity_died - Event: respawn_tick, player_respawned ### AbilitySystem (ability_system.gd) - Ability-Ausführung (Single, AOE, Utility, Ult) + Auto-Attack in _process - Listener: ability_use_requested - Event: attack_executed, damage_requested, heal_requested ### BuffSystem (buff_system.gd) - Passive-Buffs (damage/heal/shield Multiplikatoren in Stats) - Listener: role_changed - Event: buff_changed, shield_changed ### CooldownSystem (cooldown_system.gd) - Cooldown-Tracking, GCD, AA-Timer per Entity - register/deregister per Entity, direkte Funktionsaufrufe vom AbilitySystem - Event: cooldown_tick ### DamageSystem (damage_system.gd) - Reserviert für spätere Schadensberechnung (aktuell leer) ### AggroSystem (aggro_system.gd) - Aggro-Tabellen, Decay, Zielwahl, Nearby-Alerting - Listener: damage_dealt, heal_requested, entity_died, enemy_detected - Event: enemy_engaged ### EnemyAISystem (enemy_ai_system.gd) - ATTACK-State: Range-Check, Timer, Schaden - Iteriert Enemies in _physics_process - Event: damage_requested ### SpawnSystem (spawn_system.gd) - Portal-HP-Schwellen-Spawning - Listener: health_changed, entity_died - Event: portal_spawn # Szenen - Szenen sind Views — rendern, Input senden, Events empfangen - Kein Gameplay-State in Szenen (liegt in Stats Autoload) - Entities registrieren sich bei Stats in _ready(), deregistrieren in _exit_tree() - Stats cached Spieler-Werte automatisch bei Szenenwechsel (player_cache) ## Welt (world/) - world.tscn — Hauptszene (100x100m) - Systems (alle 10 Systeme als Child-Nodes) - NavigationRegion3D - Boden (MeshInstance3D, 100x100m PlaneMesh) - Kollision (StaticBody3D, WorldBoundaryShape3D) - Licht (DirectionalLight3D, 45°, Schatten) - Taverne (StaticBody3D, BoxMesh, Mitte der Karte) - Spieler (Instanz von player.tscn) - HUD (Instanz von hud.tscn) - PortalSpawner (Node, portal_spawner.gd) ## Spieler (player/) - player.tscn — CharacterBody3D - Gruppe (player) - Kollision (CapsuleShape3D, 1.8m x 0.3m) - Mesh (CapsuleMesh) - CameraPivot (Node3D, camera.gd) - Camera3D - Movement (Node, movement.gd) — WASD + Springen, liest Werte von Stats - Combat (Node, combat.gd) — Input-Handler, emittiert ability_use_requested - Role (Node, role.gd) — Rollenwechsel ALT+1/2/3, emittiert role_changed - Targeting (Node, targeting.gd) — Klick/TAB, emittiert target_requested - player.gd — Registriert bei Stats mit PlayerStats Resource, Sichtbarkeit bei Tod/Respawn - camera.gd — LMB freies Umsehen, RMB Kamera + Laufrichtung ## Gegner (enemy/) - enemy.tscn — CharacterBody3D - Gruppe (enemies) - Kollision (CapsuleShape3D) - Mesh (SphereMesh) - HitArea (Area3D) - DetectionArea (Area3D, emittiert enemy_detected) - NavigationAgent3D - EnemyMovement (Node, enemy_movement.gd) — Empfängt Bewegungsbefehle - Healthbar (Sprite3D + SubViewport, healthbar.gd) — liest HP/Shield von Stats - enemy.gd — Registriert bei Stats mit EnemyStats Resource, Detection-Area Signal - 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 Portal-Radius: Aggro verfällt exponentiell (1%, 2%, 4%, 8%, ...) - Ohne Aggro: Gegner kehrt zum Portal zurück, regeneriert - Bei Spieler-Tod → Aggro auf 0 ## Boss (enemy/) - boss.tscn — wie enemy.tscn aber größer (Mesh lila, 1.5x) - Gruppe (enemies, boss) - boss.gd — Erbt von enemy.gd, registriert bei Stats mit BossStats Resource ## Portal (portal/) - portal.tscn — StaticBody3D - Gruppe (portals) - Kollision (CylinderShape3D) - Mesh (CylinderMesh, blau) - HitArea (Area3D) - DetectionArea (Area3D, Auto-Targeting bei Betreten) - Healthbar (Sprite3D + SubViewport, healthbar.gd) - portal.gd — Registriert bei Stats mit PortalStats Resource - Spawnt Gegner bei HP-Schwellen (→ SpawnSystem) ## Gate (portal/) - gate.tscn — StaticBody3D (keine Kollision) - Mesh (CylinderMesh, grün, leuchtend) - GateArea (Area3D, 3m Radius) - gate.gd — Konfigurierbar: target_scene, is_exit - Beide Gates bestehen solange Boss lebt, verschwinden bei dungeon_cleared ## Dungeon (dungeon/) - dungeon.tscn — Geschlossener Raum (15x90m, Wände, dunkles Licht) - Systems (alle 10 Systeme, temporär bis Welt parallel läuft) - NavigationRegion3D - Boden, 4 Wände (StaticBody3D + BoxMesh, 3m hoch) - Spieler (Instanz von player.tscn) - HUD (Instanz von hud.tscn) - Gegnergruppen (4x4 Gegner) - Boss (Instanz von boss.tscn) - Exit-Gate (Instanz von gate.tscn, is_exit=true) - DungeonManager (Node, dungeon_manager.gd) - Eigene Systems bis Welt parallel läuft (geplant: Reparenting) ## HUD (hud/) - hud.tscn — CanvasLayer - HealthBar (ProgressBar, Label) - ShieldBar (ProgressBar, Label) - RespawnTimer (Label, Countdown bei Tod) - AbilityBar (HBoxContainer, RoleIcon + Abilities 1-4 + Passive) - hud.gd — Reagiert auf Events, liest Werte von Stats # Abilities (Werte) - Schadens-Klasse: - AA: 10 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, 50m (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, 50m (permanent aktiv, kein CD) - Heiler-Klasse: - 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, 50m (permanent aktiv, kein CD)