From a4f96297c207449817bdf939cf39a36b643a7224 Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sat, 8 Feb 2025 00:39:05 +0100 Subject: [PATCH] Improve CTF gameplay mechanics and particle effects Updated class selection to restrict changes during non-selection phases and adjusted spawn radius. Added flag particle trails and square border effects, improving visual feedback. Enhanced flag handling, clearing trails when the carrier is lost or offline. --- .../ctf/commands/subcommands/SelectClass.java | 7 ++- src/main/java/com/alttd/ctf/flag/Flag.java | 46 +++++++++++++++++-- version.properties | 4 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java b/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java index 698b6a6..7e68ae9 100644 --- a/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java +++ b/src/main/java/com/alttd/ctf/commands/subcommands/SelectClass.java @@ -3,6 +3,7 @@ package com.alttd.ctf.commands.subcommands; import com.alttd.ctf.commands.SubCommand; import com.alttd.ctf.config.Messages; import com.alttd.ctf.game.GameManager; +import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.game_class.creation.FighterCreator; import com.alttd.ctf.game_class.creation.TankCreator; @@ -36,17 +37,19 @@ public class SelectClass extends SubCommand { commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY); return -1; } - if (gameManager.getGamePhase().isEmpty()) { + Optional optionalGamePhase = gameManager.getGamePhase(); + if (optionalGamePhase.isEmpty()) { commandSender.sendRichMessage("CTF has to be running to select a class."); return 0; } + GamePhase gamePhase = optionalGamePhase.get(); Optional optionalTeamPlayer = gameManager.getTeamPlayer(player.getUniqueId()); if (optionalTeamPlayer.isEmpty()) { commandSender.sendRichMessage("You have to be in a CTF team to select a class."); return 0; } TeamPlayer teamPlayer = optionalTeamPlayer.get(); - if (teamPlayer.getTeam().getSpawnLocation().distance(player.getLocation()) > 15) { + if (!gamePhase.equals(GamePhase.CLASS_SELECTION) && teamPlayer.getTeam().getSpawnLocation().distance(player.getLocation()) > 5) { commandSender.sendRichMessage("You have to be near your spawn to change classes."); return 0; } diff --git a/src/main/java/com/alttd/ctf/flag/Flag.java b/src/main/java/com/alttd/ctf/flag/Flag.java index 4b27740..ca79e46 100644 --- a/src/main/java/com/alttd/ctf/flag/Flag.java +++ b/src/main/java/com/alttd/ctf/flag/Flag.java @@ -4,6 +4,7 @@ import com.alttd.ctf.Main; import com.alttd.ctf.config.Config; import com.alttd.ctf.game.GameManager; import com.alttd.ctf.team.Team; +import com.alttd.ctf.team.TeamColor; import com.alttd.ctf.team.TeamPlayer; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -24,6 +25,7 @@ import org.bukkit.scheduler.BukkitScheduler; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Future; import java.util.stream.Collectors; @@ -38,7 +40,7 @@ public class Flag implements Runnable { private int lastWinningTeamId = -1; private Location flagLocation; private Team winningTeam; - private Player flagCarrier; //TODO check for player disconnects? + private Player flagCarrier; private final Main main; private final GameManager gameManager; @@ -79,6 +81,7 @@ public class Flag implements Runnable { Placeholder.component("team", teamPlayer.getTeam().getName()) ))); flagCarrier = player; + teamFlagPointCount.clear(); } public void spawnFlag() { @@ -102,6 +105,7 @@ public class Flag implements Runnable { log.warn("Tried to run Flag without a flag location, spawn it first"); return; } + spawnParticlesOnSquareBorder(flagLocation.getWorld(), flagLocation); if (!updateScoreBasedOnNearbyPlayers().join()) { return; //Score didn't change } @@ -119,14 +123,49 @@ public class Flag implements Runnable { } } + private void spawnParticlesOnSquareBorder(World world, Location center) { + double size = 10; + double step = 0.2; + center.add(0, 0.5, 0); + Bukkit.getScheduler().runTask(main, () -> { + // Top and Bottom (Z varies, X constant) + for (double z = -size; z <= size; z += step) { + world.spawnParticle(Particle.FLAME, center.getX() + size, center.getY(), center.getZ() + z, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, center.getX() - size, center.getY(), center.getZ() + z, 1, 0, 0, 0, 0); + } + + // Left and Right (X varies, Z constant) + for (double x = -size; x <= size; x += step) { + world.spawnParticle(Particle.FLAME, center.getX() + x, center.getY(), center.getZ() + size, 1, 0, 0, 0, 0); + world.spawnParticle(Particle.FLAME, center.getX() + x, center.getY(), center.getZ() - size, 1, 0, 0, 0, 0); + } + }); + } + + LinkedList particleTrail = new LinkedList<>(); + + private void spawnTrail() { + TeamColor color = winningTeam.getColor(); + particleTrail.forEach(location -> location.getWorld().spawnParticle(Particle.DUST, location, 1, 0, 0, 0, + new Particle.DustOptions(Color.fromRGB(color.r(), color.g(), color.b()), 1))); + if (particleTrail.size() > 15) { + particleTrail.removeFirst(); + } + } + private void checkFlagCarrier() { - if (flagCarrier.isDead()) { + if (flagCarrier.isDead() || !flagCarrier.isOnline()) { flagCarrier = null; + particleTrail.clear(); spawnFlag(); return; } double distance = winningTeam.getSpawnLocation().distance(flagCarrier.getLocation()); if (distance > 5) { + Location location = flagCarrier.getLocation(); + location.setY(location.getY() + 1); + particleTrail.add(location); + spawnTrail(); //TODO spawn some particles or something so a trail is made for specific classes to follow? return; } @@ -145,8 +184,8 @@ public class Flag implements Runnable { teamPlayer.getGameClass().setArmor(flagCarrier, teamPlayer); flagCarrier.getInventory().setItem(EquipmentSlot.HEAD, null); } - teamFlagPointCount.clear(); flagCarrier = null; + particleTrail.clear(); } private Optional winnerExists() { @@ -273,6 +312,7 @@ public class Flag implements Runnable { bossBar.setProgress(0); winningTeam = null; flagCarrier = null; + particleTrail.clear(); wins.clear(); lastWinningTeamId = -1; } diff --git a/version.properties b/version.properties index 6f9094b..f71f3b8 100644 --- a/version.properties +++ b/version.properties @@ -1,3 +1,3 @@ -#Fri Feb 07 23:34:22 CET 2025 -buildNumber=9 +#Sat Feb 08 00:30:51 CET 2025 +buildNumber=11 version=0.1