feat: wire pallet/hook/gate/chest systems into gameplay
This commit is contained in:
parent
b339f4c029
commit
fcf2debbd4
4 changed files with 383 additions and 75 deletions
|
|
@ -1,9 +1,29 @@
|
|||
package dev.loki.phase;
|
||||
|
||||
import dev.loki.chest.ChestManager;
|
||||
import dev.loki.chest.ChestOpening;
|
||||
import dev.loki.core.GameSession;
|
||||
import dev.loki.gate.ExitGate;
|
||||
import dev.loki.gate.GateManager;
|
||||
import dev.loki.hook.Hook;
|
||||
import dev.loki.hook.HookManager;
|
||||
import dev.loki.hook.HookRescue;
|
||||
import dev.loki.hook.HookSacrifice;
|
||||
import dev.loki.hook.HookStage;
|
||||
import dev.loki.listener.PlayerInteractListener;
|
||||
import dev.loki.listener.PlayerMoveListener;
|
||||
import dev.loki.mdbd;
|
||||
import dev.loki.objective.GeneratorManager;
|
||||
import dev.loki.pallet.Pallet;
|
||||
import dev.loki.pallet.PalletBreak;
|
||||
import dev.loki.pallet.PalletDrop;
|
||||
import dev.loki.pallet.PalletManager;
|
||||
import dev.loki.pallet.PalletStun;
|
||||
import dev.loki.player.BasePlayer;
|
||||
import dev.loki.player.Killer;
|
||||
import dev.loki.player.PlayerState;
|
||||
import dev.loki.player.Survivor;
|
||||
import dev.loki.ui.ActionBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
|
|
@ -11,23 +31,71 @@ import org.bukkit.Sound;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
public class GameplayPhase implements Phase {
|
||||
|
||||
private final GeneratorManager generatorManager;
|
||||
private int tickCounter;
|
||||
private boolean shouldEnd;
|
||||
private boolean allGensDone;
|
||||
|
||||
// Managers initialised in enter()
|
||||
private PalletManager palletManager;
|
||||
private HookManager hookManager;
|
||||
private GateManager gateManager;
|
||||
private HookRescue hookRescue;
|
||||
private HookSacrifice hookSacrifice;
|
||||
private PalletDrop palletDrop;
|
||||
private PalletBreak palletBreak;
|
||||
private PalletStun palletStun;
|
||||
private ChestManager chestManager;
|
||||
private ChestOpening chestOpening;
|
||||
|
||||
// Listener references grabbed from plugin
|
||||
private PlayerMoveListener moveListener;
|
||||
private PlayerInteractListener interactListener;
|
||||
|
||||
public GameplayPhase(GeneratorManager generatorManager) {
|
||||
this.generatorManager = generatorManager;
|
||||
this.tickCounter = 0;
|
||||
this.shouldEnd = false;
|
||||
this.allGensDone = false;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Phase lifecycle
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void enter(GameSession session) {
|
||||
Bukkit.broadcast(Component.text("[DBD] Игра началась! Выжившие, чините генераторы!", NamedTextColor.GREEN));
|
||||
mdbd plugin = session.getPlugin();
|
||||
tickCounter = 0;
|
||||
// Teleport is handled by RoleAssigner.assignRoles — no double-teleport needed here
|
||||
shouldEnd = false;
|
||||
allGensDone = false;
|
||||
|
||||
// --- Initialise managers ---
|
||||
palletManager = new PalletManager(plugin.getConfigManager().getLocations());
|
||||
hookManager = new HookManager(plugin);
|
||||
hookManager.loadHooks(plugin.getConfigManager().getLocations());
|
||||
gateManager = new GateManager(plugin.getConfigManager().getLocations());
|
||||
ActionBar ab = new ActionBar();
|
||||
hookRescue = new HookRescue(plugin, ab);
|
||||
hookSacrifice = new HookSacrifice(plugin, null);
|
||||
palletDrop = new PalletDrop(palletManager);
|
||||
palletBreak = new PalletBreak(session.getConfig());
|
||||
palletStun = new PalletStun(session.getConfig());
|
||||
chestManager = new ChestManager(plugin, plugin.getConfigManager().getLocations());
|
||||
chestOpening = new ChestOpening(plugin);
|
||||
|
||||
// Store managers on session so other code can reach them
|
||||
session.setPalletManager(palletManager);
|
||||
session.setHookManager(hookManager);
|
||||
session.setGateManager(gateManager);
|
||||
|
||||
// --- Wire listeners ---
|
||||
moveListener = plugin.getMoveListener();
|
||||
interactListener = plugin.getInteractListener();
|
||||
|
||||
wireMoveListener(session);
|
||||
wireInteractListener(session);
|
||||
|
||||
Bukkit.broadcast(Component.text("[DBD] Игра началась! Выжившие, чините генераторы!",
|
||||
NamedTextColor.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -35,19 +103,92 @@ public class GameplayPhase implements Phase {
|
|||
tickCounter++;
|
||||
generatorManager.tick();
|
||||
|
||||
// Tick hook timers every game tick
|
||||
tickHooks(session);
|
||||
|
||||
if (tickCounter % 20 == 0) {
|
||||
checkGeneratorProgress(session);
|
||||
checkWinConditions(session);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(GameSession session) {
|
||||
// Clean up listeners
|
||||
if (moveListener != null) {
|
||||
moveListener.setOnSurvivorMove(null);
|
||||
}
|
||||
if (interactListener != null) {
|
||||
interactListener.setOnPalletInteract(null);
|
||||
interactListener.setOnRescueAttempt(null);
|
||||
interactListener.setOnChestInteract(null);
|
||||
interactListener.setOnAttack(null);
|
||||
}
|
||||
|
||||
// Stop hooks
|
||||
if (hookManager != null) {
|
||||
hookManager.clear();
|
||||
}
|
||||
if (hookRescue != null) {
|
||||
hookRescue.clear();
|
||||
}
|
||||
if (chestOpening != null) {
|
||||
chestOpening.cancelAll();
|
||||
}
|
||||
|
||||
Bukkit.broadcast(Component.text("[DBD] Игровая фаза завершена!", NamedTextColor.GOLD));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return shouldEnd;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Hook ticking
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void tickHooks(GameSession session) {
|
||||
for (Hook hook : hookManager.getAllHooks()) {
|
||||
if (!hook.isOccupied()) continue;
|
||||
|
||||
hook.tick();
|
||||
|
||||
Survivor victim = hook.getHookedSurvivor();
|
||||
if (victim == null) continue;
|
||||
|
||||
// Show action bar progress to the hooked survivor
|
||||
Player vp = victim.getPlayer();
|
||||
if (vp != null && vp.isOnline()) {
|
||||
// ActionBar shows stage progress
|
||||
double pct = hook.getStageProgressPercent();
|
||||
String label = hook.getCurrentStage() == HookStage.STAGE_2
|
||||
? "§cStage 2 - struggle!"
|
||||
: "§eOn hook";
|
||||
vp.sendActionBar(Component.text(label + " " + (int) pct + "%"));
|
||||
}
|
||||
|
||||
// Sacrifice when timer expires
|
||||
if (hook.getCurrentStage() == HookStage.SACRIFICE) {
|
||||
hookSacrifice.sacrificeIfExpired(victim, hook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Generator / win-condition checks
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void checkGeneratorProgress(GameSession session) {
|
||||
if (allGensDone) return;
|
||||
|
||||
if (generatorManager.areAllRequiredCompleted()) {
|
||||
allGensDone = true;
|
||||
gateManager.activateEndgame();
|
||||
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] Все генераторы починены! Открывайте ворота!", NamedTextColor.GREEN));
|
||||
|
||||
for (BasePlayer bp : session.getPlayers().values()) {
|
||||
Player p = bp.getPlayer();
|
||||
if (p != null) {
|
||||
|
|
@ -58,36 +199,127 @@ public class GameplayPhase implements Phase {
|
|||
}
|
||||
|
||||
private void checkWinConditions(GameSession session) {
|
||||
int aliveSurvivors = 0;
|
||||
int aliveSurvivors = 0;
|
||||
int escapedSurvivors = 0;
|
||||
int totalSurvivors = 0;
|
||||
int totalSurvivors = 0;
|
||||
|
||||
for (BasePlayer bp : session.getPlayers().values()) {
|
||||
if (bp.isKiller()) continue;
|
||||
totalSurvivors++;
|
||||
PlayerState state = bp.getState();
|
||||
if (state == PlayerState.ESCAPED) {
|
||||
PlayerState st = bp.getState();
|
||||
if (st == PlayerState.ESCAPED) {
|
||||
escapedSurvivors++;
|
||||
} else if (state != PlayerState.DEAD && state != PlayerState.HOOKED) {
|
||||
} else if (st != PlayerState.DEAD && st != PlayerState.HOOKED) {
|
||||
aliveSurvivors++;
|
||||
}
|
||||
}
|
||||
|
||||
boolean allSurvivorsDead = (aliveSurvivors == 0 && escapedSurvivors == 0 && totalSurvivors > 0);
|
||||
boolean allDead = (aliveSurvivors == 0 && escapedSurvivors == 0 && totalSurvivors > 0);
|
||||
boolean allEscaped = (escapedSurvivors == totalSurvivors && totalSurvivors > 0);
|
||||
|
||||
if (allSurvivorsDead || allEscaped) {
|
||||
if (allDead || allEscaped) {
|
||||
shouldEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(GameSession session) {
|
||||
Bukkit.broadcast(Component.text("[DBD] Игровая фаза завершена!", NamedTextColor.GOLD));
|
||||
// -------------------------------------------------------------------------
|
||||
// Listener wiring
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void wireMoveListener(GameSession session) {
|
||||
if (moveListener == null) return;
|
||||
|
||||
// Gate escape: survivor walks into open gate zone after all gens done
|
||||
moveListener.setOnSurvivorMove((survivor, loc) -> {
|
||||
if (!allGensDone) return;
|
||||
if (survivor.getState() == PlayerState.ESCAPED) return;
|
||||
|
||||
ExitGate gate = gateManager.getGateAt(loc, 3.0);
|
||||
if (gate != null && gate.isOpen()) {
|
||||
survivor.setState(PlayerState.ESCAPED);
|
||||
Player p = survivor.getPlayer();
|
||||
if (p != null) {
|
||||
p.playSound(loc, Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.2f);
|
||||
Bukkit.broadcast(Component.text(
|
||||
"[DBD] " + p.getName() + " сбежал через ворота!",
|
||||
NamedTextColor.GOLD));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isComplete() {
|
||||
return shouldEnd;
|
||||
private void wireInteractListener(GameSession session) {
|
||||
if (interactListener == null) return;
|
||||
|
||||
// Pallet interact: survivor right-click = drop, killer left-click = break
|
||||
interactListener.setOnPalletInteract((player, isRightClick) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null) return;
|
||||
|
||||
if (isRightClick && !bp.isKiller()) {
|
||||
palletDrop.tryDrop((Survivor) bp);
|
||||
|
||||
} else if (!isRightClick && bp.isKiller()) {
|
||||
Killer killer = (Killer) bp;
|
||||
Pallet nearby = palletManager.getPalletAt(player.getLocation(), 3.0);
|
||||
if (nearby != null && nearby.isDropped()) {
|
||||
palletBreak.startBreaking(killer, nearby, session.getPlugin());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Rescue attempt: survivor right-clicks near a hook
|
||||
interactListener.setOnRescueAttempt((player, ignored) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
Survivor rescuer = (Survivor) bp;
|
||||
if (rescuer.getState() == PlayerState.HOOKED) return;
|
||||
|
||||
Hook hook = hookManager.findNearestOccupiedHook(player.getLocation(), 3.0);
|
||||
if (hook != null) {
|
||||
hookRescue.startRescue(rescuer, hook);
|
||||
}
|
||||
});
|
||||
|
||||
// Killer right-click: hook a carried survivor
|
||||
interactListener.setOnAttack((player, isRightClick) -> {
|
||||
if (!isRightClick) return; // left-click handled by damage system
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || !bp.isKiller()) return;
|
||||
Killer killer = (Killer) bp;
|
||||
|
||||
if (killer.getState() == PlayerState.CARRIED || killer.isCarrying()) {
|
||||
// Find the carried survivor
|
||||
for (BasePlayer other : session.getPlayers().values()) {
|
||||
if (!other.isKiller() && other.getState() == PlayerState.CARRIED) {
|
||||
Survivor carried = (Survivor) other;
|
||||
if (hookManager.tryHookSurvivor(carried, player.getLocation())) {
|
||||
killer.setCarrying(false);
|
||||
// Teleport survivor to hook
|
||||
Hook nearestHook = hookManager.findNearestOccupiedHook(
|
||||
player.getLocation(), 5.0);
|
||||
if (nearestHook != null) {
|
||||
Player vp = carried.getPlayer();
|
||||
if (vp != null) {
|
||||
vp.teleport(nearestHook.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Chest interact
|
||||
interactListener.setOnChestInteract((player, ignored) -> {
|
||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||
if (bp == null || bp.isKiller()) return;
|
||||
|
||||
var chest = chestManager.getNearestChest(player.getLocation(), 3.0);
|
||||
if (chest != null) {
|
||||
chestOpening.startOpening(player, chest);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue