remove: hatch (люк) and windows (окна) from code and config
This commit is contained in:
parent
be86fe5960
commit
bb293c5d03
15 changed files with 57 additions and 458 deletions
|
|
@ -109,10 +109,6 @@ public class GameConfig {
|
||||||
setDefault("colors.progress-bar-incomplete", "&#FF0000");
|
setDefault("colors.progress-bar-incomplete", "&#FF0000");
|
||||||
setDefault("colors.progress-bar-background", "񑘕");
|
setDefault("colors.progress-bar-background", "񑘕");
|
||||||
|
|
||||||
// Hatch
|
|
||||||
setDefault("hatch.min-survivors-for-open", 1);
|
|
||||||
setDefault("hatch.require-more-gens-than-survivors", true);
|
|
||||||
|
|
||||||
// Block types for spawning
|
// Block types for spawning
|
||||||
setDefault("blocks.generator", "BLAST_FURNACE");
|
setDefault("blocks.generator", "BLAST_FURNACE");
|
||||||
setDefault("blocks.chest", "CHEST");
|
setDefault("blocks.chest", "CHEST");
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,6 @@ public class LocationsConfig {
|
||||||
if (!config.contains("hooks") || config.getList("hooks") == null) {
|
if (!config.contains("hooks") || config.getList("hooks") == null) {
|
||||||
config.set("hooks", new ArrayList<>());
|
config.set("hooks", new ArrayList<>());
|
||||||
}
|
}
|
||||||
if (!config.contains("windows") || config.getList("windows") == null) {
|
|
||||||
config.set("windows", new ArrayList<>());
|
|
||||||
}
|
|
||||||
if (!config.contains("chests") || config.getList("chests") == null) {
|
if (!config.contains("chests") || config.getList("chests") == null) {
|
||||||
config.set("chests", new ArrayList<>());
|
config.set("chests", new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
@ -79,10 +76,6 @@ public class LocationsConfig {
|
||||||
return loadLocationList("hooks");
|
return loadLocationList("hooks");
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Location> getWindows() {
|
|
||||||
return loadLocationList("windows");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Location> getChests() {
|
public List<Location> getChests() {
|
||||||
return loadLocationList("chests");
|
return loadLocationList("chests");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ public class GameSession {
|
||||||
if (currentPhase instanceof GameplayPhase gp) {
|
if (currentPhase instanceof GameplayPhase gp) {
|
||||||
// Всегда переходим в EndgamePhase для корректного завершения игры
|
// Всегда переходим в EndgamePhase для корректного завершения игры
|
||||||
// (очистка скорборда, телепорт в лобби, показ результатов)
|
// (очистка скорборда, телепорт в лобби, показ результатов)
|
||||||
return new EndgamePhase(gateManager, null, null);
|
return new EndgamePhase(gateManager);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public class ExitGate {
|
||||||
World world = location.getWorld();
|
World world = location.getWorld();
|
||||||
if (world == null) return;
|
if (world == null) return;
|
||||||
|
|
||||||
|
// Place all iron bars first (no physics) then force update for connections
|
||||||
if (hasZone) {
|
if (hasZone) {
|
||||||
for (int x = zoneMinX; x <= zoneMaxX; x++) {
|
for (int x = zoneMinX; x <= zoneMaxX; x++) {
|
||||||
for (int y = zoneMinY; y <= zoneMaxY; y++) {
|
for (int y = zoneMinY; y <= zoneMaxY; y++) {
|
||||||
|
|
@ -68,6 +69,14 @@ public class ExitGate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Force update all iron bars so they connect to neighbors
|
||||||
|
for (int x = zoneMinX; x <= zoneMaxX; x++) {
|
||||||
|
for (int y = zoneMinY; y <= zoneMaxY; y++) {
|
||||||
|
for (int z = zoneMinZ; z <= zoneMaxZ; z++) {
|
||||||
|
world.getBlockAt(x, y, z).getState().update(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: 3x3x3 zone around gate location
|
// Fallback: 3x3x3 zone around gate location
|
||||||
int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ();
|
int cx = location.getBlockX(), cy = location.getBlockY(), cz = location.getBlockZ();
|
||||||
|
|
@ -78,6 +87,13 @@ public class ExitGate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (int x = cx - 1; x <= cx + 1; x++) {
|
||||||
|
for (int y = cy; y <= cy + 2; y++) {
|
||||||
|
for (int z = cz - 1; z <= cz + 1; z++) {
|
||||||
|
world.getBlockAt(x, y, z).getState().update(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button at gate center + (1, 1, 1)
|
// Button at gate center + (1, 1, 1)
|
||||||
|
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
package dev.loki.hatch;
|
|
||||||
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
|
|
||||||
public class Hatch {
|
|
||||||
private final Location location;
|
|
||||||
private HatchState state;
|
|
||||||
private Block hatchBlock;
|
|
||||||
|
|
||||||
public enum HatchState {
|
|
||||||
HIDDEN,
|
|
||||||
CLOSED,
|
|
||||||
OPEN
|
|
||||||
}
|
|
||||||
|
|
||||||
public Hatch(Location location) {
|
|
||||||
this.location = location;
|
|
||||||
this.state = HatchState.HIDDEN;
|
|
||||||
this.hatchBlock = location.getBlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Location getJumpTarget() {
|
|
||||||
return location.clone().add(0.5, -2, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HatchState getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHidden() {
|
|
||||||
return state == HatchState.HIDDEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isClosed() {
|
|
||||||
return state == HatchState.CLOSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOpen() {
|
|
||||||
return state == HatchState.OPEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reveal() {
|
|
||||||
if (state == HatchState.HIDDEN) {
|
|
||||||
state = HatchState.CLOSED;
|
|
||||||
updateVisuals();
|
|
||||||
playRevealEffect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void open() {
|
|
||||||
if (state == HatchState.CLOSED) {
|
|
||||||
state = HatchState.OPEN;
|
|
||||||
updateVisuals();
|
|
||||||
playOpenEffect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hide() {
|
|
||||||
state = HatchState.HIDDEN;
|
|
||||||
clearVisuals();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
state = HatchState.HIDDEN;
|
|
||||||
clearVisuals();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateVisuals() {
|
|
||||||
switch (state) {
|
|
||||||
case CLOSED -> hatchBlock.setType(Material.IRON_TRAPDOOR);
|
|
||||||
case OPEN -> hatchBlock.setType(Material.AIR);
|
|
||||||
default -> hatchBlock.setType(Material.AIR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearVisuals() {
|
|
||||||
hatchBlock.setType(Material.AIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInRange(Location playerLoc, double radius) {
|
|
||||||
return location.distance(playerLoc) <= radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canEscape(Location playerLoc) {
|
|
||||||
return isOpen() && isInRange(playerLoc, 1.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void playRevealEffect() {
|
|
||||||
World world = location.getWorld();
|
|
||||||
if (world == null) return;
|
|
||||||
|
|
||||||
world.playSound(location, Sound.BLOCK_METAL_PLACE, 1.0f, 0.8f);
|
|
||||||
world.spawnParticle(org.bukkit.Particle.SMOKE,
|
|
||||||
location.clone().add(0.5, 0.5, 0.5),
|
|
||||||
30, 0.3, 0.3, 0.3, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void playOpenEffect() {
|
|
||||||
World world = location.getWorld();
|
|
||||||
if (world == null) return;
|
|
||||||
|
|
||||||
world.playSound(location, Sound.BLOCK_IRON_TRAPDOOR_OPEN, 1.0f, 1.0f);
|
|
||||||
world.spawnParticle(org.bukkit.Particle.END_ROD,
|
|
||||||
location.clone().add(0.5, 0.5, 0.5),
|
|
||||||
20, 0.2, 0.2, 0.2, 0.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playEscapeEffect() {
|
|
||||||
World world = location.getWorld();
|
|
||||||
if (world == null) return;
|
|
||||||
|
|
||||||
world.playSound(location, Sound.ENTITY_PLAYER_SPLASH, 1.0f, 1.0f);
|
|
||||||
world.spawnParticle(org.bukkit.Particle.PORTAL,
|
|
||||||
location.clone().add(0.5, 0, 0.5),
|
|
||||||
100, 0.5, 0.5, 0.5, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package dev.loki.hatch;
|
|
||||||
|
|
||||||
import dev.loki.player.BasePlayer;
|
|
||||||
import dev.loki.player.PlayerState;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public class HatchCondition {
|
|
||||||
private final int minSurvivorsForOpen;
|
|
||||||
|
|
||||||
public HatchCondition(int minSurvivorsForOpen) {
|
|
||||||
this.minSurvivorsForOpen = minSurvivorsForOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldSpawn(Collection<BasePlayer> players, int repairedGenerators) {
|
|
||||||
int aliveSurvivors = countAliveSurvivors(players);
|
|
||||||
return aliveSurvivors <= repairedGenerators;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean shouldOpen(Hatch hatch, Collection<BasePlayer> players, int repairedGenerators) {
|
|
||||||
if (hatch.isOpen()) return false;
|
|
||||||
if (!hatch.isClosed() && !hatch.isHidden()) return false;
|
|
||||||
|
|
||||||
return shouldSpawn(players, repairedGenerators);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canOpen(Hatch hatch, Collection<BasePlayer> players, int repairedGenerators) {
|
|
||||||
if (!hatch.isHidden() && !hatch.isClosed()) return false;
|
|
||||||
|
|
||||||
int aliveSurvivors = countAliveSurvivors(players);
|
|
||||||
int requiredGens = Math.max(minSurvivorsForOpen, aliveSurvivors);
|
|
||||||
|
|
||||||
return repairedGenerators >= requiredGens;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int countAliveSurvivors(Collection<BasePlayer> players) {
|
|
||||||
return (int) players.stream()
|
|
||||||
.filter(p -> !p.isKiller())
|
|
||||||
.filter(this::isAlive)
|
|
||||||
.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAlive(BasePlayer player) {
|
|
||||||
PlayerState state = player.getState();
|
|
||||||
return state != PlayerState.DEAD
|
|
||||||
&& state != PlayerState.ESCAPED
|
|
||||||
&& state != PlayerState.HOOKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRemainingAlive(Collection<BasePlayer> players) {
|
|
||||||
return countAliveSurvivors(players);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLastSurvivor(Collection<BasePlayer> players) {
|
|
||||||
return countAliveSurvivors(players) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkAndReveal(Hatch hatch, Collection<BasePlayer> players, int repairedGenerators) {
|
|
||||||
if (hatch.isHidden() && shouldSpawn(players, repairedGenerators)) {
|
|
||||||
hatch.reveal();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkAndOpen(Hatch hatch, Collection<BasePlayer> players, int repairedGenerators) {
|
|
||||||
if (canOpen(hatch, players, repairedGenerators)) {
|
|
||||||
if (hatch.isHidden()) {
|
|
||||||
hatch.reveal();
|
|
||||||
}
|
|
||||||
hatch.open();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
package dev.loki.hatch;
|
|
||||||
|
|
||||||
import dev.loki.config.MessagesConfig;
|
|
||||||
import dev.loki.mdbd;
|
|
||||||
import dev.loki.player.PlayerState;
|
|
||||||
import dev.loki.player.Survivor;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
public class HatchEscape {
|
|
||||||
private static final double ESCAPE_RADIUS = 1.5;
|
|
||||||
|
|
||||||
private final Hatch hatch;
|
|
||||||
private final MessagesConfig messages;
|
|
||||||
|
|
||||||
public HatchEscape(Hatch hatch) {
|
|
||||||
this.hatch = hatch;
|
|
||||||
this.messages = mdbd.getInstance().getConfigManager().getMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean tryEscape(Survivor survivor) {
|
|
||||||
if (!hatch.isOpen()) {
|
|
||||||
return tryRevealAndCheck(survivor);
|
|
||||||
}
|
|
||||||
|
|
||||||
Player player = survivor.getPlayer();
|
|
||||||
if (player == null) return false;
|
|
||||||
|
|
||||||
if (!isAtHatch(player.getLocation())) {
|
|
||||||
player.sendMessage(messages.get("hatch.too-far"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
performEscape(survivor);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canEscape(Survivor survivor) {
|
|
||||||
if (!hatch.isOpen()) return false;
|
|
||||||
|
|
||||||
Player player = survivor.getPlayer();
|
|
||||||
if (player == null) return false;
|
|
||||||
|
|
||||||
return isAtHatch(player.getLocation());
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean tryRevealAndCheck(Survivor survivor) {
|
|
||||||
Player player = survivor.getPlayer();
|
|
||||||
if (player == null) return false;
|
|
||||||
|
|
||||||
if (hatch.isHidden()) {
|
|
||||||
player.sendMessage(messages.get("hatch.hidden"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hatch.isClosed()) {
|
|
||||||
player.sendMessage(messages.get("hatch.closed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAtHatch(Location location) {
|
|
||||||
return hatch.isInRange(location, ESCAPE_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void performEscape(Survivor survivor) {
|
|
||||||
Player player = survivor.getPlayer();
|
|
||||||
if (player == null) return;
|
|
||||||
|
|
||||||
player.teleport(hatch.getJumpTarget());
|
|
||||||
hatch.playEscapeEffect();
|
|
||||||
|
|
||||||
player.getWorld().playSound(player.getLocation(),
|
|
||||||
Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
|
|
||||||
player.sendTitle(
|
|
||||||
messages.getString("hatch.escape-title"),
|
|
||||||
messages.getString("hatch.escape-subtitle"),
|
|
||||||
10, 60, 10);
|
|
||||||
|
|
||||||
survivor.setState(PlayerState.ESCAPED);
|
|
||||||
|
|
||||||
giveEscapeReward(survivor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void giveEscapeReward(Survivor survivor) {
|
|
||||||
Player player = survivor.getPlayer();
|
|
||||||
if (player == null) return;
|
|
||||||
|
|
||||||
player.sendMessage(messages.get("hatch.reward"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void forceOpenForEscape() {
|
|
||||||
if (hatch.isHidden()) {
|
|
||||||
hatch.reveal();
|
|
||||||
}
|
|
||||||
if (!hatch.isOpen()) {
|
|
||||||
hatch.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyNearbyPlayers() {
|
|
||||||
Location hatchLoc = hatch.getLocation();
|
|
||||||
World world = hatchLoc.getWorld();
|
|
||||||
if (world == null) return;
|
|
||||||
|
|
||||||
for (Player player : world.getPlayers()) {
|
|
||||||
if (player.getLocation().distance(hatchLoc) < 30) {
|
|
||||||
player.sendMessage(messages.get("hatch.open-notify"));
|
|
||||||
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1.0f, 2.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -32,7 +32,7 @@ public class PlayerInteractListener implements Listener {
|
||||||
private BiConsumer<Player, Boolean> onAttack;
|
private BiConsumer<Player, Boolean> onAttack;
|
||||||
private BiConsumer<Player, Boolean> onRescueAttempt;
|
private BiConsumer<Player, Boolean> onRescueAttempt;
|
||||||
private BiConsumer<Player, Boolean> onChestInteract;
|
private BiConsumer<Player, Boolean> onChestInteract;
|
||||||
private BiConsumer<Player, Boolean> onHatchInteract;
|
private BiConsumer<Player, Boolean> onGateInteract;
|
||||||
/** Called when killer toggles sneak: (player, isSneaking) */
|
/** Called when killer toggles sneak: (player, isSneaking) */
|
||||||
private BiConsumer<Player, Boolean> onKillerSneak;
|
private BiConsumer<Player, Boolean> onKillerSneak;
|
||||||
/** Called when a survivor sneaks near another injured/downed survivor: (healer, target) */
|
/** Called when a survivor sneaks near another injured/downed survivor: (healer, target) */
|
||||||
|
|
@ -56,7 +56,7 @@ public class PlayerInteractListener implements Listener {
|
||||||
public void setOnAttack(BiConsumer<Player, Boolean> h) { this.onAttack = h; }
|
public void setOnAttack(BiConsumer<Player, Boolean> h) { this.onAttack = h; }
|
||||||
public void setOnRescueAttempt(BiConsumer<Player, Boolean> h) { this.onRescueAttempt = h; }
|
public void setOnRescueAttempt(BiConsumer<Player, Boolean> h) { this.onRescueAttempt = h; }
|
||||||
public void setOnChestInteract(BiConsumer<Player, Boolean> h) { this.onChestInteract = h; }
|
public void setOnChestInteract(BiConsumer<Player, Boolean> h) { this.onChestInteract = h; }
|
||||||
public void setOnHatchInteract(BiConsumer<Player, Boolean> h) { this.onHatchInteract = h; }
|
public void setOnGateInteract(BiConsumer<Player, Boolean> h) { this.onGateInteract = h; }
|
||||||
public void setOnKillerSneak(BiConsumer<Player, Boolean> h) { this.onKillerSneak = h; }
|
public void setOnKillerSneak(BiConsumer<Player, Boolean> h) { this.onKillerSneak = h; }
|
||||||
public void setOnHealSneak(BiConsumer<Player, Player> h) { this.onHealSneak = h; }
|
public void setOnHealSneak(BiConsumer<Player, Player> h) { this.onHealSneak = h; }
|
||||||
private BiConsumer<Player, Boolean> onCarriedShift;
|
private BiConsumer<Player, Boolean> onCarriedShift;
|
||||||
|
|
@ -245,12 +245,12 @@ public class PlayerInteractListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gate opening — проверяем ДО генератора, чтобы ворота можно было открыть рядом с геной
|
// Gate opening — проверяем ДО генератора, чтобы ворота можно было открыть рядом с геной
|
||||||
if (!bp.isKiller() && onHatchInteract != null) {
|
if (!bp.isKiller() && onGateInteract != null) {
|
||||||
var s = gameManager.getPlayerSession(player.getUniqueId());
|
var s = gameManager.getPlayerSession(player.getUniqueId());
|
||||||
if (s != null && s.getGateManager() != null) {
|
if (s != null && s.getGateManager() != null) {
|
||||||
var gate = s.getGateManager().getGateAt(player.getLocation(), 3.0);
|
var gate = s.getGateManager().getGateAt(player.getLocation(), 3.0);
|
||||||
if (gate != null && !gate.isOpen()) {
|
if (gate != null && !gate.isOpen()) {
|
||||||
onHatchInteract.accept(player, true);
|
onGateInteract.accept(player, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ public class MapConfig {
|
||||||
applyList("generators", locs);
|
applyList("generators", locs);
|
||||||
applyList("hooks", locs);
|
applyList("hooks", locs);
|
||||||
applyList("chests", locs);
|
applyList("chests", locs);
|
||||||
applyList("windows", locs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,6 @@ public class TemplateManager {
|
||||||
// Chest preset (1x1x1)
|
// Chest preset (1x1x1)
|
||||||
presets.put("chest_default", new PresetMap("chest_default",
|
presets.put("chest_default", new PresetMap("chest_default",
|
||||||
"chest", new Location(null, 0, 0, 0)));
|
"chest", new Location(null, 0, 0, 0)));
|
||||||
|
|
||||||
// Hatch preset (2x1x2)
|
|
||||||
presets.put("hatch_default", new PresetMap("hatch_default",
|
|
||||||
"hatch", new Location(null, 1, 0, 1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean placeObject(String templateName, Location location) {
|
public boolean placeObject(String templateName, Location location) {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,8 @@ package dev.loki.phase;
|
||||||
|
|
||||||
import dev.loki.core.GameSession;
|
import dev.loki.core.GameSession;
|
||||||
import dev.loki.gate.GateManager;
|
import dev.loki.gate.GateManager;
|
||||||
import dev.loki.hatch.Hatch;
|
|
||||||
import dev.loki.hatch.HatchCondition;
|
|
||||||
import dev.loki.hatch.HatchEscape;
|
|
||||||
import dev.loki.player.BasePlayer;
|
import dev.loki.player.BasePlayer;
|
||||||
import dev.loki.player.PlayerState;
|
import dev.loki.player.PlayerState;
|
||||||
import dev.loki.player.Survivor;
|
|
||||||
import dev.loki.ui.Sidebar;
|
import dev.loki.ui.Sidebar;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
@ -27,9 +23,6 @@ public class EndgamePhase implements Phase {
|
||||||
private boolean gatesActivated;
|
private boolean gatesActivated;
|
||||||
private boolean killerWin; // true если маньяк убил всех — пропускаем геймплей эндгейма
|
private boolean killerWin; // true если маньяк убил всех — пропускаем геймплей эндгейма
|
||||||
private GateManager gateManager;
|
private GateManager gateManager;
|
||||||
private Hatch hatch;
|
|
||||||
private HatchCondition hatchCondition;
|
|
||||||
private HatchEscape hatchEscape;
|
|
||||||
private Sidebar sidebar;
|
private Sidebar sidebar;
|
||||||
private int endgameTimer = -1; // секунд до конца эндгейма (-1 = не активно)
|
private int endgameTimer = -1; // секунд до конца эндгейма (-1 = не активно)
|
||||||
|
|
||||||
|
|
@ -37,13 +30,9 @@ public class EndgamePhase implements Phase {
|
||||||
this.openTicks = 20 * 20;
|
this.openTicks = 20 * 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EndgamePhase(GateManager gateManager,
|
public EndgamePhase(GateManager gateManager) {
|
||||||
Hatch hatch, HatchCondition hatchCondition) {
|
|
||||||
this.openTicks = 20 * 20;
|
this.openTicks = 20 * 20;
|
||||||
this.gateManager = gateManager;
|
this.gateManager = gateManager;
|
||||||
this.hatch = hatch;
|
|
||||||
this.hatchCondition = hatchCondition;
|
|
||||||
this.hatchEscape = new HatchEscape(hatch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
@ -120,7 +109,7 @@ public class EndgamePhase implements Phase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHatch(session);
|
updateGates(session);
|
||||||
checkWinConditions(session);
|
checkWinConditions(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,10 +126,6 @@ public class EndgamePhase implements Phase {
|
||||||
sidebar = null;
|
sidebar = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hatch != null) {
|
|
||||||
hatch.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gateManager != null) {
|
if (gateManager != null) {
|
||||||
gateManager.resetAll();
|
gateManager.resetAll();
|
||||||
}
|
}
|
||||||
|
|
@ -229,29 +214,9 @@ public class EndgamePhase implements Phase {
|
||||||
gateManager.activateEndgame();
|
gateManager.activateEndgame();
|
||||||
gatesActivated = true;
|
gatesActivated = true;
|
||||||
}
|
}
|
||||||
checkHatchConditions(session);
|
|
||||||
session.getPlugin().getLogger().info("Endgame started!");
|
session.getPlugin().getLogger().info("Endgame started!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkHatchConditions(GameSession session) {
|
|
||||||
if (hatch == null || hatchCondition == null) return;
|
|
||||||
int repairedGens = countRepairedGenerators(session);
|
|
||||||
hatchCondition.checkAndReveal(hatch, session.getPlayers().values(), repairedGens);
|
|
||||||
if (hatchCondition.isLastSurvivor(session.getPlayers().values())) {
|
|
||||||
hatchCondition.checkAndOpen(hatch, session.getPlayers().values(), repairedGens);
|
|
||||||
if (hatch.isOpen() && hatchEscape != null) {
|
|
||||||
hatchEscape.notifyNearbyPlayers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int countRepairedGenerators(GameSession session) {
|
|
||||||
if (session.getGeneratorManager() != null) {
|
|
||||||
return session.getGeneratorManager().getCompletedCount();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void announceEndgameStart(GameSession session) {
|
private void announceEndgameStart(GameSession session) {
|
||||||
for (BasePlayer bp : session.getPlayers().values()) {
|
for (BasePlayer bp : session.getPlayers().values()) {
|
||||||
Player p = bp.getPlayer();
|
Player p = bp.getPlayer();
|
||||||
|
|
@ -271,18 +236,6 @@ public class EndgamePhase implements Phase {
|
||||||
gateManager.updateAllGates(1.0 / openTicks);
|
gateManager.updateAllGates(1.0 / openTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateHatch(GameSession session) {
|
|
||||||
if (hatch == null || !hatch.isOpen() || hatchEscape == null) return;
|
|
||||||
for (BasePlayer player : session.getPlayers().values()) {
|
|
||||||
if (player.isKiller()) continue;
|
|
||||||
PlayerState st = player.getState();
|
|
||||||
if (st != PlayerState.HEALTHY && st != PlayerState.INJURED) continue;
|
|
||||||
if (hatchEscape.canEscape((Survivor) player)) {
|
|
||||||
hatchEscape.tryEscape((Survivor) player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkWinConditions(GameSession session) {
|
private void checkWinConditions(GameSession session) {
|
||||||
if (complete) return;
|
if (complete) return;
|
||||||
int survivorsAlive = 0;
|
int survivorsAlive = 0;
|
||||||
|
|
|
||||||
|
|
@ -301,8 +301,8 @@ public class GameplayInteraction {
|
||||||
damageSystem.getKillerController().getCarry().onSurvivorShift(survivor.getUuid());
|
damageSystem.getKillerController().getCarry().onSurvivorShift(survivor.getUuid());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gate (uses hatch callback - triggered on PORTAL/HOPPER interaction)
|
// Gate - triggered on HOPPER interaction
|
||||||
interactListener.setOnHatchInteract((player, ignored) -> {
|
interactListener.setOnGateInteract((player, ignored) -> {
|
||||||
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
BasePlayer bp = session.getPlayer(player.getUniqueId());
|
||||||
if (bp == null || bp.isKiller()) return;
|
if (bp == null || bp.isKiller()) return;
|
||||||
Survivor survivor = (Survivor) bp;
|
Survivor survivor = (Survivor) bp;
|
||||||
|
|
@ -337,7 +337,7 @@ public class GameplayInteraction {
|
||||||
interactListener.setOnCarriedShift(null);
|
interactListener.setOnCarriedShift(null);
|
||||||
interactListener.setOnGeneratorSkillCheckSneak(null);
|
interactListener.setOnGeneratorSkillCheckSneak(null);
|
||||||
interactListener.setOnGeneratorInteract(null);
|
interactListener.setOnGeneratorInteract(null);
|
||||||
interactListener.setOnHatchInteract(null);
|
interactListener.setOnGateInteract(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -176,20 +176,6 @@ bossbar:
|
||||||
# Расстояние полного заполнения (блоков)
|
# Расстояние полного заполнения (блоков)
|
||||||
full-range: 8
|
full-range: 8
|
||||||
|
|
||||||
# Окна
|
|
||||||
window:
|
|
||||||
# Быстрый волт выжившего (секунд)
|
|
||||||
vault-survivor-fast: 1.0
|
|
||||||
|
|
||||||
# Медленный волт выжившего (секунд)
|
|
||||||
vault-survivor-slow: 1.5
|
|
||||||
|
|
||||||
# Волт киллера (секунд)
|
|
||||||
vault-killer: 1.5
|
|
||||||
|
|
||||||
# Блокировка после 3 волтов подряд (секунд)
|
|
||||||
vault-block-seconds: 15
|
|
||||||
|
|
||||||
# Эндгейм
|
# Эндгейм
|
||||||
endgame:
|
endgame:
|
||||||
# Время открытия ворот (секунд)
|
# Время открытия ворот (секунд)
|
||||||
|
|
@ -229,14 +215,6 @@ scoreboard:
|
||||||
color-healing: "GREEN"
|
color-healing: "GREEN"
|
||||||
color-hooked: "DARK_RED"
|
color-hooked: "DARK_RED"
|
||||||
|
|
||||||
# Люк
|
|
||||||
hatch:
|
|
||||||
# Минимум живых для открытия люка
|
|
||||||
min-survivors-for-open: 1
|
|
||||||
|
|
||||||
# Условие: живых < починенных генераторов
|
|
||||||
require-more-gens-than-survivors: true
|
|
||||||
|
|
||||||
# Блоки для объектов (спавнятся на местах при старте игры)
|
# Блоки для объектов (спавнятся на местах при старте игры)
|
||||||
blocks:
|
blocks:
|
||||||
# Блок на месте генератора
|
# Блок на месте генератора
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,6 @@ hooks: []
|
||||||
# Пример:
|
# Пример:
|
||||||
# - "world,120.5,65.0,180.5,0.0,0.0"
|
# - "world,120.5,65.0,180.5,0.0,0.0"
|
||||||
|
|
||||||
# Окна (много)
|
|
||||||
windows: []
|
|
||||||
|
|
||||||
# Сундуки с лутом (3-4)
|
# Сундуки с лутом (3-4)
|
||||||
chests: []
|
chests: []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ dbdadmin:
|
||||||
hooks:
|
hooks:
|
||||||
usage: "%admin-prefix%&c/dbd admin hooks <игрок> <0-3>"
|
usage: "%admin-prefix%&c/dbd admin hooks <игрок> <0-3>"
|
||||||
sender: "%admin-prefix%&a%s hooks=%d"
|
sender: "%admin-prefix%&a%s hooks=%d"
|
||||||
invalid: "%admin-prefix%&cЧисло 0–3."
|
invalid: "%admin-prefix%&cЧисло 0-3."
|
||||||
kill:
|
kill:
|
||||||
sender: "%admin-prefix%&c%s → DEAD"
|
sender: "%admin-prefix%&c%s → DEAD"
|
||||||
resolve:
|
resolve:
|
||||||
|
|
@ -152,8 +152,8 @@ lobby:
|
||||||
# ── Роли ───────────────────────────────────────
|
# ── Роли ───────────────────────────────────────
|
||||||
|
|
||||||
role:
|
role:
|
||||||
killer: "%prefix%&4Вы — Маньяк! Поймайте всех выживших!"
|
killer: "%prefix%&4Вы - Маньяк! Поймайте всех выживших!"
|
||||||
survivor: "%prefix%&bВы — Выживший! Почините генераторы и сбегите!"
|
survivor: "%prefix%&bВы - Выживший! Почините генераторы и сбегите!"
|
||||||
|
|
||||||
# ── Генераторы ─────────────────────────────────
|
# ── Генераторы ─────────────────────────────────
|
||||||
|
|
||||||
|
|
@ -256,17 +256,6 @@ gate:
|
||||||
door-interrupted: "&7Открытие прервано!"
|
door-interrupted: "&7Открытие прервано!"
|
||||||
door-actionbar: "&aОткрываем ворота... (зажмите ПКМ)"
|
door-actionbar: "&aОткрываем ворота... (зажмите ПКМ)"
|
||||||
|
|
||||||
# ── Люк ────────────────────────────────────────
|
|
||||||
|
|
||||||
hatch:
|
|
||||||
too-far: "&cПодойдите ближе к люку!"
|
|
||||||
hidden: "&7Люк скрыт..."
|
|
||||||
closed: "&cЛюк закрыт!"
|
|
||||||
open-notify: "&e&lЛюк открыт!"
|
|
||||||
escape-title: "&a&lПОБЕГ!"
|
|
||||||
escape-subtitle: "&7Вы сбежали через люк!"
|
|
||||||
reward: "&a+5000 Очков — Побег через люк!"
|
|
||||||
|
|
||||||
# ── Игрок вышел ────────────────────────────────
|
# ── Игрок вышел ────────────────────────────────
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
|
|
@ -286,19 +275,19 @@ minigames:
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
dbd-header: "&6=== DBD Команды ==="
|
dbd-header: "&6=== DBD Команды ==="
|
||||||
dbd-join: "&7/dbd join [name] — присоединиться к игре/лобби"
|
dbd-join: "&7/dbd join [name] - присоединиться к игре/лобби"
|
||||||
dbd-leave: "&7/dbd leave — покинуть игру"
|
dbd-leave: "&7/dbd leave - покинуть игру"
|
||||||
dbd-lobby: "&7/dbd lobby — телепорт в лобби"
|
dbd-lobby: "&7/dbd lobby - телепорт в лобби"
|
||||||
dbd-create: "&7/dbd create — создать лобби"
|
dbd-create: "&7/dbd create - создать лобби"
|
||||||
dbd-list: "&7/dbd list — список лобби"
|
dbd-list: "&7/dbd list - список лобби"
|
||||||
dbd-delete: "&7/dbd delete — удалить лобби"
|
dbd-delete: "&7/dbd delete - удалить лобби"
|
||||||
dbd-admin: "&e/dbd admin — управление игроками в матче"
|
dbd-admin: "&e/dbd admin - управление игроками в матче"
|
||||||
dbd-forcestart: "&e/dbd forcestart — форс старт"
|
dbd-forcestart: "&e/dbd forcestart - форс старт"
|
||||||
dbd-stop: "&e/dbd stop — остановить игру"
|
dbd-stop: "&e/dbd stop - остановить игру"
|
||||||
dbd-reload: "&e/dbd reload — перезагрузить конфиги"
|
dbd-reload: "&e/dbd reload - перезагрузить конфиги"
|
||||||
dbd-setlobby: "&e/dbd setlobby — установить точку лобби"
|
dbd-setlobby: "&e/dbd setlobby - установить точку лобби"
|
||||||
dbd-save: "&e/dbd save — сохранить карту"
|
dbd-save: "&e/dbd save - сохранить карту"
|
||||||
dbd-load: "&e/dbd load — загрузить карту"
|
dbd-load: "&e/dbd load - загрузить карту"
|
||||||
admin-header: "&6=== /dbd admin ==="
|
admin-header: "&6=== /dbd admin ==="
|
||||||
admin-heal: "&6/dbd admin heal [игрок]"
|
admin-heal: "&6/dbd admin heal [игрок]"
|
||||||
admin-down: "&6/dbd admin down [игрок]"
|
admin-down: "&6/dbd admin down [игрок]"
|
||||||
|
|
@ -306,20 +295,20 @@ usage:
|
||||||
admin-state: "&6/dbd admin state <игрок> <статус>"
|
admin-state: "&6/dbd admin state <игрок> <статус>"
|
||||||
admin-hooks: "&6/dbd admin hooks <игрок> <0-3>"
|
admin-hooks: "&6/dbd admin hooks <игрок> <0-3>"
|
||||||
admin-kill: "&6/dbd admin kill [игрок]"
|
admin-kill: "&6/dbd admin kill [игрок]"
|
||||||
admin-jump: "&6/dbd admin jump [on/off] — вкл/выкл прыжки"
|
admin-jump: "&6/dbd admin jump [on/off] - вкл/выкл прыжки"
|
||||||
setup-header: "&6=== DBD Setup ==="
|
setup-header: "&6=== DBD Setup ==="
|
||||||
setup-wand: "&6/dbdsetup wand — Получить ванд (ЛКМ/ПКМ для ворот)"
|
setup-wand: "&6/dbdsetup wand - Получить ванд (ЛКМ/ПКМ для ворот)"
|
||||||
setup-hook: "&6/dbdsetup set hook — Установить крюк (ломай блок)"
|
setup-hook: "&6/dbdsetup set hook - Установить крюк (ломай блок)"
|
||||||
setup-chest: "&6/dbdsetup set chest — Установить сундук"
|
setup-chest: "&6/dbdsetup set chest - Установить сундук"
|
||||||
setup-generator: "&6/dbdsetup set generator — Установить генератор"
|
setup-generator: "&6/dbdsetup set generator - Установить генератор"
|
||||||
setup-killer-spawn: "&6/dbdsetup set killer-spawn — Спавн киллера (только 1)"
|
setup-killer-spawn: "&6/dbdsetup set killer-spawn - Спавн киллера (только 1)"
|
||||||
setup-survivor-spawn: "&6/dbdsetup set survivor-spawn — Спавн выжившего (до 4)"
|
setup-survivor-spawn: "&6/dbdsetup set survivor-spawn - Спавн выжившего (до 4)"
|
||||||
setup-gate: "&6/dbdsetup set gate A|B — Установить ворота (из точек ванда)"
|
setup-gate: "&6/dbdsetup set gate A|B - Установить ворота (из точек ванда)"
|
||||||
setup-clear: "&6/dbdsetup clear [тип] — Очистить объекты (без разрушения блоков)"
|
setup-clear: "&6/dbdsetup clear [тип] - Очистить объекты (без разрушения блоков)"
|
||||||
setup-delete: "&6/dbdsetup delete <тип> <#> — Удалить конкретный объект"
|
setup-delete: "&6/dbdsetup delete <тип> <#> - Удалить конкретный объект"
|
||||||
setup-clear-spawns: "&6/dbdsetup clear-spawns — Очистить все спавны"
|
setup-clear-spawns: "&6/dbdsetup clear-spawns - Очистить все спавны"
|
||||||
setup-lobby: "&6/dbdsetup lobby — Установить точку лобби"
|
setup-lobby: "&6/dbdsetup lobby - Установить точку лобби"
|
||||||
admin-list-header: "&6=== DBD Admin ==="
|
admin-list-header: "&6=== DBD Admin ==="
|
||||||
admin-list-list: "&6/dbdadmin list — Список всех объектов"
|
admin-list-list: "&6/dbdadmin list - Список всех объектов"
|
||||||
admin-list-type: "&6/dbdadmin list <тип> — Список по типу"
|
admin-list-type: "&6/dbdadmin list <тип> - Список по типу"
|
||||||
admin-world: "&6/dbdadmin world <game|мир> — Телепорт в мир"
|
admin-world: "&6/dbdadmin world <game|мир> - Телепорт в мир"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue