diff --git a/src/main/java/dev/loki/killer/KillerVision.java b/src/main/java/dev/loki/killer/KillerVision.java new file mode 100644 index 0000000..11272d7 --- /dev/null +++ b/src/main/java/dev/loki/killer/KillerVision.java @@ -0,0 +1,125 @@ +package dev.loki.killer; + +import dev.loki.player.Killer; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; + +public class KillerVision extends BukkitRunnable { + + private static final long PARTICLE_INTERVAL = 5L; + private static final int PARTICLE_COUNT = 5; + private static final double PARTICLE_SPACING = 0.3; + + private final JavaPlugin plugin; + private Killer killer; + private boolean active; + + public KillerVision(JavaPlugin plugin) { + this.plugin = plugin; + this.active = false; + } + + public void setKiller(Killer killer) { + this.killer = killer; + } + + public void start() { + this.active = true; + runTaskTimer(plugin, 0L, PARTICLE_INTERVAL); + } + + public void stop() { + this.active = false; + cancel(); + } + + public boolean isActive() { + return active; + } + + @Override + public void run() { + if (!active || killer == null || !killer.isOnline()) { + return; + } + + Player player = killer.getPlayer(); + if (player == null) return; + + spawnRedStain(player); + } + + private void spawnRedStain(Player player) { + Location eyeLoc = player.getEyeLocation(); + Vector direction = eyeLoc.getDirection(); + World world = player.getWorld(); + + for (int i = 0; i < PARTICLE_COUNT; i++) { + double distance = 1.0 + (i * PARTICLE_SPACING); + Location particleLoc = eyeLoc.clone().add(direction.clone().multiply(distance)); + + particleLoc.setY(particleLoc.getY() - 0.5); + + world.spawnParticle( + Particle.REDSTONE, + particleLoc, + 1, + 0, 0, 0, + 0, + new Particle.DustOptions(org.bukkit.Color.RED, 1.0f) + ); + } + + world.spawnParticle( + Particle.DRIPPING_LAVA, + eyeLoc.clone().add(direction.clone().multiply(0.5)), + 2, + 0.1, 0.1, 0.1, + 0 + ); + } + + public void spawnAttackEffect(Location location) { + World world = location.getWorld(); + if (world == null) return; + + world.spawnParticle( + Particle.CRIT, + location, + 20, + 0.5, 0.5, 0.5, + 0.1 + ); + + world.spawnParticle( + Particle.REDSTONE, + location, + 15, + 0.3, 0.3, 0.3, + 0, + new Particle.DustOptions(org.bukkit.Color.MAROON, 1.5f) + ); + } + + public void spawnLungeEffect(Player player) { + Location loc = player.getLocation(); + World world = player.getWorld(); + Vector direction = loc.getDirection(); + + for (int i = 0; i < 10; i++) { + Location particleLoc = loc.clone().add(direction.clone().multiply(i * 0.3)); + world.spawnParticle( + Particle.SWEEP_ATTACK, + particleLoc, + 1, + 0.2, 0.2, 0.2, + 0 + ); + } + } +} diff --git a/src/main/java/dev/loki/objective/GeneratorRegression.java b/src/main/java/dev/loki/objective/GeneratorRegression.java new file mode 100644 index 0000000..7390102 --- /dev/null +++ b/src/main/java/dev/loki/objective/GeneratorRegression.java @@ -0,0 +1,68 @@ +package dev.loki.objective; + +import dev.loki.config.GameConfig; + +public class GeneratorRegression { + private final GameConfig config; + + private static final double NORMAL_REGRESSION_PER_TICK = 0.25 / 20.0; + private static final double KICK_REGRESSION_PER_TICK = 2.5 / 20.0; + + public GeneratorRegression(GameConfig config) { + this.config = config; + } + + public void applyRegression(Generator generator) { + if (generator.isCompleted() || generator.isBeingRepaired()) { + return; + } + + double rate = generator.wasKicked() ? getKickRegressionRate() : getNormalRegressionRate(); + generator.removeProgress(rate); + } + + public void onGeneratorKicked(Generator generator) { + generator.setKicked(true); + generator.setRegressionTicks(config.getKickDuration() * 20); + } + + public void tick(Generator generator) { + if (!generator.isUnderRegression()) { + return; + } + + applyRegression(generator); + generator.decrementRegression(); + + if (generator.getRegressionTicks() <= 0) { + generator.setKicked(false); + } + } + + public void tickAll(GeneratorManager manager) { + for (Generator gen : manager.getAllGenerators()) { + if (!gen.isCompleted() && !gen.isBeingRepaired()) { + tick(gen); + } + } + } + + private double getNormalRegressionRate() { + return config.getRegressionRate() / 20.0; + } + + private double getKickRegressionRate() { + return config.getKickRegressionRate() / 20.0; + } + + public static boolean shouldStartRegression(Generator generator) { + return !generator.isCompleted() + && !generator.isBeingRepaired() + && generator.getProgress() > 0; + } + + public static double calculateRegressionLoss(double progress, int regressionTicks, boolean wasKicked) { + double rate = wasKicked ? KICK_REGRESSION_PER_TICK : NORMAL_REGRESSION_PER_TICK; + return Math.min(progress, rate * regressionTicks); + } +}