136 lines
No EOL
4.9 KiB
Java
136 lines
No EOL
4.9 KiB
Java
package dev.loki.phase;
|
||
|
||
import dev.loki.config.GameConfig;
|
||
import dev.loki.core.GameSession;
|
||
import dev.loki.hook.*;
|
||
import dev.loki.player.BasePlayer;
|
||
import dev.loki.player.Killer;
|
||
import dev.loki.player.PlayerState;
|
||
import dev.loki.player.Survivor;
|
||
import dev.loki.ui.TitleUI;
|
||
import net.kyori.adventure.text.Component;
|
||
import net.kyori.adventure.text.format.NamedTextColor;
|
||
import org.bukkit.Bukkit;
|
||
import org.bukkit.GameMode;
|
||
import org.bukkit.Sound;
|
||
import org.bukkit.entity.Player;
|
||
|
||
/**
|
||
* Handles win condition checking during gameplay phase.
|
||
*/
|
||
public class GameplayWinConditions {
|
||
|
||
private boolean shouldEnd;
|
||
private String winReason; // "killer_win", "survivors_win", null
|
||
|
||
public boolean isShouldEnd() {
|
||
return shouldEnd;
|
||
}
|
||
|
||
public String getWinReason() {
|
||
return winReason;
|
||
}
|
||
|
||
/**
|
||
* Check all win conditions each second (20 ticks).
|
||
*/
|
||
public void checkWinConditions(GameSession session) {
|
||
int aliveSurvivors = countAliveSurvivors(session);
|
||
Killer killer = getKiller(session);
|
||
|
||
// Killer disconnect: if killer player is null/offline, survivors win
|
||
if (killer == null || killer.getPlayer() == null || !killer.getPlayer().isOnline()) {
|
||
winReason = "survivors_win";
|
||
Bukkit.broadcast(Component.text("[DBD] Маньяк покинул игру! Выжившие победили!", NamedTextColor.GREEN));
|
||
announceSurvivorsWin(session);
|
||
shouldEnd = true;
|
||
return;
|
||
}
|
||
|
||
// Killer wins: all survivors are downed/hooked/carried/dead
|
||
if (allSurvivorsIncapacitated(session)) {
|
||
winReason = "killer_win";
|
||
Bukkit.broadcast(Component.text("[DBD] Все выжившие обезврежены!", NamedTextColor.DARK_RED));
|
||
announceKillerWin(session);
|
||
shouldEnd = true;
|
||
return;
|
||
}
|
||
|
||
// Survivors win: all generators done and at least one escaped
|
||
if (hasEscapedSurvivor(session)) {
|
||
winReason = "survivors_win";
|
||
announceSurvivorsWin(session);
|
||
shouldEnd = true;
|
||
}
|
||
}
|
||
|
||
/** True if NO survivor can act (all are DOWNED, HOOKED, CARRIED, or DEAD). */
|
||
private boolean allSurvivorsIncapacitated(GameSession session) {
|
||
boolean hasSurvivors = false;
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
if (bp.isKiller()) continue;
|
||
hasSurvivors = true;
|
||
PlayerState st = bp.getState();
|
||
if (st != PlayerState.DOWNED && st != PlayerState.HOOKED
|
||
&& st != PlayerState.CARRIED && st != PlayerState.DEAD) {
|
||
return false; // at least one survivor can still act
|
||
}
|
||
}
|
||
return hasSurvivors; // true if there are survivors and all are incapacitated
|
||
}
|
||
|
||
private int countAliveSurvivors(GameSession session) {
|
||
int count = 0;
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
if (bp.isKiller()) continue;
|
||
Survivor s = (Survivor) bp;
|
||
if (!s.isDeadOrEscaped()) count++;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
private boolean hasEscapedSurvivor(GameSession session) {
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
if (bp.isKiller()) continue;
|
||
if (bp.getState() == PlayerState.ESCAPED) return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private Killer getKiller(GameSession session) {
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
if (bp.isKiller()) return (Killer) bp;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
public void announceKillerWin(GameSession session) {
|
||
winReason = "killer_win";
|
||
Bukkit.broadcast(Component.text("[DBD] Маньяк победил! Все выжившие мертвы!", NamedTextColor.DARK_RED));
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
Player p = bp.getPlayer();
|
||
if (p == null || !p.isOnline()) continue;
|
||
if (!bp.isKiller() && bp.getState() == PlayerState.DEAD) {
|
||
p.setGameMode(GameMode.SPECTATOR);
|
||
} else {
|
||
p.setGameMode(GameMode.SURVIVAL);
|
||
}
|
||
p.playSound(p.getLocation(), Sound.ENTITY_WITHER_DEATH, 1.0f, 1.0f);
|
||
}
|
||
// Teleport handled by EndgamePhase.exit()
|
||
}
|
||
|
||
public void announceSurvivorsWin(GameSession session) {
|
||
winReason = "survivors_win";
|
||
Bukkit.broadcast(Component.text("[DBD] Выжившие победили!", NamedTextColor.GREEN));
|
||
for (BasePlayer bp : session.getPlayers().values()) {
|
||
Player p = bp.getPlayer();
|
||
if (p == null || !p.isOnline()) continue;
|
||
p.setGameMode(GameMode.SURVIVAL);
|
||
p.playSound(p.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f);
|
||
}
|
||
// Teleport handled by EndgamePhase.exit()
|
||
}
|
||
|
||
// Removed scheduleTeleportToLobby — teleport now happens only in EndgamePhase.exit()
|
||
} |