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
|
|
@ -8,19 +8,25 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
|||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Лобби-фаза: ждёт минимум 4 игроков.
|
||||
* При 4 игроках таймер 45 сек, при 5 — сбрасывается до 15 сек.
|
||||
*/
|
||||
public class LobbyPhase implements Phase {
|
||||
private final GameConfig config;
|
||||
private int countdown;
|
||||
private int tickSub; // счётчик тиков внутри текущей секунды
|
||||
private int secondsLeft;
|
||||
private boolean started;
|
||||
private boolean forced;
|
||||
private int lastPlayerCount; // для отслеживания изменения кол-ва игроков
|
||||
|
||||
public LobbyPhase(GameConfig config) {
|
||||
this.config = config;
|
||||
this.secondsLeft = config.getLobbyCountdown();
|
||||
this.countdown = 0;
|
||||
this.secondsLeft = config.getCountdown4Players(); // начальный таймер
|
||||
this.tickSub = 0;
|
||||
this.started = false;
|
||||
this.forced = false;
|
||||
this.lastPlayerCount = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -43,31 +49,62 @@ public class LobbyPhase implements Phase {
|
|||
}
|
||||
|
||||
int playerCount = session.getPlayerCount();
|
||||
int minPlayers = config.getMinPlayers();
|
||||
int minPlayers = config.getMinPlayers(); // 4
|
||||
int maxPlayers = config.getMaxPlayers(); // 5
|
||||
|
||||
// Недостаточно игроков — сбрасываем таймер
|
||||
if (playerCount < minPlayers) {
|
||||
secondsLeft = config.getLobbyCountdown();
|
||||
countdown = 0;
|
||||
secondsLeft = config.getCountdown4Players();
|
||||
tickSub = 0;
|
||||
lastPlayerCount = playerCount;
|
||||
sendActionBarToAll(session,
|
||||
Component.text("⏳ Ожидание игроков: " + playerCount + "/" + minPlayers, NamedTextColor.YELLOW));
|
||||
Component.text("⏳ Ожидание игроков: " + playerCount + "/" + minPlayers,
|
||||
NamedTextColor.YELLOW));
|
||||
return;
|
||||
}
|
||||
|
||||
countdown++;
|
||||
if (countdown >= 20) {
|
||||
countdown = 0;
|
||||
secondsLeft--;
|
||||
// Когда количество игроков меняется — обновляем нужный таймер
|
||||
if (playerCount != lastPlayerCount) {
|
||||
lastPlayerCount = playerCount;
|
||||
if (playerCount >= maxPlayers) {
|
||||
// При максимуме игроков сокращаем таймер до countdown-5-players
|
||||
int fast = config.getCountdown5Players();
|
||||
if (secondsLeft > fast) {
|
||||
secondsLeft = fast;
|
||||
tickSub = 0;
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] Все игроки вошли! Старт через " + fast + " сек!",
|
||||
NamedTextColor.GREEN));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String bar = buildCountdownBar(secondsLeft, config.getLobbyCountdown());
|
||||
// Тикаем таймер
|
||||
tickSub++;
|
||||
if (tickSub >= 20) {
|
||||
tickSub = 0;
|
||||
secondsLeft--;
|
||||
|
||||
// Анонс вслух на ключевых секундах
|
||||
if (secondsLeft == 30 || secondsLeft == 15 || secondsLeft == 10
|
||||
|| secondsLeft == 5 || secondsLeft == 3
|
||||
|| secondsLeft == 2 || secondsLeft == 1) {
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] До начала: " + secondsLeft + " сек.",
|
||||
NamedTextColor.YELLOW));
|
||||
}
|
||||
}
|
||||
|
||||
// ActionBar всем
|
||||
int total = (playerCount >= maxPlayers)
|
||||
? config.getCountdown5Players()
|
||||
: config.getCountdown4Players();
|
||||
String bar = buildCountdownBar(secondsLeft, total);
|
||||
NamedTextColor barColor = (playerCount >= maxPlayers)
|
||||
? NamedTextColor.GREEN : NamedTextColor.YELLOW;
|
||||
sendActionBarToAll(session,
|
||||
Component.text("▶ Старт через: " + secondsLeft + "с " + bar +
|
||||
" (" + playerCount + "/" + minPlayers + ")", NamedTextColor.GREEN));
|
||||
|
||||
if (countdown == 0 && (secondsLeft <= 5 || secondsLeft == 10 || secondsLeft == 30)) {
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] До начала: " + secondsLeft + " сек.", NamedTextColor.YELLOW));
|
||||
}
|
||||
" (" + playerCount + "/" + minPlayers + ")", barColor));
|
||||
|
||||
if (secondsLeft <= 0) {
|
||||
started = true;
|
||||
|
|
@ -85,7 +122,7 @@ public class LobbyPhase implements Phase {
|
|||
|
||||
private String buildCountdownBar(int current, int total) {
|
||||
int filled = total > 0 ? (int) (10.0 * current / total) : 0;
|
||||
int empty = 10 - filled;
|
||||
int empty = 10 - filled;
|
||||
return "§a" + "█".repeat(Math.max(0, filled)) + "§7" + "░".repeat(Math.max(0, empty));
|
||||
}
|
||||
|
||||
|
|
@ -102,9 +139,10 @@ public class LobbyPhase implements Phase {
|
|||
public void onPlayerJoined(GameSession session, Player player) {
|
||||
session.getPlugin().getLobbyManager().teleportToLobby(player);
|
||||
int playerCount = session.getPlayerCount();
|
||||
int minPlayers = config.getMinPlayers();
|
||||
int minPlayers = config.getMinPlayers();
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] " + player.getName() + " присоединился к очереди! (" + playerCount + "/" + minPlayers + ")",
|
||||
"[DBD] " + player.getName() + " присоединился к очереди! (" +
|
||||
playerCount + "/" + minPlayers + ")",
|
||||
NamedTextColor.YELLOW));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue