package me.viper.survivalmechanics.mechanics; import me.viper.survivalmechanics.SurvivalMechanics; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerToggleSprintEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.ChatColor; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class StaminaManager implements Listener { private final JavaPlugin plugin; private final Map staminaLevels = new HashMap<>(); private final int maxStamina; private final double decreaseRate; private final double sprintMultiplier; private final double jumpMultiplier; private final double combatMultiplier; private final double climbingMultiplier; private final int climbingHeightThreshold; private final double climbingHeightScaling; private final double regenRate; private final double hungerThirstPenalty; private final double fatiguePenalty; private final double vulnerabilityStaminaPenalty; private final double staminaVulnerabilityIncrease; private final int criticalThreshold; private final int minToSprint; private final int messageCooldown; private final boolean criticalMessageOnly; public StaminaManager(JavaPlugin plugin) { this.plugin = plugin; this.maxStamina = plugin.getConfig().getInt("stamina.max", 100); this.decreaseRate = plugin.getConfig().getDouble("stamina.decrease-rate", 1); this.sprintMultiplier = plugin.getConfig().getDouble("stamina.sprint-multiplier", 3); this.jumpMultiplier = plugin.getConfig().getDouble("stamina.jump-multiplier", 2); this.combatMultiplier = plugin.getConfig().getDouble("stamina.combat-multiplier", 4); this.climbingMultiplier = plugin.getConfig().getDouble("stamina.climbing-multiplier", 2); this.climbingHeightThreshold = plugin.getConfig().getInt("stamina.climbing-height-threshold", 100); this.climbingHeightScaling = plugin.getConfig().getDouble("stamina.climbing-height-scaling", 0.01); this.regenRate = plugin.getConfig().getDouble("stamina.regen-rate", 2); this.hungerThirstPenalty = plugin.getConfig().getDouble("stamina.hunger-thirst-penalty", 0.5); this.fatiguePenalty = plugin.getConfig().getDouble("stamina.fatigue-penalty", 0.5); this.vulnerabilityStaminaPenalty = plugin.getConfig().getDouble("stamina.vulnerability-stamina-penalty", 0.7); this.staminaVulnerabilityIncrease = plugin.getConfig().getDouble("stamina.stamina-vulnerability-increase", 2); this.criticalThreshold = plugin.getConfig().getInt("stamina.critical-threshold", 20); this.minToSprint = plugin.getConfig().getInt("stamina.min-to-sprint", 20); this.messageCooldown = plugin.getConfig().getInt("stamina.message-cooldown", 60); this.criticalMessageOnly = plugin.getConfig().getBoolean("stamina.critical-message-only", true); plugin.getServer().getPluginManager().registerEvents(this, plugin); } public void startStaminaTask() { new BukkitRunnable() { @Override public void run() { for (Player player : plugin.getServer().getOnlinePlayers()) { UUID playerId = player.getUniqueId(); int stamina = staminaLevels.getOrDefault(playerId, maxStamina); int hunger = ((SurvivalMechanics) plugin).getHungerManager().getHunger(playerId); int thirst = ((SurvivalMechanics) plugin).getThirstManager().getThirst(playerId); int fatigue = ((SurvivalMechanics) plugin).getFatigueManager().getFatigue(playerId); double regen = regenRate; // Low hunger or thirst reduces stamina regeneration if (hunger < criticalThreshold || thirst < criticalThreshold) { regen *= hungerThirstPenalty; } // Low fatigue reduces stamina regeneration if (fatigue < criticalThreshold) { regen *= fatiguePenalty; } stamina = Math.min(maxStamina, stamina + (int) regen); staminaLevels.put(playerId, stamina); // Warning when stamina is too low to sprint if (stamina <= criticalThreshold && canSendMessage(playerId)) { player.sendMessage(ChatColor.translateAlternateColorCodes('&', ((SurvivalMechanics) plugin).getLangConfig().getString("stamina.critical-sprint", "§4Du bist zu schwach, um zu sprinten!"))); player.getWorld().playSound(player.getLocation(), "entity.player.hurt", 1.0f, 1.0f); setLastMessageTime(playerId); } } } }.runTaskTimer(plugin, 0L, 20L * 60); // Every 60 seconds } @EventHandler public void onPlayerToggleSprint(PlayerToggleSprintEvent event) { Player player = event.getPlayer(); UUID playerId = player.getUniqueId(); int stamina = staminaLevels.getOrDefault(playerId, maxStamina); if (event.isSprinting()) { // Prevent sprinting if stamina is too low if (stamina < minToSprint) { event.setCancelled(true); if (canSendMessage(playerId)) { player.sendMessage(ChatColor.translateAlternateColorCodes('&', ((SurvivalMechanics) plugin).getLangConfig().getString("stamina.critical-sprint", "§4Du bist zu schwach, um zu sprinten!"))); player.getWorld().playSound(player.getLocation(), "entity.player.hurt", 1.0f, 1.0f); setLastMessageTime(playerId); } } else { // Drain stamina when sprinting stamina = Math.max(0, stamina - (int) (decreaseRate * sprintMultiplier)); staminaLevels.put(playerId, stamina); applyVulnerabilityIncrease(playerId); } } } @EventHandler public void onPlayerMove(PlayerMoveEvent event) { Player player = event.getPlayer(); UUID playerId = player.getUniqueId(); int stamina = staminaLevels.getOrDefault(playerId, maxStamina); // Jumping drains stamina if (player.getVelocity().getY() > 0 && !player.isOnGround()) { stamina = Math.max(0, stamina - (int) (decreaseRate * jumpMultiplier)); staminaLevels.put(playerId, stamina); if (stamina <= criticalThreshold && canSendMessage(playerId)) { player.sendMessage(ChatColor.translateAlternateColorCodes('&', ((SurvivalMechanics) plugin).getLangConfig().getString("stamina.critical-jump", "§4Du bist zu schwach, um zu springen!"))); player.getWorld().playSound(player.getLocation(), "entity.player.hurt", 1.0f, 1.0f); setLastMessageTime(playerId); } applyVulnerabilityIncrease(playerId); } // Climbing at high altitudes drains stamina faster else if (player.isClimbing() && player.getLocation().getY() > climbingHeightThreshold) { double heightFactor = 1 + ((player.getLocation().getY() - climbingHeightThreshold) * climbingHeightScaling); stamina = Math.max(0, stamina - (int) (decreaseRate * climbingMultiplier * heightFactor)); staminaLevels.put(playerId, stamina); if (stamina <= criticalThreshold && canSendMessage(playerId)) { player.sendMessage(ChatColor.translateAlternateColorCodes('&', ((SurvivalMechanics) plugin).getLangConfig().getString("climbing.critical", "§4Das Klettern zehrt an deinen Kräften!"))); player.getWorld().playSound(player.getLocation(), "entity.player.hurt", 1.0f, 1.0f); setLastMessageTime(playerId); } applyVulnerabilityIncrease(playerId); } } @EventHandler public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { // When player attacks (is the damager) if (event.getDamager() instanceof Player) { Player player = (Player) event.getDamager(); UUID playerId = player.getUniqueId(); int stamina = staminaLevels.getOrDefault(playerId, maxStamina); // Combat drains stamina stamina = Math.max(0, stamina - (int) (decreaseRate * combatMultiplier)); staminaLevels.put(playerId, stamina); if (stamina <= criticalThreshold && canSendMessage(playerId)) { player.sendMessage(ChatColor.translateAlternateColorCodes('&', ((SurvivalMechanics) plugin).getLangConfig().getString("stamina.critical-combat", "§4Du bist zu schwach, um zu kämpfen!"))); player.getWorld().playSound(player.getLocation(), "entity.player.hurt", 1.0f, 1.0f); setLastMessageTime(playerId); } applyVulnerabilityIncrease(playerId); } } public void applyFatiguePenalty(UUID playerId, double penalty) { int stamina = staminaLevels.getOrDefault(playerId, maxStamina); stamina = Math.max(0, stamina - (int) (decreaseRate * penalty)); staminaLevels.put(playerId, stamina); } private void applyVulnerabilityIncrease(UUID playerId) { int stamina = staminaLevels.getOrDefault(playerId, maxStamina); if (stamina <= criticalThreshold) { ((SurvivalMechanics) plugin).getVulnerabilityManager().increaseVulnerability(playerId, (int) staminaVulnerabilityIncrease); } } private boolean canSendMessage(UUID playerId) { return ((SurvivalMechanics) plugin).canSendMessage(playerId, "stamina"); } private void setLastMessageTime(UUID playerId) { ((SurvivalMechanics) plugin).setLastMessageTime(playerId, "stamina"); } public int getStamina(UUID playerId) { return staminaLevels.getOrDefault(playerId, maxStamina); } public void loadStamina(UUID playerId, int stamina) { staminaLevels.put(playerId, stamina); } }