# DBD Plugin — План разработки ## Архитектурные принципы - **KISS**: Нет абстракций ради абстракций. Простые классы с одной ответственностью. - **DRY**: Общая логика в утилитах, не копипаста. - **SOLID**: SRP, OCP, LSP, ISP, DIP. Max 150 строк/файл. --- ## Статус реализации ### ✅ Этап 0: Скелет проекта - [x] `build.gradle` (Paper 1.21.1, Java 21) - [x] `plugin.yml` с пермишнами - [x] `DBDPlugin.java` — onEnable/onDisable - [x] `ConfigManager` — загрузка yaml без перезаписи - [x] `LocationsConfig` — координаты объектов - [x] `GameConfig` — все балансные цифры (BossBar, carry, heal limits, lobby timers, sizes, kick cooldown, sabotage) ### ✅ Этап 1: Core Game Loop - [x] `GameState` enum - [x] `GameSession` — хранит игроков, фазу, таймер; передаёт `GateManager` и `collapseSeconds` в `EndgamePhase` - [x] `Phase` interface - [x] `LobbyPhase` — таймер **45 сек при 4 игроках**, **15 сек при 5**, min-players=4, анонс на ключевых секундах - [x] `RoleAssigner` + `RoleQueue` — выбор киллера; применяет `GENERIC_SCALE` через Attribute API - [x] `RoleAssignPhase` — телепорты, задержка 5 сек - [x] `GameplayPhase` — полная логика (см. ниже) - [x] `EndgamePhase` — `collapseSeconds` из конфига, таймер в `Sidebar`, `GateManager` из сессии, Adventure API title - [x] `/dbd join`, `/dbd leave`, `/dbd forcestart`, `/dbd stop`, `/dbd reload`, `/dbd lobby`, `/dbd setlobby` ### ✅ Этап 2: Игроки и состояния - [x] `BasePlayer`, `Survivor`, `Killer` - [x] `PlayerState`: HEALTHY, INJURED, DOWNED, HOOKED, CARRIED, DEAD, ESCAPED - [x] `StateMachine` — переходы с валидацией - [x] `PlayerManager` — map UUID → BasePlayer - [x] `SpawnPosition` — телепорт из конфига - [x] Перевод в `GameMode.SPECTATOR` при `PlayerState.DEAD` (в `GameplayPhase.checkWinConditions` и `HookSacrifice`) - [x] Размеры через `Attribute.GENERIC_SCALE`: Survivor=1.0, Killer=1.5 (в `RoleAssigner` и `GameplayPhase`) ### ✅ Этап 3: Киллер - [x] `KillerController` — без дублирующей регистрации `AttackListener` - [x] `KillerAttack` — ЛКМ, кулдаун 2.5 с, hitbox - [x] `HitValidator` — line of sight, расстояние - [x] `DamageHandler` — Healthy→Injured, Injured→Downed - [x] `KillerCarry` — побег через **спам пробела** (PlayerJumpListener), шкала в ActionBar, Speed I при побеге - [x] `KillerMovement` — скорость из конфига, замедление после удара - [x] `GeneratorKick` — Shift 3 сек → −20% прогресса, кулдаун 30 сек, progress bar - [x] `BossBarManager` — BossBar с градиентом по дистанции до маньяка, читает все параметры из конфига ### ✅ Этап 4: Выживший - [x] `SurvivorController` — передаёт `GameConfig` в `SurvivorHealing` - [x] `SurvivorMovement` — sprint, exhaustion - [x] `SurvivorHealing` — таймеры из конфига (other=15 сек, self=30 сек), лимит **4 лечений** из конфига, sneak-check, range-check - [x] Downed movement — crawl 30% скорости ### ✅ Этап 5: Генераторы - [x] `Generator` — `setUnderRegression(bool, ticks)`, `wasKicked()` - [x] `GeneratorManager` — `getCompletedCount()` считает живое состояние - [x] `GeneratorRepair` — ПКМ, прогресс в ActionBar; при фейле skillcheck: `setUnderRegression` + **компас маньяку** на `compass-duration-seconds` - [x] `GeneratorRegression` — скорость полностью из конфига (`regression-rate`, `kick-regression-rate`), без хардкодированных констант - [x] `SkillCheck` + `SkillCheckUI` — QTE система ### ✅ Этап 6: Крюки - [x] `Hook` — поле `disabled` + `isDisabled()`/`setDisabled()` - [x] `HookManager` — `maxHooks` из конфига, `tryHookSurvivor` проверяет лимит → при превышении сразу `DEAD`; `findNearestUnoccupiedHook` и `findAvailableHook` учитывают `isDisabled()` - [x] `HookStage` — Stage 1 (60 с), Stage 2 (60 с) - [x] `HookStruggle` — `struggleIntervalTicks` из конфига (`hooks.struggle-interval`) - [x] `HookRescue` — 60 тиков (3 сек из конфига), sneak-check, range-check, Speed I после спасения - [x] `HookSacrifice` — смерть + **SPECTATOR mode** - [x] `HookSabotage` — выживший держит Shift **10 сек** → крюк отключён, восстановление **60 сек** (всё из конфига), progress bar, broadcast ### ✅ Этап 7: UI - [x] `ActionBar` — статус, прогресс-бары - [x] `Sidebar` — сердца ♥ (по `hooksTaken`), цвета ников по состоянию, `GeneratorManager` (живой счёт), таймер коллапса - [x] `TitleUI`, `ProgressBar`, `StatusIcons` - [x] `BossBarManager` — BossBar для каждого выжившего, градиент по дистанции - [x] Шкала wiggle в `KillerCarry.showWiggleProgress()` (ActionBar) ### ✅ Этап 8: Паллеты и окна - [x] `Pallet`, `PalletManager`, `PalletDrop`, `PalletBreak`, `PalletStun` - [x] `Window`, `WindowManager`, `WindowVault`, `WindowFastVault` ### ✅ Этап 9: Ворота и люк - [x] `ExitGate` — `savedProgress` + `getSavedProgress()`/`saveProgress()`/`restoreProgress()`/`setProgressDirect()`; `reset()` чистит `savedProgress` - [x] `GateManager` — `activateEndgame()` только включает питание, **без авто-открытия** - [x] `GateOpening` — **линейный прогресс** (`setProgressDirect`), сохраняет/восстанавливает прогресс при уходе/возврате игрока - [x] `Hatch`, `HatchCondition`, `HatchEscape` ### ✅ Этап 10: Звук - [x] `TerrorRadiusSound` — `terrorRadius` параметр конструктора (из конфига), дефолт 32 - [x] `SoundManager`, `GeneratorSound`, `SoundLevels` ### ✅ Этап 11: Слушатели - [x] `PlayerJumpListener` — прыжки для wiggle при переноске - [x] `PlayerInteractListener` — `setOnKillerSneak` + `PlayerToggleSneakEvent` (маньяк → GeneratorKick, выживший → HookSabotage) - [x] `PlayerMoveListener`, `PlayerQuitListener`, `DamageListener` ### ✅ Этап 12: Данные и хранение - [x] `DataStorage`, `YamlStorage`, `SQLiteStorage`, `PlayerStats`, `MatchResult` --- ## ❌ Не реализовано (следующие этапы) ### Пользовательские лобби - [ ] `LobbySession` — пользовательское лобби (пароль, владелец, приватность) - [ ] `LobbyRegistry` — реестр серверных и пользовательских лобби, YAML persistence - [ ] `/dbd create [password] [private]` — для обычных игроков (сейчас требует `mdbd.admin`) - [ ] `/dbd join ` — вход в конкретное лобби ### Механики крюков - [ ] `HookRecovery` — самостоятельное слезание с крюка на Stage 2 ### Перки - [ ] `IPerk` интерфейс, `PerkRegistry` - [ ] Survivor: `SelfCarePerk`, `DeadHardPerk`, `SprintBurstPerk`, `BorrowedTimePerk` - [ ] Killer: `HexRuinPerk`, `CorruptInterventionPerk`, `BBQChiliPerk` ### Предметы из конфига - [ ] `ChestLoot` — читать веса и типы предметов из `game.yml` (сейчас захардкожено) --- ## Конфиги (game.yml) — актуальные ключи ```yaml lobby: min-players: 4 max-players: 5 countdown-4-players: 45 countdown-5-players: 15 role-assign-delay: 5 players: survivor-scale: 1.0 killer-scale: 1.5 generators: total-count: 7 required-count: 5 repair-seconds: 90 regression-rate: 0.25 kick-regression-rate: 2.5 kick-regression-percent: 20.0 kick-duration-seconds: 30 kick-cooldown-seconds: 30 kick-charge-seconds: 3 interaction-range: 3.0 hooks: stage1-seconds: 60 stage2-seconds: 60 struggle-interval: 2 max-hooks: 3 interaction-range: 3.0 rescue-seconds: 3 sabotage-seconds: 10 sabotage-recovery-seconds: 60 healing: other-heal-seconds: 15 self-heal-seconds: 30 medkit-bonus: 0.5 interrupt-on-move: true max-heals-per-match: 4 heal-range: 3.0 carry: escape-jumps: 15 escape-speed-seconds: 3 jump-fill-percent: 6.67 killer: attack-cooldown: 2.5 attack-range: 3.0 pallet-stun-seconds: 2.0 pallet-break-seconds: 3.0 terror-radius: 32 pallet-interaction-range: 3.0 bossbar: enabled: true title: "☠ МАНЬЯК РЯДОМ ☠" color: RED style: SOLID appear-range: 32 full-range: 8 endgame: gate-open-seconds: 20 collapse-seconds: 120 chest-open-seconds: 3 gate-interaction-range: 3.0 killer-notification: compass-duration-seconds: 5 scoreboard: show-hearts: true heart-symbol: "♥" color-healthy: "WHITE" color-injured: "RED" color-healing: "GREEN" color-hooked: "DARK_RED" ```