Stage 12: Data storage system
This commit is contained in:
parent
82ed455cd2
commit
4fd7955d56
62 changed files with 5613 additions and 0 deletions
99
src/main/java/dev/loki/killer/HitValidator.java
Normal file
99
src/main/java/dev/loki/killer/HitValidator.java
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package dev.loki.killer;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class HitValidator {
|
||||
private static final double ATTACK_ANGLE = 60.0;
|
||||
private static final double MAX_VERTICAL_ANGLE = 45.0;
|
||||
|
||||
public static boolean isValidHit(Player killer, Player target, double maxRange) {
|
||||
if (!target.isOnline() || target.isDead()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Location killerLoc = killer.getEyeLocation();
|
||||
Location targetLoc = target.getEyeLocation();
|
||||
|
||||
double distance = killerLoc.distance(targetLoc);
|
||||
if (distance > maxRange) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasLineOfSight(killer, target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isWithinAttackAngle(killer, targetLoc);
|
||||
}
|
||||
|
||||
private static boolean hasLineOfSight(Player from, Player to) {
|
||||
Location eyeLoc = from.getEyeLocation();
|
||||
Vector direction = to.getEyeLocation().toVector().subtract(eyeLoc.toVector());
|
||||
|
||||
double distance = direction.length();
|
||||
direction.normalize();
|
||||
|
||||
RayTraceResult result = from.getWorld().rayTraceBlocks(
|
||||
eyeLoc,
|
||||
direction,
|
||||
distance,
|
||||
org.bukkit.FluidCollisionMode.NEVER,
|
||||
true
|
||||
);
|
||||
|
||||
return result == null || result.getHitBlock() == null;
|
||||
}
|
||||
|
||||
private static boolean isWithinAttackAngle(Player killer, Location target) {
|
||||
Vector killerDir = killer.getEyeLocation().getDirection();
|
||||
Vector toTarget = target.toVector().subtract(killer.getEyeLocation().toVector());
|
||||
|
||||
double horizontalAngle = Math.toDegrees(killerDir.clone().setY(0).angle(toTarget.clone().setY(0)));
|
||||
if (horizontalAngle > ATTACK_ANGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double verticalDiff = toTarget.getY();
|
||||
double horizontalDist = Math.sqrt(toTarget.getX() * toTarget.getX() + toTarget.getZ() * toTarget.getZ());
|
||||
double verticalAngle = Math.toDegrees(Math.atan2(verticalDiff, horizontalDist));
|
||||
|
||||
return Math.abs(verticalAngle) <= MAX_VERTICAL_ANGLE;
|
||||
}
|
||||
|
||||
public static boolean isValidCarryPosition(Player killer, Player carried) {
|
||||
Location kLoc = killer.getLocation();
|
||||
Location cLoc = carried.getLocation();
|
||||
|
||||
double horizontalDist = Math.sqrt(
|
||||
Math.pow(kLoc.getX() - cLoc.getX(), 2) +
|
||||
Math.pow(kLoc.getZ() - cLoc.getZ(), 2)
|
||||
);
|
||||
|
||||
double yDiff = Math.abs(kLoc.getY() - cLoc.getY());
|
||||
|
||||
return horizontalDist <= 2.0 && yDiff <= 1.5;
|
||||
}
|
||||
|
||||
public static boolean hasClearPath(Player from, Location to) {
|
||||
Location eyeLoc = from.getEyeLocation();
|
||||
Vector direction = to.toVector().subtract(eyeLoc.toVector());
|
||||
double distance = direction.length();
|
||||
direction.normalize();
|
||||
|
||||
RayTraceResult result = from.getWorld().rayTraceBlocks(
|
||||
eyeLoc,
|
||||
direction,
|
||||
distance,
|
||||
org.bukkit.FluidCollisionMode.NEVER,
|
||||
true
|
||||
);
|
||||
|
||||
return result == null || result.getHitBlock() == null;
|
||||
}
|
||||
}
|
||||
126
src/main/java/dev/loki/killer/KillerAttack.java
Normal file
126
src/main/java/dev/loki/killer/KillerAttack.java
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package dev.loki.killer;
|
||||
|
||||
import dev.loki.config.GameConfig;
|
||||
import dev.loki.damage.DamageHandler;
|
||||
import dev.loki.player.Killer;
|
||||
import dev.loki.player.PlayerManager;
|
||||
import dev.loki.player.Survivor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KillerAttack {
|
||||
private final Plugin plugin;
|
||||
private final PlayerManager playerManager;
|
||||
private final DamageHandler damageHandler;
|
||||
private final GameConfig config;
|
||||
private final Map<UUID, Long> cooldowns;
|
||||
private BukkitTask cleanupTask;
|
||||
|
||||
public KillerAttack(Plugin plugin, PlayerManager playerManager,
|
||||
DamageHandler damageHandler, GameConfig config) {
|
||||
this.plugin = plugin;
|
||||
this.playerManager = playerManager;
|
||||
this.damageHandler = damageHandler;
|
||||
this.config = config;
|
||||
this.cooldowns = new HashMap<>();
|
||||
startCleanupTask();
|
||||
}
|
||||
|
||||
public boolean tryAttack(Killer killer, Survivor target) {
|
||||
if (!canAttack(killer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player killerPlayer = killer.getPlayer();
|
||||
Player targetPlayer = target.getPlayer();
|
||||
|
||||
if (killerPlayer == null || targetPlayer == null) return false;
|
||||
if (!targetPlayer.isOnline()) return false;
|
||||
|
||||
if (!HitValidator.isValidHit(killerPlayer, targetPlayer, config.getAttackRange())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!damageHandler.applyDamage(target)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
applyCooldown(killer);
|
||||
playAttackEffects(killerPlayer, targetPlayer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canAttack(Killer killer) {
|
||||
Long lastAttack = cooldowns.get(killer.getUuid());
|
||||
if (lastAttack == null) return true;
|
||||
|
||||
int cooldownTicks = config.getAttackCooldown();
|
||||
long currentTick = Bukkit.getCurrentTick();
|
||||
return currentTick - lastAttack >= cooldownTicks;
|
||||
}
|
||||
|
||||
private void applyCooldown(Killer killer) {
|
||||
cooldowns.put(killer.getUuid(), Bukkit.getCurrentTick());
|
||||
}
|
||||
|
||||
public double getCooldownProgress(Killer killer) {
|
||||
Long lastAttack = cooldowns.get(killer.getUuid());
|
||||
if (lastAttack == null) return 1.0;
|
||||
|
||||
int cooldownTicks = config.getAttackCooldown();
|
||||
long currentTick = Bukkit.getCurrentTick();
|
||||
long elapsed = currentTick - lastAttack;
|
||||
|
||||
return Math.min(1.0, (double) elapsed / cooldownTicks);
|
||||
}
|
||||
|
||||
public boolean isOnCooldown(Killer killer) {
|
||||
return !canAttack(killer);
|
||||
}
|
||||
|
||||
private void playAttackEffects(Player killer, Player target) {
|
||||
killer.getWorld().playSound(killer.getLocation(),
|
||||
org.bukkit.Sound.ENTITY_PLAYER_ATTACK_STRONG, 1.0f, 0.8f);
|
||||
|
||||
target.getWorld().playSound(target.getLocation(),
|
||||
org.bukkit.Sound.ENTITY_PLAYER_HURT, 1.0f, 1.0f);
|
||||
|
||||
org.bukkit.Particle particle = target.getHealth() <= 4 ?
|
||||
org.bukkit.Particle.DAMAGE_INDICATOR : org.bukkit.Particle.CRIT;
|
||||
|
||||
target.getWorld().spawnParticle(particle, target.getLocation().add(0, 1, 0),
|
||||
10, 0.3, 0.5, 0.3, 0.1);
|
||||
}
|
||||
|
||||
public void attackNearest(Killer killer) {
|
||||
Player killerPlayer = killer.getPlayer();
|
||||
if (killerPlayer == null) return;
|
||||
|
||||
Survivor nearest = playerManager.getNearestSurvivor(killerPlayer, config.getAttackRange());
|
||||
if (nearest != null) {
|
||||
tryAttack(killer, nearest);
|
||||
}
|
||||
}
|
||||
|
||||
private void startCleanupTask() {
|
||||
cleanupTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
long currentTick = Bukkit.getCurrentTick();
|
||||
int cooldownTicks = config.getAttackCooldown();
|
||||
cooldowns.entrySet().removeIf(e -> currentTick - e.getValue() > cooldownTicks * 2);
|
||||
}, 1200L, 1200L);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (cleanupTask != null) {
|
||||
cleanupTask.cancel();
|
||||
}
|
||||
cooldowns.clear();
|
||||
}
|
||||
}
|
||||
189
src/main/java/dev/loki/killer/KillerCarry.java
Normal file
189
src/main/java/dev/loki/killer/KillerCarry.java
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
package dev.loki.killer;
|
||||
|
||||
import dev.loki.config.GameConfig;
|
||||
import dev.loki.player.Killer;
|
||||
import dev.loki.player.Survivor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KillerCarry {
|
||||
private final Plugin plugin;
|
||||
private final GameConfig config;
|
||||
private final Map<UUID, CarryData> activeCarries;
|
||||
private BukkitTask carryTask;
|
||||
|
||||
private static class CarryData {
|
||||
final Killer killer;
|
||||
final Survivor survivor;
|
||||
double wiggleProgress;
|
||||
|
||||
CarryData(Killer killer, Survivor survivor) {
|
||||
this.killer = killer;
|
||||
this.survivor = survivor;
|
||||
this.wiggleProgress = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public KillerCarry(Plugin plugin, GameConfig config) {
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.activeCarries = new HashMap<>();
|
||||
}
|
||||
|
||||
public boolean tryPickup(Killer killer, Survivor survivor) {
|
||||
if (!canPickup(killer, survivor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player killerPlayer = killer.getPlayer();
|
||||
Player survivorPlayer = survivor.getPlayer();
|
||||
|
||||
if (killerPlayer == null || survivorPlayer == null) return false;
|
||||
|
||||
if (!HitValidator.isValidCarryPosition(killerPlayer, survivorPlayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
startCarry(killer, survivor);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean canPickup(Killer killer, Survivor survivor) {
|
||||
if (killer.isCarrying()) return false;
|
||||
if (!survivor.getState().name().equals("DOWNED")) return false;
|
||||
|
||||
Player killerPlayer = killer.getPlayer();
|
||||
Player survivorPlayer = survivor.getPlayer();
|
||||
|
||||
return killerPlayer != null && survivorPlayer != null && survivorPlayer.isOnline();
|
||||
}
|
||||
|
||||
private void startCarry(Killer killer, Survivor survivor) {
|
||||
killer.setCarrying(true);
|
||||
|
||||
Player survivorPlayer = survivor.getPlayer();
|
||||
if (survivorPlayer != null) {
|
||||
survivorPlayer.setInvisible(true);
|
||||
}
|
||||
|
||||
CarryData data = new CarryData(killer, survivor);
|
||||
activeCarries.put(killer.getUuid(), data);
|
||||
|
||||
if (carryTask == null) {
|
||||
startCarryTask();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean drop(Killer killer) {
|
||||
CarryData data = activeCarries.remove(killer.getUuid());
|
||||
if (data == null) return false;
|
||||
|
||||
stopCarry(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void stopCarry(CarryData data) {
|
||||
data.killer.setCarrying(false);
|
||||
|
||||
Player survivorPlayer = data.survivor.getPlayer();
|
||||
if (survivorPlayer != null) {
|
||||
survivorPlayer.setInvisible(false);
|
||||
survivorPlayer.teleport(data.killer.getPlayer().getLocation());
|
||||
}
|
||||
|
||||
if (activeCarries.isEmpty() && carryTask != null) {
|
||||
carryTask.cancel();
|
||||
carryTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void startCarryTask() {
|
||||
carryTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
activeCarries.values().removeIf(data -> {
|
||||
if (!isValidCarry(data)) {
|
||||
stopCarry(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
updateCarryPosition(data);
|
||||
updateWiggle(data);
|
||||
|
||||
return false;
|
||||
});
|
||||
}, 1L, 1L);
|
||||
}
|
||||
|
||||
private boolean isValidCarry(CarryData data) {
|
||||
Player killerPlayer = data.killer.getPlayer();
|
||||
Player survivorPlayer = data.survivor.getPlayer();
|
||||
|
||||
if (killerPlayer == null || survivorPlayer == null) return false;
|
||||
if (!killerPlayer.isOnline() || !survivorPlayer.isOnline()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateCarryPosition(CarryData data) {
|
||||
Player killerPlayer = data.killer.getPlayer();
|
||||
Player survivorPlayer = data.survivor.getPlayer();
|
||||
|
||||
Location carryLoc = killerPlayer.getLocation().clone().add(0, -0.5, 0);
|
||||
survivorPlayer.teleport(carryLoc);
|
||||
}
|
||||
|
||||
private void updateWiggle(CarryData data) {
|
||||
Player survivorPlayer = data.survivor.getPlayer();
|
||||
if (survivorPlayer == null) return;
|
||||
|
||||
if (survivorPlayer.isSneaking()) {
|
||||
data.wiggleProgress += 1.5;
|
||||
}
|
||||
|
||||
if (data.wiggleProgress >= 100) {
|
||||
forceDrop(data.killer);
|
||||
}
|
||||
}
|
||||
|
||||
public void forceDrop(Killer killer) {
|
||||
CarryData data = activeCarries.remove(killer.getUuid());
|
||||
if (data == null) return;
|
||||
|
||||
Player survivorPlayer = data.survivor.getPlayer();
|
||||
if (survivorPlayer != null) {
|
||||
Location dropLoc = survivorPlayer.getLocation();
|
||||
dropLoc.add(killer.getPlayer().getLocation().getDirection().multiply(1.5));
|
||||
survivorPlayer.teleport(dropLoc);
|
||||
}
|
||||
|
||||
stopCarry(data);
|
||||
}
|
||||
|
||||
public boolean isCarrying(Killer killer) {
|
||||
return activeCarries.containsKey(killer.getUuid());
|
||||
}
|
||||
|
||||
public Survivor getCarried(Killer killer) {
|
||||
CarryData data = activeCarries.get(killer.getUuid());
|
||||
return data != null ? data.survivor : null;
|
||||
}
|
||||
|
||||
public double getWiggleProgress(Killer killer) {
|
||||
CarryData data = activeCarries.get(killer.getUuid());
|
||||
return data != null ? data.wiggleProgress : 0;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (carryTask != null) {
|
||||
carryTask.cancel();
|
||||
}
|
||||
activeCarries.values().forEach(this::stopCarry);
|
||||
activeCarries.clear();
|
||||
}
|
||||
}
|
||||
126
src/main/java/dev/loki/killer/KillerController.java
Normal file
126
src/main/java/dev/loki/killer/KillerController.java
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
package dev.loki.killer;
|
||||
|
||||
import dev.loki.config.GameConfig;
|
||||
import dev.loki.damage.AttackListener;
|
||||
import dev.loki.damage.DamageHandler;
|
||||
import dev.loki.player.Killer;
|
||||
import dev.loki.player.PlayerManager;
|
||||
import dev.loki.player.Survivor;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class KillerController {
|
||||
private final Plugin plugin;
|
||||
private final PlayerManager playerManager;
|
||||
private final DamageHandler damageHandler;
|
||||
private final GameConfig config;
|
||||
|
||||
private final KillerAttack attack;
|
||||
private final KillerCarry carry;
|
||||
private final KillerMovement movement;
|
||||
private AttackListener attackListener;
|
||||
|
||||
public KillerController(Plugin plugin, PlayerManager playerManager,
|
||||
DamageHandler damageHandler, GameConfig config) {
|
||||
this.plugin = plugin;
|
||||
this.playerManager = playerManager;
|
||||
this.damageHandler = damageHandler;
|
||||
this.config = config;
|
||||
|
||||
this.attack = new KillerAttack(plugin, playerManager, damageHandler, config);
|
||||
this.carry = new KillerCarry(plugin, config);
|
||||
this.movement = new KillerMovement(plugin, config);
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
attackListener = new AttackListener(playerManager, damageHandler,
|
||||
(killer, survivor) -> tryAttack(killer, survivor));
|
||||
attackListener.register(plugin);
|
||||
|
||||
for (Killer killer : playerManager.getKillers()) {
|
||||
movement.startTracking(killer);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (attackListener != null) {
|
||||
attackListener.unregister();
|
||||
}
|
||||
attack.shutdown();
|
||||
carry.shutdown();
|
||||
movement.shutdown();
|
||||
}
|
||||
|
||||
public boolean tryAttack(Killer killer, Survivor target) {
|
||||
boolean success = attack.tryAttack(killer, target);
|
||||
if (success) {
|
||||
movement.applyAttackSlowdown(killer);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean tryPickup(Killer killer, Survivor target) {
|
||||
boolean success = carry.tryPickup(killer, target);
|
||||
if (success) {
|
||||
movement.updateSpeed(killer);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean tryDrop(Killer killer) {
|
||||
boolean success = carry.drop(killer);
|
||||
if (success) {
|
||||
movement.updateSpeed(killer);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public void onKillerJoin(Killer killer) {
|
||||
movement.startTracking(killer);
|
||||
}
|
||||
|
||||
public void onKillerLeave(Killer killer) {
|
||||
movement.stopTracking(killer);
|
||||
carry.drop(killer);
|
||||
}
|
||||
|
||||
public void registerKiller(Killer killer) {
|
||||
movement.startTracking(killer);
|
||||
}
|
||||
|
||||
public void unregisterKiller(Killer killer) {
|
||||
carry.drop(killer);
|
||||
movement.stopTracking(killer);
|
||||
}
|
||||
|
||||
public boolean isOnCooldown(Killer killer) {
|
||||
return attack.isOnCooldown(killer);
|
||||
}
|
||||
|
||||
public double getCooldownProgress(Killer killer) {
|
||||
return attack.getCooldownProgress(killer);
|
||||
}
|
||||
|
||||
public boolean isCarrying(Killer killer) {
|
||||
return carry.isCarrying(killer);
|
||||
}
|
||||
|
||||
public Survivor getCarried(Killer killer) {
|
||||
return carry.getCarried(killer);
|
||||
}
|
||||
|
||||
public double getWiggleProgress(Killer killer) {
|
||||
return carry.getWiggleProgress(killer);
|
||||
}
|
||||
|
||||
public KillerAttack getAttack() {
|
||||
return attack;
|
||||
}
|
||||
|
||||
public KillerCarry getCarry() {
|
||||
return carry;
|
||||
}
|
||||
|
||||
public KillerMovement getMovement() {
|
||||
return movement;
|
||||
}
|
||||
}
|
||||
119
src/main/java/dev/loki/killer/KillerMovement.java
Normal file
119
src/main/java/dev/loki/killer/KillerMovement.java
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package dev.loki.killer;
|
||||
|
||||
import dev.loki.config.GameConfig;
|
||||
import dev.loki.player.Killer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KillerMovement {
|
||||
private final Plugin plugin;
|
||||
private final GameConfig config;
|
||||
private final Map<UUID, BukkitTask> slowdownTasks;
|
||||
private BukkitTask updateTask;
|
||||
|
||||
private static final double BASE_SPEED = 0.1;
|
||||
|
||||
public KillerMovement(Plugin plugin, GameConfig config) {
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.slowdownTasks = new HashMap<>();
|
||||
}
|
||||
|
||||
public void startTracking(Killer killer) {
|
||||
if (updateTask == null) {
|
||||
startUpdateTask();
|
||||
}
|
||||
updateSpeed(killer);
|
||||
}
|
||||
|
||||
public void stopTracking(Killer killer) {
|
||||
BukkitTask task = slowdownTasks.remove(killer.getUuid());
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
Player player = killer.getPlayer();
|
||||
if (player != null) {
|
||||
resetSpeed(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void startUpdateTask() {
|
||||
updateTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
}, 20L, 20L);
|
||||
}
|
||||
|
||||
public void updateSpeed(Killer killer) {
|
||||
Player player = killer.getPlayer();
|
||||
if (player == null || !player.isOnline()) return;
|
||||
|
||||
double multiplier = killer.isCarrying() ?
|
||||
config.getKillerCarrySpeed() : config.getKillerSpeed();
|
||||
|
||||
applySpeed(player, multiplier);
|
||||
}
|
||||
|
||||
private void applySpeed(Player player, double multiplier) {
|
||||
AttributeInstance speedAttr = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
|
||||
if (speedAttr == null) return;
|
||||
|
||||
double newSpeed = BASE_SPEED * multiplier;
|
||||
speedAttr.setBaseValue(newSpeed);
|
||||
}
|
||||
|
||||
private void resetSpeed(Player player) {
|
||||
AttributeInstance speedAttr = player.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
|
||||
if (speedAttr == null) return;
|
||||
|
||||
speedAttr.setBaseValue(BASE_SPEED);
|
||||
}
|
||||
|
||||
public void applyTemporarySlowdown(Killer killer, double multiplier, int ticks) {
|
||||
Player player = killer.getPlayer();
|
||||
if (player == null) return;
|
||||
|
||||
cancelExistingSlowdown(killer);
|
||||
|
||||
BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
slowdownTasks.remove(killer.getUuid());
|
||||
updateSpeed(killer);
|
||||
}, ticks);
|
||||
|
||||
slowdownTasks.put(killer.getUuid(), task);
|
||||
applySpeed(player, multiplier);
|
||||
}
|
||||
|
||||
private void cancelExistingSlowdown(Killer killer) {
|
||||
BukkitTask task = slowdownTasks.remove(killer.getUuid());
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyAttackSlowdown(Killer killer) {
|
||||
applyTemporarySlowdown(killer, 0.85, 30);
|
||||
}
|
||||
|
||||
public double getSpeedMultiplier(Killer killer) {
|
||||
if (slowdownTasks.containsKey(killer.getUuid())) {
|
||||
return 0.85;
|
||||
}
|
||||
return killer.isCarrying() ? config.getKillerCarrySpeed() : config.getKillerSpeed();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
if (updateTask != null) {
|
||||
updateTask.cancel();
|
||||
}
|
||||
slowdownTasks.values().forEach(BukkitTask::cancel);
|
||||
slowdownTasks.clear();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue