feat(gameplay): implement hook sabotage, generator kick, jump listener, and boss bar UI
- Add HookSabotage system for survivors to disable hooks temporarily - Add GeneratorKick killer ability to regress generator progress - Add PlayerJumpListener to track survivor jump actions - Add BossBarManager for displaying game state and objectives - Update generator regression logic to support killer kick mechanic - Update KillerController to integrate generator kick ability - Update PlayerInteractListener to handle new interaction types - Refactor game phases to use BossBarManager for UI updates - Update .gitignore to exclude compiled bin/ directory - Simplify PLAN.md documentation for easier maintenance
This commit is contained in:
parent
3d6204cc83
commit
89dc9eb00d
78 changed files with 2293 additions and 1210 deletions
463
PLAN.md
463
PLAN.md
|
|
@ -4,330 +4,203 @@
|
|||
|
||||
- **KISS**: Нет абстракций ради абстракций. Простые классы с одной ответственностью.
|
||||
- **DRY**: Общая логика в утилитах, не копипаста.
|
||||
- **SOLID**:
|
||||
- SRP: Один класс = одна задача (StateManager только состояния, DamageHandler только урон)
|
||||
- OCP: Перки через интерфейс, не if-else везде
|
||||
- LSP: KillerController и SurvivorController наследуются от PlayerController корректно
|
||||
- ISP: Маленькие интерфейсы (IRepairable, IHealable, IHookable)
|
||||
- DIP: Высокоуровневые модули зависят от абстракций, не от имплементаций
|
||||
- max 150 строк/файл
|
||||
## Структура папок (max 150 строк/файл)
|
||||
- **SOLID**: SRP, OCP, LSP, ISP, DIP. Max 150 строк/файл.
|
||||
|
||||
```
|
||||
src/main/java/com/dbd/plugin/
|
||||
├── DBDPlugin.java # Точка входа (max 50 строк)
|
||||
├── config/
|
||||
│ ├── ConfigManager.java # Загрузка всех yaml
|
||||
│ ├── LocationsConfig.java # Координаты объектов
|
||||
│ └── GameConfig.java # Балансные цифры
|
||||
├── core/
|
||||
│ ├── GameManager.java # Главный контроллер игр
|
||||
│ ├── GameSession.java # Одна игра (lobby -> end)
|
||||
│ ├── GameState.java # Enum: LOBBY, IN_GAME, ENDING
|
||||
│ └── GameEventBus.java # Внутренние события игры
|
||||
├── phase/
|
||||
│ ├── Phase.java # Interface: enter(), tick(), exit()
|
||||
│ ├── LobbyPhase.java # Ожидание игроков
|
||||
│ ├── RoleAssignPhase.java # Назначение ролей, таймер 5сек
|
||||
│ ├── GameplayPhase.java # Основная игра
|
||||
│ └── EndgamePhase.java # Эндгейм коллапс + результаты
|
||||
├── player/
|
||||
│ ├── BasePlayer.java # UUID, Player объект
|
||||
│ ├── Survivor.java # Данные выжившего
|
||||
│ ├── Killer.java # Данные киллера
|
||||
│ ├── PlayerState.java # Enum: HEALTHY, INJURED, DOWNED...
|
||||
│ └── PlayerManager.java # Map<UUID, BasePlayer>
|
||||
├── state/
|
||||
│ ├── StateMachine.java # Машина состояний игрока
|
||||
│ ├── StateTransition.java # Проверка можно ли перейти
|
||||
│ └── StateHandler.java # Обработчик изменений
|
||||
├── role/
|
||||
│ ├── RoleAssigner.java # Логика выбора кто киллер
|
||||
│ ├── RoleQueue.java # Очередь на киллера
|
||||
│ └── SpawnPosition.java # Спавн-точки из конфига
|
||||
├── survivor/
|
||||
│ ├── SurvivorController.java # Действия выжившего
|
||||
│ ├── SurvivorMovement.java # Sprint, Exhaustion
|
||||
│ ├── SurvivorHealing.java # Лечение себя/других
|
||||
│ └── SurvivorInventory.java # Предметы в руках
|
||||
├── killer/
|
||||
│ ├── KillerController.java # Действия киллера
|
||||
│ ├── KillerAttack.java # ЛКМ, кулдаун, hit detection
|
||||
│ ├── KillerCarry.java # Подъём, перенос, wiggle
|
||||
│ └── KillerVision.java # Terror radius, red stain
|
||||
├── damage/
|
||||
│ ├── DamageHandler.java # Нанесение урона (Healthy->Injured...)
|
||||
│ ├── AttackListener.java # Слушатель ЛКМ киллера
|
||||
│ └── HitValidator.java # Line of sight, range check
|
||||
├── objective/
|
||||
│ ├── Generator.java # Один генератор
|
||||
│ ├── GeneratorManager.java # Все 7 генераторов
|
||||
│ ├── GeneratorRepair.java # Логика починки
|
||||
│ ├── GeneratorRegression.java # Откат прогресса
|
||||
│ ├── SkillCheck.java # QTE система
|
||||
│ └── SkillCheckUI.java # Title-анимация
|
||||
├── hook/
|
||||
│ ├── Hook.java # Один крюк
|
||||
│ ├── HookManager.java # Все крюки
|
||||
│ ├── HookStage.java # Stage 1, Stage 2
|
||||
│ ├── HookStruggle.java # Skill checks на Stage 2
|
||||
│ ├── HookRescue.java # Спасание с крюка
|
||||
│ └── HookSacrifice.java # Смерть после Stage 2
|
||||
├── pallet/
|
||||
│ ├── Pallet.java # Один паллет
|
||||
│ ├── PalletManager.java # Все паллеты
|
||||
│ ├── PalletDrop.java # Выживший бросает
|
||||
│ ├── PalletStun.java # Стан киллера
|
||||
│ └── PalletBreak.java # Киллер ломает
|
||||
├── window/
|
||||
│ ├── Window.java # Одно окно
|
||||
│ ├── WindowManager.java # Все окна
|
||||
│ ├── WindowVault.java # Прыжок через окно
|
||||
│ └── WindowFastVault.java # Быстрый/медленный волт
|
||||
├── gate/
|
||||
│ ├── ExitGate.java # Одни ворота
|
||||
│ ├── GateManager.java # 2 ворота
|
||||
│ └── GateOpening.java # 20 сек открытие
|
||||
├── hatch/
|
||||
│ ├── Hatch.java # Люк
|
||||
│ ├── HatchCondition.java # Условие появления
|
||||
│ └── HatchEscape.java # Прыжок в люк
|
||||
├── item/
|
||||
│ ├── ItemType.java # Enum: MEDKIT, FLASHLIGHT...
|
||||
│ ├── BaseItem.java # Interface предмета
|
||||
│ ├── ItemMedkit.java # Аптечка
|
||||
│ ├── ItemFlashlight.java # Фонарик
|
||||
│ ├── ItemToolbox.java # Ящик инструментов
|
||||
│ ├── ItemKey.java # Ключ от люка
|
||||
│ ├── ItemMap.java # Карта
|
||||
│ └── ChestLoot.java # Лут из сундуков
|
||||
├── chest/
|
||||
│ ├── Chest.java # Сундук
|
||||
│ ├── ChestManager.java # Все сундуки
|
||||
│ └── ChestOpening.java # 3 сек открытие
|
||||
├── totem/
|
||||
│ ├── Totem.java # Тотем
|
||||
│ ├── TotemManager.java # 5 тотемов
|
||||
│ ├── DullTotem.java # Обычный тотем
|
||||
│ └── HexTotem.java # Проклятый (с перком)
|
||||
├── perk/
|
||||
│ ├── IPerk.java # Интерфейс перка
|
||||
│ ├── PerkType.java # Enum: SURVIVOR, KILLER
|
||||
│ ├── PerkRegistry.java # Map всех перков
|
||||
│ ├── survivor/
|
||||
│ │ ├── SelfCarePerk.java
|
||||
│ │ ├── DeadHardPerk.java
|
||||
│ │ ├── SprintBurstPerk.java
|
||||
│ │ └── BorrowedTimePerk.java
|
||||
│ └── killer/
|
||||
│ ├── HexRuinPerk.java
|
||||
│ ├── CorruptInterventionPerk.java
|
||||
│ └── BBQChiliPerk.java
|
||||
├── ui/
|
||||
│ ├── ActionBar.java # Нижняя полоска
|
||||
│ ├── Sidebar.java # Scoreboard
|
||||
│ ├── TitleUI.java # Title/Subtitle
|
||||
│ ├── ProgressBar.java # [████░░░░░░] 40%
|
||||
│ └── StatusIcons.java # ❤ 🩸 💀
|
||||
├── sound/
|
||||
│ ├── SoundManager.java # Воспроизведение звуков
|
||||
│ ├── TerrorRadiusSound.java # Сердцебиение
|
||||
│ ├── GeneratorSound.java # Звуки генератора
|
||||
│ └── SoundLevels.java # 3 уровня громкости
|
||||
├── util/
|
||||
│ ├── LocationUtil.java # Dist, line of sight
|
||||
│ ├── PlayerUtil.java # Is sneaking, sprinting
|
||||
│ ├── TimeUtil.java # Форматирование секунд
|
||||
│ ├── MathUtil.java # Clamp, lerp
|
||||
│ └── ParticleUtil.java # Спавн частиц
|
||||
├── command/
|
||||
│ ├── DBDCommand.java # /dbd главная
|
||||
│ ├── JoinSubcommand.java # /dbd join
|
||||
│ ├── LeaveSubcommand.java # /dbd leave
|
||||
│ ├── SetupSubcommand.java # /dbd setgen, sethook...
|
||||
│ ├── AdminSubcommand.java # /dbd forcestart, stop
|
||||
│ └── StatsSubcommand.java # /dbd stats
|
||||
├── listener/
|
||||
│ ├── PlayerQuitListener.java # Дисконнект во время игры
|
||||
│ ├── PlayerInteractListener.java # ПКМ, ЛКМ
|
||||
│ ├── PlayerMoveListener.java # Движение, ползание
|
||||
│ └── DamageListener.java # Отмена ванильного урона
|
||||
├── data/
|
||||
│ ├── DataStorage.java # Interface: save(), load()
|
||||
│ ├── YamlStorage.java # YAML реализация
|
||||
│ ├── SQLiteStorage.java # SQLite реализация (позже)
|
||||
│ ├── PlayerStats.java # Статистика игрока
|
||||
│ └── MatchResult.java # Результат матча
|
||||
└── exception/
|
||||
├── DBDException.java # Базовое исключение
|
||||
├── InvalidLocationException.java
|
||||
└── InvalidStateException.java
|
||||
```
|
||||
---
|
||||
|
||||
## TODO (по порядку)
|
||||
## Статус реализации
|
||||
|
||||
### Этап 0: Скелет проекта
|
||||
- [x] Создать `build.gradle` (Paper 1.20.6, Java 21, ProtocolLib)
|
||||
### ✅ Этап 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` — балансные цифры
|
||||
- [x] `LocationsConfig` — координаты объектов
|
||||
- [x] `GameConfig` — все балансные цифры (BossBar, carry, heal limits, lobby timers, sizes, kick cooldown, sabotage)
|
||||
|
||||
### Этап 1: Core Game Loop
|
||||
### ✅ Этап 1: Core Game Loop
|
||||
- [x] `GameState` enum
|
||||
- [x] `GameSession` — хранит игроков, фазу, таймер
|
||||
- [x] `GameSession` — хранит игроков, фазу, таймер; передаёт `GateManager` и `collapseSeconds` в `EndgamePhase`
|
||||
- [x] `Phase` interface
|
||||
- [x] `LobbyPhase` — ожидание, минимум 5 игроков, таймер 60сек
|
||||
- [x] `RoleAssigner` + `RoleQueue` — кто киллер
|
||||
- [x] `RoleAssignPhase` — телепорты, задержка 5сек
|
||||
- [x] `GameplayPhase` — заглушка
|
||||
- [x] `/dbd join`, `/dbd leave`, `/dbd forcestart`
|
||||
- [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: Игроки и состояния
|
||||
### ✅ Этап 2: Игроки и состояния
|
||||
- [x] `BasePlayer`, `Survivor`, `Killer`
|
||||
- [x] `PlayerState` enum: HEALTHY, INJURED, DOWNED, HOOKED, DEAD, ESCAPED
|
||||
- [x] `PlayerState`: HEALTHY, INJURED, DOWNED, HOOKED, CARRIED, DEAD, ESCAPED
|
||||
- [x] `StateMachine` — переходы с валидацией
|
||||
- [x] `PlayerManager` — map UUID -> BasePlayer
|
||||
- [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` — основной класс
|
||||
- [x] `KillerAttack` — ЛКМ, кулдаун 2.5с, hitbox
|
||||
### ✅ Этап 3: Киллер
|
||||
- [x] `KillerController` — без дублирующей регистрации `AttackListener`
|
||||
- [x] `KillerAttack` — ЛКМ, кулдаун 2.5 с, hitbox
|
||||
- [x] `HitValidator` — line of sight, расстояние
|
||||
- [x] `DamageHandler` — Healthy->Injured, Injured->Downed
|
||||
- [x] `KillerCarry` — подъём, перенос, wiggle progress
|
||||
- [x] `KillerMovement` — скорость 115%, замедление после удара
|
||||
- [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`
|
||||
- [x] `SurvivorMovement` — sprint, exhaustion 3сек/5сек кулдаун
|
||||
- [x] `SurvivorHealing` — аптечка 10сек, другие 16сек, прогресс-бар
|
||||
### ✅ Этап 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` класс — прогресс, статус
|
||||
- [x] `GeneratorManager` — 7 штук, 5 нужно
|
||||
- [x] `GeneratorRepair` — зажать ПКМ, прогресс в ActionBar
|
||||
- [x] `SkillCheck` — логика QTE, успех/провал
|
||||
- [x] `SkillCheckUI` — Title-анимация, круг (текстом или картинкой)
|
||||
- [x] `GeneratorRegression` — откат 0.25%/сек, Kick 2.5%/сек 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` класс
|
||||
- [x] `HookManager` — все крюки, подвал
|
||||
- [x] `HookStage` — Stage 1 (60с), Stage 2 (60с)
|
||||
- [x] `HookStruggle` — skill check каждые 2с
|
||||
- [x] `HookRescue` — снятие 2сек
|
||||
- [x] `HookSacrifice` — смерть
|
||||
- [x] Счётчик крюков — 3 раза макс
|
||||
### ✅ Этап 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
|
||||
### ✅ Этап 7: UI
|
||||
- [x] `ActionBar` — статус, прогресс-бары
|
||||
- [x] `ProgressBar` — [████░░░░░░] формат
|
||||
- [x] `Sidebar` — генераторы, живые
|
||||
- [x] `TitleUI` — начало игры, skill check, победа/поражение
|
||||
- [x] `StatusIcons` — ❤ 🩸 💀
|
||||
- [x] `Sidebar` — сердца ♥ (по `hooksTaken`), цвета ников по состоянию, `GeneratorManager` (живой счёт), таймер коллапса
|
||||
- [x] `TitleUI`, `ProgressBar`, `StatusIcons`
|
||||
- [x] `BossBarManager` — BossBar для каждого выжившего, градиент по дистанции
|
||||
- [x] Шкала wiggle в `KillerCarry.showWiggleProgress()` (ActionBar)
|
||||
|
||||
### Этап 8: Паллеты и окна
|
||||
- [x] `Pallet` — standing/dropped/broken
|
||||
- [x] `PalletDrop` — ПКМ выжившим
|
||||
- [x] `PalletStun` — 2.5сек стан киллеру
|
||||
- [x] `PalletBreak` — зажать ПКМ 3сек
|
||||
- [x] `Window` — класс
|
||||
- [x] `WindowVault` — 1сек выживший, 1.5сек киллер
|
||||
### ✅ Этап 8: Паллеты и окна
|
||||
- [x] `Pallet`, `PalletManager`, `PalletDrop`, `PalletBreak`, `PalletStun`
|
||||
- [x] `Window`, `WindowManager`, `WindowVault`, `WindowFastVault`
|
||||
|
||||
### Этап 9: Эндгейм
|
||||
- [x] `ExitGate` — открытие 20сек
|
||||
- [x] `GateManager` — 2 ворота
|
||||
- [x] `Hatch` — условие появления
|
||||
- [x] `HatchCondition` — формула: живые < починенные гены
|
||||
- [x] `HatchEscape` — прыжок = побег
|
||||
- [x] `EndgamePhase` — коллапс 120сек
|
||||
### ✅ Этап 9: Ворота и люк
|
||||
- [x] `ExitGate` — `savedProgress` + `getSavedProgress()`/`saveProgress()`/`restoreProgress()`/`setProgressDirect()`; `reset()` чистит `savedProgress`
|
||||
- [x] `GateManager` — `activateEndgame()` только включает питание, **без авто-открытия**
|
||||
- [x] `GateOpening` — **линейный прогресс** (`setProgressDirect`), сохраняет/восстанавливает прогресс при уходе/возврате игрока
|
||||
- [x] `Hatch`, `HatchCondition`, `HatchEscape`
|
||||
|
||||
### Этап 10: Предметы
|
||||
- [x] `ItemType` enum
|
||||
- [x] `BaseItem` interface
|
||||
- [x] `ItemMedkit`, `ItemFlashlight`, `ItemToolbox`, `ItemKey`, `ItemMap`
|
||||
- [x] `Chest` — 3сек открытие
|
||||
- [x] `ChestLoot` — весовая таблица
|
||||
### ✅ Этап 10: Звук
|
||||
- [x] `TerrorRadiusSound` — `terrorRadius` параметр конструктора (из конфига), дефолт 32
|
||||
- [x] `SoundManager`, `GeneratorSound`, `SoundLevels`
|
||||
|
||||
### Этап 11: Звуки и Terror Radius
|
||||
- [x] `SoundManager`
|
||||
- [x] `TerrorRadiusSound` — 3 уровня по расстоянию
|
||||
- [x] `KillerVision` — red stain частицы
|
||||
- [x] Звуки генераторов, взрывы
|
||||
### ✅ Этап 11: Слушатели
|
||||
- [x] `PlayerJumpListener` — прыжки для wiggle при переноске
|
||||
- [x] `PlayerInteractListener` — `setOnKillerSneak` + `PlayerToggleSneakEvent` (маньяк → GeneratorKick, выживший → HookSabotage)
|
||||
- [x] `PlayerMoveListener`, `PlayerQuitListener`, `DamageListener`
|
||||
|
||||
### Этап 12: Data (YAML -> SQLite)
|
||||
- [x] `DataStorage` interface
|
||||
- [x] `YamlStorage` — реализация
|
||||
- [x] `SQLiteStorage` — заглушка
|
||||
- [x] `PlayerStats` — сохранение BP, матчей
|
||||
- [x] `MatchResult` — результат матча
|
||||
### ✅ Этап 12: Данные и хранение
|
||||
- [x] `DataStorage`, `YamlStorage`, `SQLiteStorage`, `PlayerStats`, `MatchResult`
|
||||
|
||||
### Этап 13: Перки (отложено до стабильности)
|
||||
- [x] `IPerk` interface: onEquip, onTrigger, onRemove
|
||||
- [x] `PerkRegistry` — фабрика перков
|
||||
- [x] 4 перка выжившего (Self-Care, Dead Hard, Sprint Burst, Borrowed Time)
|
||||
- [x] 3 перка киллера (Hex: Ruin, Corrupt Intervention, BBQ)
|
||||
- [x] `Totem` + `TotemManager` — только с Hex
|
||||
---
|
||||
|
||||
### Этап 14: Полировка
|
||||
- [x] Обработка дисконнекта
|
||||
- [x] Баланс скоростей
|
||||
- [x] Утилиты (LocationUtil, PlayerUtil, TimeUtil, MathUtil, ParticleUtil)
|
||||
- [x] Оптимизация (проверка не каждый тик)
|
||||
## ❌ Не реализовано (следующие этапы)
|
||||
|
||||
## Правила <150 строк на файл
|
||||
### Пользовательские лобби
|
||||
- [ ] `LobbySession` — пользовательское лобби (пароль, владелец, приватность)
|
||||
- [ ] `LobbyRegistry` — реестр серверных и пользовательских лобби, YAML persistence
|
||||
- [ ] `/dbd create <name> [password] [private]` — для обычных игроков (сейчас требует `mdbd.admin`)
|
||||
- [ ] `/dbd join <name>` — вход в конкретное лобби
|
||||
|
||||
```java
|
||||
// ✅ Правильно: Controller делегирует
|
||||
public class KillerController {
|
||||
private final KillerAttack attack;
|
||||
private final KillerCarry carry;
|
||||
private final KillerMovement movement;
|
||||
|
||||
public void onLeftClick(Player target) {
|
||||
attack.tryAttack(target);
|
||||
}
|
||||
}
|
||||
### Механики крюков
|
||||
- [ ] `HookRecovery` — самостоятельное слезание с крюка на Stage 2
|
||||
|
||||
// ❌ Неправильно: всё в одном классе
|
||||
public class KillerController {
|
||||
// 500 строк логики атаки, переноса, движения...
|
||||
}
|
||||
```
|
||||
|
||||
## Ключевые интерфейсы
|
||||
|
||||
### IPerk
|
||||
```java
|
||||
public interface IPerk {
|
||||
String getId();
|
||||
String getName();
|
||||
PerkType getType(); // SURVIVOR or KILLER
|
||||
|
||||
void onEquip(BasePlayer player);
|
||||
void onTrigger(BasePlayer player, PerkTrigger trigger);
|
||||
void onRemove(BasePlayer player);
|
||||
}
|
||||
```
|
||||
|
||||
### Phase
|
||||
```java
|
||||
public interface Phase {
|
||||
void enter(GameSession session);
|
||||
void tick(GameSession session); // каждую секунду
|
||||
void exit(GameSession session);
|
||||
boolean isComplete();
|
||||
}
|
||||
```
|
||||
|
||||
### DataStorage
|
||||
```java
|
||||
public interface DataStorage {
|
||||
void saveStats(UUID player, PlayerStats stats);
|
||||
PlayerStats loadStats(UUID player);
|
||||
void saveMatch(MatchResult result);
|
||||
}
|
||||
### Перки
|
||||
- [ ] `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: "<red>☠ МАНЬЯК РЯДОМ ☠</red>"
|
||||
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"
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue