Files
mmo/plan.md
Marek Lenczewski 73af6abeb7 update
2026-04-02 19:30:44 +02:00

286 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Projektstruktur
## Ordnerstruktur
Drei Grundordner nach Verantwortung. Resources liegen bei ihren Skripten.
```
scenes/ — Darstellung + Input
healthbar.gd — Shared Component
player/ — Spieler + player_stats
role/ — Rollenwechsel + Ability/AbilitySet-Klassen
damage/ — set.tres + abilities/
tank/ — set.tres + abilities/
healer/ — set.tres + abilities/
enemy/ — Gegner + Boss + enemy_stats + boss_stats
portal/ — Portal + Gate + portal_stats
dungeon/ — Dungeon + dungeon_manager
hud/ — HUD
world/ — Hauptszene + portal_spawner
systems/ — Spiellogik
aggro/ — AggroSystem (system, tracker, decay, events) + aggro_config
9× *_system.gd — health, shield, damage, ability, cooldown, enemy_ai, respawn, spawn, buff
autoloads/ — Globaler Zustand
event_bus.gd
game_state.gd
stats/ — stats.gd + base_stats.gd
```
## 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 (systems/aggro/)
- Systemweite Werte in AggroConfig Resource (resources/stats/aggro_config.tres)
- aggro_system.gd — Parent, Config halten, Children verdrahten
- aggro_tracker.gd — Aggro-Tabellen, Players-in-Range, Zielwahl, Radius-Helper
- aggro_decay.gd — Combat-Timer, Decay-Berechnung, Spread, Alert
- aggro_events.gd — Signal-Handler (damage_dealt, heal_requested, entity_died, enemy_detected, enemy_lost)
- 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 (Werte in AggroConfig Resource):
- Aufbau:
- Schaden = Aggro (1:1), Tank 2x Multiplikator
- Heilung = 0.5x Aggro auf alle Gegner die Heiler kennen
- Aggro-Spread: 50% des Aggro an Gegner im alert_radius (10m)
- Detection-Area (10m): +1 Aggro, Alert an Nachbarn im alert_radius
- Kampfstatus:
- Spieler in DetectionArea → immer im Kampf (kein Decay)
- Spieler verlässt DetectionArea → 5s Combat-Timeout, dann Decay
- Schaden verursachen setzt Combat-Timer zurück
- Abbau (nach Combat-Timeout):
- Basis: -aggro_decay/s (default 1.0)
- Exponentieller Decay basierend auf Zeit seit Kampfende (1%·2^sekunden)
- 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)