diff --git a/build.gradle b/build.gradle index 26d2e9a..77b2d29 100755 --- a/build.gradle +++ b/build.gradle @@ -21,11 +21,15 @@ repositories { name = "sk89q-repo" url = "https://maven.enginehub.org/repo/" } + maven { + url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' + } } dependencies { compileOnly("io.papermc.paper:paper-api:1.21.5-R0.1-SNAPSHOT") compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.14-SNAPSHOT' + compileOnly 'me.clip:placeholderapi:2.11.6' } tasks { diff --git a/src/main/java/me/trouper/trimserver/TrimServer.java b/src/main/java/me/trouper/trimserver/TrimServer.java index b4accbd..4d09f9e 100755 --- a/src/main/java/me/trouper/trimserver/TrimServer.java +++ b/src/main/java/me/trouper/trimserver/TrimServer.java @@ -29,10 +29,10 @@ public final class TrimServer extends JavaPlugin { @Override public void onDisable() { - BlockDisplayRaytracer.cleanup(); + getLogger().info("Cleaning up..."); + manager.cleanup(); getLogger().info("Saved all IO files."); manager.io.saveAll(); - getLogger().info("Saved all IO files."); } public static TrimServer getInstance() { diff --git a/src/main/java/me/trouper/trimserver/server/Main.java b/src/main/java/me/trouper/trimserver/server/Main.java index 1529f09..22513d6 100755 --- a/src/main/java/me/trouper/trimserver/server/Main.java +++ b/src/main/java/me/trouper/trimserver/server/Main.java @@ -5,15 +5,15 @@ import me.trouper.trimserver.TrimServer; import me.trouper.trimserver.data.IO; import me.trouper.trimserver.data.io.Config; import me.trouper.trimserver.data.io.Storage; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.CustomBossBar; +import me.trouper.trimserver.utils.text.Text; import org.bukkit.command.CommandSender; import java.util.Random; import java.util.function.BooleanSupplier; public interface Main { - Main main = new Main() { - }; + Main main = new Main() {}; Random random = new Random(); @@ -53,6 +53,10 @@ public interface Main { Text.sendMessage(Text.Pallet.WARNING, player, message, args); } + default void success(CommandSender player, String message, Object... args) { + Text.sendMessage(Text.Pallet.SUCCESS, player, message, args); + } + default void checkPre(boolean check, String msg, Object... args) { if (!check) { throw new IllegalArgumentException(msg.formatted(args)); diff --git a/src/main/java/me/trouper/trimserver/server/Manager.java b/src/main/java/me/trouper/trimserver/server/Manager.java index 536556d..9b0b2ba 100755 --- a/src/main/java/me/trouper/trimserver/server/Manager.java +++ b/src/main/java/me/trouper/trimserver/server/Manager.java @@ -1,43 +1,56 @@ package me.trouper.trimserver.server; +import me.trouper.trimserver.TrimServer; import me.trouper.trimserver.data.IO; +import me.trouper.trimserver.server.api.TrimPlaceholders; import me.trouper.trimserver.server.commands.AdminCommand; import me.trouper.trimserver.server.commands.InfoCommand; import me.trouper.trimserver.server.commands.TrustCommand; -import me.trouper.trimserver.server.events.JoinEvent; -import me.trouper.trimserver.server.events.SwapHandsEvent; -import me.trouper.trimserver.server.events.TrustEvents; -import me.trouper.trimserver.server.flags.AbilityFlag; +import me.trouper.trimserver.server.events.*; +import me.trouper.trimserver.server.api.AbilityFlag; +import me.trouper.trimserver.server.systems.PollingBackend; import me.trouper.trimserver.server.systems.TrustBackend; import me.trouper.trimserver.server.systems.AbilityBackend; import me.trouper.trimserver.server.systems.abilities.trims.*; +import me.trouper.trimserver.utils.text.CustomBossBar; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; +import org.bukkit.Bukkit; public class Manager { public IO io; public AbilityBackend abilityBackend; public TrustBackend trustBackend; + public PollingBackend pollingBackend; public AbilityFlag abilityFlag; - + public Manager() { io = new IO(); abilityBackend = new AbilityBackend(); trustBackend = new TrustBackend(); + pollingBackend = new PollingBackend(); abilityFlag = new AbilityFlag(); } public void init() { io.loadAll(); + cleanup(); registerAbilities(); registerEvents(); registerCommands(); - - BlockDisplayRaytracer.cleanup(); + registerPlaceholders(); - abilityBackend.startTickingBars(); abilityFlag.register(); + pollingBackend.startPolling(); + } + + private void registerPlaceholders() { + if (!Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) { + TrimServer.getInstance().getLogger().info("Could not register PAPI Expansion!"); + return; + } + new TrimPlaceholders(TrimServer.getInstance()).register(); } private void registerCommands() { @@ -47,9 +60,11 @@ public class Manager { } private void registerEvents() { - new SwapHandsEvent().registerEvents(); + new AbilityUseEvent().registerEvents(); new JoinEvent().registerEvents(); new TrustEvents().registerEvents(); + new ItemUseEvent().registerEvents(); + new CraftEvents().registerEvents(); } private void registerAbilities() { @@ -72,4 +87,9 @@ public class Manager { abilityBackend.registerAbility(new WayfinderAbility()).registerEvents(); abilityBackend.registerAbility(new WildAbility()).registerEvents(); } + + public void cleanup() { + BlockDisplayRaytracer.cleanup(); + CustomBossBar.removeAllBossBars(); + } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/server/flags/AbilityFlag.java b/src/main/java/me/trouper/trimserver/server/api/AbilityFlag.java similarity index 87% rename from src/main/java/me/trouper/trimserver/server/flags/AbilityFlag.java rename to src/main/java/me/trouper/trimserver/server/api/AbilityFlag.java index 547830f..fb39f3c 100644 --- a/src/main/java/me/trouper/trimserver/server/flags/AbilityFlag.java +++ b/src/main/java/me/trouper/trimserver/server/api/AbilityFlag.java @@ -1,12 +1,10 @@ -package me.trouper.trimserver.server.flags; +package me.trouper.trimserver.server.api; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.flags.*; import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; -import com.sk89q.worldguard.session.handler.FlagValueChangeHandler; import me.trouper.trimserver.TrimServer; -import org.jetbrains.annotations.Nullable; public class AbilityFlag { diff --git a/src/main/java/me/trouper/trimserver/server/api/TrimPlaceholders.java b/src/main/java/me/trouper/trimserver/server/api/TrimPlaceholders.java new file mode 100644 index 0000000..a1f373d --- /dev/null +++ b/src/main/java/me/trouper/trimserver/server/api/TrimPlaceholders.java @@ -0,0 +1,65 @@ +package me.trouper.trimserver.server.api; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.trouper.trimserver.TrimServer; +import me.trouper.trimserver.server.systems.AbilityBackend; +import me.trouper.trimserver.server.systems.abilities.AbstractAbility; +import me.trouper.trimserver.utils.text.Text; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.inventory.meta.trim.TrimMaterial; + +public class TrimPlaceholders extends PlaceholderExpansion { + + public TrimPlaceholders(TrimServer instance) { + + } + + @Override + public String getAuthor() { + return "obvWolf"; + } + + @Override + public String getIdentifier() { + return "trims"; + } + + @Override + public String getVersion() { + return "1.0.0"; + } + + @Override + public boolean persist() { + return true; // This is required or else PlaceholderAPI will unregister the Expansion on reload + } + + @Override + public String onRequest(OfflinePlayer player, String params) { + if (params.equalsIgnoreCase("active_pattern")){ + if (Bukkit.getPlayer(player.getUniqueId()) == null) return "Offline Player!"; + AbstractAbility ability = TrimServer.getInstance().getManager().abilityBackend.getAbility(player.getPlayer()); + if (ability == null) return "none"; + return ability.getPatternName(); + } + + if (params.equalsIgnoreCase("active_material")) { + if (Bukkit.getPlayer(player.getUniqueId()) == null) return "Offline Player!"; + TrimMaterial material = TrimServer.getInstance().getManager().abilityBackend.getMaterial(player.getPlayer()); + if (material == null) return "none"; + return Text.formatEnum(AbilityBackend.ValidMaterial.validate(material)); + } + + if (params.equalsIgnoreCase("active_cooldown")) { + if (Bukkit.getPlayer(player.getUniqueId()) == null) return "Offline Player!"; + TrimMaterial material = TrimServer.getInstance().getManager().abilityBackend.getMaterial(player.getPlayer()); + AbstractAbility ability = TrimServer.getInstance().getManager().abilityBackend.getAbility(player.getPlayer()); + double sec = TrimServer.getInstance().getManager().abilityBackend.getCooldowns().getCooldownSec(new AbilityBackend.AbilityCooldown(player.getUniqueId(),ability.getPattern(),material)); + if (sec <= 0) return "ready"; + return sec + "s"; + } + + return null; + } +} diff --git a/src/main/java/me/trouper/trimserver/server/commands/AdminCommand.java b/src/main/java/me/trouper/trimserver/server/commands/AdminCommand.java index e6de3fd..8ffd712 100755 --- a/src/main/java/me/trouper/trimserver/server/commands/AdminCommand.java +++ b/src/main/java/me/trouper/trimserver/server/commands/AdminCommand.java @@ -1,10 +1,9 @@ package me.trouper.trimserver.server.commands; -import io.papermc.paper.registry.keys.TrimPatternKeys; import me.trouper.trimserver.server.systems.AbilityBackend; import me.trouper.trimserver.utils.SoundPlayer; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.commands.Args; import me.trouper.trimserver.utils.commands.CommandRegistry; import me.trouper.trimserver.utils.commands.Permission; @@ -18,7 +17,6 @@ import org.bukkit.*; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Display; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -29,8 +27,6 @@ import org.bukkit.inventory.meta.trim.TrimMaterial; import org.bukkit.inventory.meta.trim.TrimPattern; import java.util.List; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicInteger; @CommandRegistry(value = "trims",permission = @Permission("trims.admin"),printStackTrace = true) public class AdminCommand implements QuickCommand { @@ -45,6 +41,7 @@ public class AdminCommand implements QuickCommand { case "reload" -> handleReload(commandSender,args); case "try" -> handleTry(commandSender,args); case "test" -> handleTest(commandSender,args); + case "give" -> handleGive(commandSender,args); } } @@ -93,9 +90,38 @@ public class AdminCommand implements QuickCommand { ) ) ) + ).then( + b.arg("give") + .then(b.arg("consumable") + .then( + b.argEnum(AbilityBackend.ValidPattern.class) + .then( + b.argEnum(AbilityBackend.ValidMaterial.class) + ) + ) + ) + ); } + private void handleGive(CommandSender commandSender, Args args) { + switch (args.get(1).toString()) { + case "consumable" -> { + if (!(commandSender instanceof Player p)) { + error(commandSender,"This sub-command is player only."); + return; + } + AbilityBackend.ValidPattern pattern = args.get(2).toEnum(AbilityBackend.ValidPattern.class); + AbilityBackend.ValidMaterial material = args.get(3).toEnum(AbilityBackend.ValidMaterial.class); + + p.getInventory().addItem(main.man().abilityBackend.createConsumableAbility(pattern,material)); + success(commandSender,"Given you a consumable {0} material {1} consumable trim.",Text.formatEnum(material),Text.formatEnum(pattern)); + } + } + } + + + private void handleTest(CommandSender commandSender, Args args) { switch (args.get(1).toString()) { case "vector" -> { diff --git a/src/main/java/me/trouper/trimserver/server/commands/InfoCommand.java b/src/main/java/me/trouper/trimserver/server/commands/InfoCommand.java index 8ab412a..b689884 100755 --- a/src/main/java/me/trouper/trimserver/server/commands/InfoCommand.java +++ b/src/main/java/me/trouper/trimserver/server/commands/InfoCommand.java @@ -2,7 +2,7 @@ package me.trouper.trimserver.server.commands; import me.trouper.trimserver.TrimServer; import me.trouper.trimserver.server.systems.AbilityBackend; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.commands.Args; import me.trouper.trimserver.utils.commands.CommandRegistry; import me.trouper.trimserver.utils.commands.QuickCommand; @@ -10,7 +10,7 @@ import me.trouper.trimserver.utils.commands.completions.CompletionBuilder; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -@CommandRegistry(value = "info") +@CommandRegistry(value = "triminfo") public class InfoCommand implements QuickCommand { @Override public void dispatchCommand(CommandSender commandSender, Command command, String s, Args args) { diff --git a/src/main/java/me/trouper/trimserver/server/commands/TrustCommand.java b/src/main/java/me/trouper/trimserver/server/commands/TrustCommand.java index 5d78aa4..7b18d50 100755 --- a/src/main/java/me/trouper/trimserver/server/commands/TrustCommand.java +++ b/src/main/java/me/trouper/trimserver/server/commands/TrustCommand.java @@ -1,7 +1,7 @@ package me.trouper.trimserver.server.commands; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.commands.Args; import me.trouper.trimserver.utils.commands.CommandRegistry; import me.trouper.trimserver.utils.commands.QuickCommand; diff --git a/src/main/java/me/trouper/trimserver/server/events/SwapHandsEvent.java b/src/main/java/me/trouper/trimserver/server/events/AbilityUseEvent.java similarity index 87% rename from src/main/java/me/trouper/trimserver/server/events/SwapHandsEvent.java rename to src/main/java/me/trouper/trimserver/server/events/AbilityUseEvent.java index 60b0729..82a8784 100755 --- a/src/main/java/me/trouper/trimserver/server/events/SwapHandsEvent.java +++ b/src/main/java/me/trouper/trimserver/server/events/AbilityUseEvent.java @@ -5,7 +5,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerSwapHandItemsEvent; -public class SwapHandsEvent implements QuickListener, Main { +public class AbilityUseEvent implements QuickListener, Main { @EventHandler public void onSwap(PlayerSwapHandItemsEvent e) { diff --git a/src/main/java/me/trouper/trimserver/server/events/CraftEvents.java b/src/main/java/me/trouper/trimserver/server/events/CraftEvents.java new file mode 100644 index 0000000..37a5604 --- /dev/null +++ b/src/main/java/me/trouper/trimserver/server/events/CraftEvents.java @@ -0,0 +1,24 @@ +package me.trouper.trimserver.server.events; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.CrafterCraftEvent; +import org.bukkit.event.inventory.CraftItemEvent; +import org.bukkit.event.inventory.PrepareSmithingEvent; +import org.bukkit.inventory.ItemCraftResult; + +public class CraftEvents implements QuickListener { + @EventHandler + public void onCraft(CraftItemEvent e) { + + } + + @EventHandler + public void onCraft(CrafterCraftEvent e) { + + } + + @EventHandler + public void onCraft(PrepareSmithingEvent e) { + + } +} diff --git a/src/main/java/me/trouper/trimserver/server/events/ItemUseEvent.java b/src/main/java/me/trouper/trimserver/server/events/ItemUseEvent.java new file mode 100644 index 0000000..760567a --- /dev/null +++ b/src/main/java/me/trouper/trimserver/server/events/ItemUseEvent.java @@ -0,0 +1,42 @@ +package me.trouper.trimserver.server.events; + +import me.trouper.trimserver.server.systems.AbilityBackend; +import me.trouper.trimserver.server.systems.abilities.AbstractAbility; +import me.trouper.trimserver.server.systems.abilities.MaterialInfo; +import me.trouper.trimserver.utils.text.Text; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class ItemUseEvent implements QuickListener { + + @EventHandler + public void onClick(PlayerInteractEvent e) { + if (!e.getAction().equals(Action.RIGHT_CLICK_AIR) && !e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return; + ItemStack i = e.getItem(); + Player p = e.getPlayer(); + if (i == null) return; + AbilityBackend.ValidPattern pattern = main.man().abilityBackend.getConsumablePattern(i); + AbilityBackend.ValidMaterial material = main.man().abilityBackend.getConsumableMaterial(i); + if (pattern == null || material == null) return; + + AbilityBackend.AbilityCooldown cooldownKey = new AbilityBackend.AbilityCooldown(p.getUniqueId(),pattern.getCanonical(),material.getCanonical()); + if (main.man().abilityBackend.getCooldowns().isOnCooldown(cooldownKey)) { + error(p,"This ability is on cooldown for {0} seconds!",main.man().abilityBackend.getCooldowns().getCooldownSec(cooldownKey)); + p.setCooldown(i, (int) (20*main.man().abilityBackend.getCooldowns().getCooldownSec(cooldownKey))); + return; + } + + AbstractAbility ability = main.man().abilityBackend.getAbility(pattern.getCanonical()); + MaterialInfo info = ability.getAbilityInfo(material.getCanonical()); + + ability.dispatchAbility(material,p); + main.man().abilityBackend.getCooldowns().setCooldown(cooldownKey,info.cooldownTicks() * 50L); + p.setCooldown(i, info.cooldownTicks()); + i.setAmount(i.getAmount() - 1); + + success(p,"You have used the {0} ability for the {1} trim!", Text.formatEnum(material),Text.formatEnum(pattern)); + } +} diff --git a/src/main/java/me/trouper/trimserver/server/systems/AbilityBackend.java b/src/main/java/me/trouper/trimserver/server/systems/AbilityBackend.java index a2be1ab..6119245 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/AbilityBackend.java +++ b/src/main/java/me/trouper/trimserver/server/systems/AbilityBackend.java @@ -4,30 +4,34 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; -import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.regions.RegionContainer; import com.sk89q.worldguard.protection.regions.RegionQuery; import io.papermc.paper.registry.RegistryAccess; import io.papermc.paper.registry.RegistryKey; -import io.papermc.paper.registry.keys.TrimPatternKeys; import me.trouper.trimserver.server.Main; -import me.trouper.trimserver.server.flags.AbilityFlag; +import me.trouper.trimserver.server.api.AbilityFlag; import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.misc.Cooldown; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; +import net.kyori.adventure.text.format.TextDecoration; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.ArmorMeta; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.trim.ArmorTrim; import org.bukkit.inventory.meta.trim.TrimMaterial; import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; import java.util.*; import java.util.logging.Level; @@ -35,10 +39,119 @@ import java.util.logging.Level; public class AbilityBackend implements Main { public final Map registeredAbilities = new HashMap<>(); - private record AbilityCooldown(UUID who, TrimPattern pattern, TrimMaterial material) {}; + public Cooldown getCooldowns() { + return onCooldown; + } + + public record AbilityCooldown(UUID who, TrimPattern pattern, TrimMaterial material) {}; private final Cooldown onCooldown = new Cooldown<>(); + /** + * Creates a consumable ability token item with specified trim material and pattern. + * This item can be used to grant a single-use ability. + * + * @param material The ValidMaterial for the ability token. + * @param pattern The ValidPattern for the ability token. + * @return An ItemStack representing the consumable ability token, or null if material/pattern is invalid. + */ + public ItemStack createConsumableAbility(ValidPattern pattern, ValidMaterial material) { + if (material == null || pattern == null) { + main.getPlugin().getLogger().warning("Attempted to create a consumable token with null material or pattern."); + return null; + } + + ItemStack token = new ItemStack(pattern.getMaterial(), 1); + ItemMeta meta = token.getItemMeta(); + + if (meta == null) { + main.getPlugin().getLogger().severe("Failed to get ItemMeta for ability token."); + return null; + } + + NamespacedKey materialKey = new NamespacedKey(main.getPlugin(), "consumable_trim_material"); + NamespacedKey patternKey = new NamespacedKey(main.getPlugin(), "consumable_trim_pattern"); + + PersistentDataContainer pdc = meta.getPersistentDataContainer(); + pdc.set(materialKey, PersistentDataType.STRING, material.name()); + pdc.set(patternKey, PersistentDataType.STRING, pattern.name()); + + meta.displayName( + Text.color("&7Ability Token &8-&2&l " + Text.formatEnum(material)).decoration(TextDecoration.ITALIC,false) + ); + + List lore = new ArrayList<>(List.of( + Text.color("&8&l| &7A &csingle-use &7ability token.").decoration(TextDecoration.ITALIC, false), + Text.color("&8&l| &7Pattern: &4" + Text.formatEnum(pattern)).decoration(TextDecoration.ITALIC, false), + Text.color("&8&l| &7Material: &4" + Text.formatEnum(material)).decoration(TextDecoration.ITALIC, false), + Text.color("&8&l|").decoration(TextDecoration.ITALIC,false), + Text.color("&8&l| &cConsumable").decoration(TextDecoration.ITALIC, false) + )); + meta.addEnchant(Enchantment.MENDING,1,true); + meta.addItemFlags(ItemFlag.HIDE_ARMOR_TRIM,ItemFlag.HIDE_ATTRIBUTES,ItemFlag.HIDE_ENCHANTS); + + meta.lore(lore); + + token.setItemMeta(meta); + return token; + } + + /** + * Retrieves the ValidMaterial stored in a consumable ability token's persistent data. + * + * @param itemStack The ItemStack to check. + * @return The ValidMaterial if found, otherwise null. + */ + public ValidMaterial getConsumableMaterial(ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR || !itemStack.hasItemMeta()) { + return null; + } + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) return null; + + NamespacedKey materialKey = new NamespacedKey(main.getPlugin(), "consumable_trim_material"); + PersistentDataContainer pdc = meta.getPersistentDataContainer(); + + if (pdc.has(materialKey, PersistentDataType.STRING)) { + String materialName = pdc.get(materialKey, PersistentDataType.STRING); + try { + return ValidMaterial.valueOf(materialName.toUpperCase()); + } catch (IllegalArgumentException e) { + main.getPlugin().getLogger().warning("Invalid material string found on consumable: " + materialName); + return null; + } + } + return null; + } + + /** + * Retrieves the ValidPattern stored in a consumable ability token's persistent data. + * + * @param itemStack The ItemStack to check. + * @return The ValidPattern if found, otherwise null. + */ + public ValidPattern getConsumablePattern(ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR || !itemStack.hasItemMeta()) { + return null; + } + ItemMeta meta = itemStack.getItemMeta(); + if (meta == null) return null; + + NamespacedKey patternKey = new NamespacedKey(main.getPlugin(), "consumable_trim_pattern"); + PersistentDataContainer pdc = meta.getPersistentDataContainer(); + + if (pdc.has(patternKey, PersistentDataType.STRING)) { + String patternName = pdc.get(patternKey, PersistentDataType.STRING); + try { + return ValidPattern.valueOf(patternName.toUpperCase()); + } catch (IllegalArgumentException e) { + main.getPlugin().getLogger().warning("Invalid pattern string found on consumable: " + patternName); + return null; + } + } + return null; + } + /** * Get a list of registered ability pattern names as strings. * @return a list containing the string keys of the registered trim patterns. @@ -91,7 +204,11 @@ public class AbilityBackend implements Main { } public TrimMaterial getMaterial(Player player) { - return getArmorInfo(player).getValidMaterial().getCanonical(); + ArmorInfo info = getArmorInfo(player); + if (info == null) return null; + ValidMaterial material = getArmorInfo(player).getValidMaterial(); + if (material == null) return null; + return material.getCanonical(); } /** @@ -172,7 +289,7 @@ public class AbilityBackend implements Main { try { - boolean applyCooldown = abilityAllowed(player, player.getLocation()) && ability.dispatchAbility(info.getValidMaterial().getCanonical(), player); + boolean applyCooldown = abilityAllowed(player, player.getLocation()) && ability.dispatchAbility(info.getValidMaterial(), player); if (cooldownTicks > 0 && applyCooldown) onCooldown.addCooldown(cooldownKey, (long) cooldownTicks * 50L); @@ -183,52 +300,6 @@ public class AbilityBackend implements Main { } } - /** - * Begins ticking player's action bars. - */ - public void startTickingBars() { - Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task)->{ - for (Player player : Bukkit.getServer().getOnlinePlayers()) { - tickActionBar(player); - } - },0,20); - } - - /** - * Plays the cooldown and info action bar for a player. - * @param player the player to send actionbar to. - */ - public void tickActionBar(Player player) { - AbstractAbility ability = getAbility(player); - TrimMaterial material = getMaterial(player); - if (ability == null || material == null) return; - TrimPattern pattern = ability.getPattern(); - MaterialInfo materialInfo = ability.getAbilityInfo(material); - - AbilityCooldown cooldownKey = new AbilityCooldown(player.getUniqueId(), pattern, material); - int cooldownTicks = (materialInfo != null) ? materialInfo.cooldownTicks() : 0; - - Component bar = Component.text(""); - - if (onCooldown.isOnCooldown(cooldownKey)) { - long remainingMillis = onCooldown.getCooldown(cooldownKey); - long totalDurationMillis = (long) cooldownTicks * 50L; - long elapsedMillis = totalDurationMillis - remainingMillis; - - elapsedMillis = Math.max(0, elapsedMillis); - elapsedMillis = Math.min(totalDurationMillis, elapsedMillis); - - bar = bar.append(Component.text("Ability Recharging: ", NamedTextColor.WHITE)) - .append(Text.color(Text.generateProgressBar(20, (int)totalDurationMillis, (int)elapsedMillis))); - } else { - bar = bar.append(Component.text("Ability Ready", NamedTextColor.namedColor(0x00FFAA))); - } - - bar = bar.append(Text.formatArgs(Text.Pallet.INFO," /info {0} for usage",Text.formatEnum(ValidPattern.validate(pattern)))); - - player.sendActionBar(bar); - } - /** * Gets the formatted Component information message for a specific trim pattern's ability. * Includes overall pattern info and grouped material variant details. @@ -326,29 +397,35 @@ public class AbilityBackend implements Main { } public enum ValidPattern { - BOLT(TrimPattern.BOLT), - COAST(TrimPattern.COAST), - DUNE(TrimPattern.DUNE), - EYE(TrimPattern.EYE), - FLOW(TrimPattern.FLOW), - HOST(TrimPattern.HOST), - RAISER(TrimPattern.RAISER), - RIB(TrimPattern.RIB), - SENTRY(TrimPattern.SENTRY), - SHAPER(TrimPattern.SHAPER), - SILENCE(TrimPattern.SILENCE), - SNOUT(TrimPattern.SNOUT), - SPIRE(TrimPattern.SPIRE), - TIDE(TrimPattern.TIDE), - VEX(TrimPattern.VEX), - WARD(TrimPattern.WARD), - WAYFINDER(TrimPattern.WAYFINDER), - WILD(TrimPattern.WILD); + BOLT(TrimPattern.BOLT, Material.BOLT_ARMOR_TRIM_SMITHING_TEMPLATE), + COAST(TrimPattern.COAST, Material.COAST_ARMOR_TRIM_SMITHING_TEMPLATE), + DUNE(TrimPattern.DUNE, Material.DUNE_ARMOR_TRIM_SMITHING_TEMPLATE), + EYE(TrimPattern.EYE, Material.EYE_ARMOR_TRIM_SMITHING_TEMPLATE), + FLOW(TrimPattern.FLOW, Material.FLOW_ARMOR_TRIM_SMITHING_TEMPLATE), + HOST(TrimPattern.HOST, Material.HOST_ARMOR_TRIM_SMITHING_TEMPLATE), + RAISER(TrimPattern.RAISER, Material.RAISER_ARMOR_TRIM_SMITHING_TEMPLATE), + RIB(TrimPattern.RIB, Material.RIB_ARMOR_TRIM_SMITHING_TEMPLATE), + SENTRY(TrimPattern.SENTRY, Material.SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE), + SHAPER(TrimPattern.SHAPER, Material.SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE), + SILENCE(TrimPattern.SILENCE, Material.SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE), + SNOUT(TrimPattern.SNOUT, Material.SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE), + SPIRE(TrimPattern.SPIRE, Material.SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE), + TIDE(TrimPattern.TIDE, Material.TIDE_ARMOR_TRIM_SMITHING_TEMPLATE), + VEX(TrimPattern.VEX, Material.VEX_ARMOR_TRIM_SMITHING_TEMPLATE), + WARD(TrimPattern.WARD, Material.WARD_ARMOR_TRIM_SMITHING_TEMPLATE), + WAYFINDER(TrimPattern.WAYFINDER, Material.WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE), + WILD(TrimPattern.WILD, Material.WILD_ARMOR_TRIM_SMITHING_TEMPLATE); private final TrimPattern canonical; + private final Material material; - ValidPattern(TrimPattern canonical) { + ValidPattern(TrimPattern canonical, Material material) { this.canonical = canonical; + this.material = material; + } + + public Material getMaterial() { + return material; } public TrimPattern getCanonical() { diff --git a/src/main/java/me/trouper/trimserver/server/systems/PollingBackend.java b/src/main/java/me/trouper/trimserver/server/systems/PollingBackend.java new file mode 100644 index 0000000..ec9c2be --- /dev/null +++ b/src/main/java/me/trouper/trimserver/server/systems/PollingBackend.java @@ -0,0 +1,65 @@ +package me.trouper.trimserver.server.systems; + +import me.trouper.trimserver.server.Main; +import me.trouper.trimserver.server.systems.abilities.AbstractAbility; +import me.trouper.trimserver.server.systems.abilities.MaterialInfo; +import me.trouper.trimserver.utils.text.Text; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; + +public class PollingBackend implements Main { + /** + * Begins per-player polling + */ + public void startPolling() { + Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task)->{ + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + tickActionBar(player); + tickPlaceholders(player); + } + },0,20); + } + + public void tickPlaceholders(Player player) { + + } + + /** + * Plays the cooldown and info action bar for a player. + * @param player the player to send actionbar to. + */ + public void tickActionBar(Player player) { + AbstractAbility ability = main.man().abilityBackend.getAbility(player); + TrimMaterial material = main.man().abilityBackend.getMaterial(player); + if (ability == null || material == null) return; + TrimPattern pattern = ability.getPattern(); + MaterialInfo materialInfo = ability.getAbilityInfo(material); + + AbilityBackend.AbilityCooldown cooldownKey = new AbilityBackend.AbilityCooldown(player.getUniqueId(), pattern, material); + int cooldownTicks = (materialInfo != null) ? materialInfo.cooldownTicks() : 0; + + Component bar = Component.text(""); + + if (main.man().abilityBackend.getCooldowns().isOnCooldown(cooldownKey)) { + long remainingMillis = main.man().abilityBackend.getCooldowns().getCooldown(cooldownKey); + long totalDurationMillis = (long) cooldownTicks * 50L; + long elapsedMillis = totalDurationMillis - remainingMillis; + + elapsedMillis = Math.max(0, elapsedMillis); + elapsedMillis = Math.min(totalDurationMillis, elapsedMillis); + + bar = bar.append(Component.text("Ability Recharging: ", NamedTextColor.WHITE)) + .append(Text.color(Text.generateProgressBar(20, (int)totalDurationMillis, (int)elapsedMillis))); + } else { + bar = bar.append(Component.text("Ability Ready", NamedTextColor.namedColor(0x00FFAA))); + } + + bar = bar.append(Text.formatArgs(Text.Pallet.INFO," /info {0} for usage",Text.formatEnum(AbilityBackend.ValidPattern.validate(pattern)))); + + player.sendActionBar(bar); + } +} diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/AbstractAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/AbstractAbility.java index 677d15d..6595b61 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/AbstractAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/AbstractAbility.java @@ -4,7 +4,8 @@ import io.papermc.paper.registry.RegistryAccess; import io.papermc.paper.registry.RegistryKey; import me.trouper.trimserver.server.Main; import me.trouper.trimserver.server.events.QuickListener; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.server.systems.AbilityBackend; +import me.trouper.trimserver.utils.text.Text; import net.kyori.adventure.text.Component; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -101,25 +102,20 @@ public abstract class AbstractAbility implements Main, QuickListener { * @return true if the ability was successfully executed and should apply cooldown, * false if the ability failed or otherwise shouldn't trigger cooldown. */ - public final boolean dispatchAbility(TrimMaterial material, Player player) { - String methodName = getMethodNameForMaterial(material); - if (methodName == null) { - main.getPlugin().getLogger().warning("Attempted to dispatch for unknown material: " + main.getRegistryAccess().getRegistry(RegistryKey.TRIM_MATERIAL).getKey(material).getKey()); - return false; - } - - try { - Method abilityMethod = this.getClass().getMethod(methodName, Player.class); - Object result = abilityMethod.invoke(this, player); - return (result instanceof Boolean) ? (Boolean) result : true; - } catch (NoSuchMethodException e) { - main.getPlugin().getLogger().warning("Method " + methodName + " not found in " + this.getClass().getSimpleName() + " for dispatch."); - return false; - } catch (Exception e) { - main.getPlugin().getLogger().severe("Error dispatching ability method " + methodName + " for pattern " + getPatternName() + ": " + e.getMessage()); - e.printStackTrace(); - return false; - } + public final boolean dispatchAbility(AbilityBackend.ValidMaterial material, Player player) { + return switch (material) { + case AMETHYST -> amethystAbility(player); + case COPPER -> copperAbility(player); + case DIAMOND -> diamondAbility(player); + case EMERALD -> emeraldAbility(player); + case GOLD -> goldAbility(player); + case IRON -> ironAbility(player); + case LAPIS -> lapisAbility(player); + case NETHERITE -> netheriteAbility(player); + case QUARTZ -> quartzAbility(player); + case REDSTONE -> redstoneAbility(player); + case RESIN -> resinAbility(player); + }; } /** diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/WormEvent.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/WormEvent.java index 04b4993..6309fc9 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/WormEvent.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/WormEvent.java @@ -1,6 +1,6 @@ package me.trouper.trimserver.server.systems.abilities; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.Verbose; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; import org.bukkit.*; @@ -38,7 +38,7 @@ public class WormEvent { private static final Material WORM_TEETH_MATERIAL = Material.DRIPSTONE_BLOCK; private static final int TICKS_PER_SECOND = 5; // Standard Minecraft ticks per second private static final double TEETH_CLOSE_FACTOR = 1; // How far teeth move inwards (fraction of radius, 0.0 to 1.0) - private static final double DAMAGE_AMOUNT = 19; // Damage dealt by the worm's bite + private static final double DAMAGE_AMOUNT = 90; // Damage dealt by the worm's bite private static final float BITE_SOUND_VOLUME = 2.0f; private static final float BITE_SOUND_PITCH_GROWL = 0.5f; private static final float BITE_SOUND_PITCH_GRIND = 0.1f; diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/BoltAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/BoltAbility.java index 56ad809..6d79458 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/BoltAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/BoltAbility.java @@ -6,14 +6,13 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; import org.bukkit.*; import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageType; import org.bukkit.entity.Player; import org.bukkit.inventory.meta.trim.TrimPattern; -import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; import java.util.ArrayList; @@ -22,11 +21,20 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Bolt", description = "Summon a bolt of lightning at enemies. Includes Variants.") public class BoltAbility extends AbstractAbility implements Main { + + public static final int NORMAL_COOLDOWN = 20 * 10; + public static final double NORMAL_DAMAGE = 10; + + public static final int RESIN_COOLDOWN = 20 * 5; + public static final double RESIN_DAMAGE = 7; + + public static final int NETHERITE_COOLDOWN = 20 * 15; + public static final double NETHERITE_DAMAGE = 20; public BoltAbility() { super(TrimPattern.BOLT); } - + public boolean strike(Player caster, int range, double damage, Material innerBlock, Material outerBlock) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -36,7 +44,7 @@ public class BoltAbility extends AbstractAbility implements Main { main.man().abilityBackend.abilityAllowed(caster,target.getLocation()),(target) ->{ drawLightning(caster.getEyeLocation(),target.getEyeLocation(),innerBlock,outerBlock); target.damage(damage,DamageSource.builder(DamageType.LIGHTNING_BOLT).withDamageLocation(caster.getEyeLocation()).withDirectEntity(caster).build()); - if (target instanceof Player t) Text.sendMessage(Text.Pallet.INFO,t,"You have been stunned by {0}'s Bolt!",caster.name()); + if (target instanceof Player t) Text.sendMessage(Text.Pallet.INFO,t,"You have been stunned by {0}'s Bolt!",caster.getName()); AtomicInteger counter = new AtomicInteger(0); Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task) -> { @@ -96,69 +104,69 @@ public class BoltAbility extends AbstractAbility implements Main { BlockDisplayRaytracer.trace(blockOuter, current, end, thicknessOut, stayTime, viewers); } - @MaterialInfo(name = "Amethyst Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Amethyst Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - return strike(player,20,10,Material.AMETHYST_BLOCK,Material.PURPLE_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.AMETHYST_BLOCK,Material.PURPLE_STAINED_GLASS); } - @MaterialInfo(name = "Copper Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Copper Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - return strike(player,20,10,Material.ORANGE_TERRACOTTA,Material.ORANGE_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.ORANGE_TERRACOTTA,Material.ORANGE_STAINED_GLASS); } - @MaterialInfo(name = "Diamond Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Diamond Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - return strike(player,20,10,Material.LIGHT_BLUE_CONCRETE_POWDER,Material.LIGHT_BLUE_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.LIGHT_BLUE_CONCRETE_POWDER,Material.LIGHT_BLUE_STAINED_GLASS); } - @MaterialInfo(name = "Emerald ",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Emerald ",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - return strike(player,20,10,Material.LIME_CONCRETE,Material.LIME_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.LIME_CONCRETE,Material.LIME_STAINED_GLASS); } - @MaterialInfo(name = "Gold Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Gold Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - return strike(player,20,10,Material.YELLOW_CONCRETE_POWDER,Material.YELLOW_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.YELLOW_CONCRETE_POWDER,Material.YELLOW_STAINED_GLASS); } - @MaterialInfo(name = "Iron Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Iron Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - return strike(player,20,10,Material.LIGHT_GRAY_WOOL,Material.LIGHT_GRAY_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.LIGHT_GRAY_WOOL,Material.LIGHT_GRAY_STAINED_GLASS); } - @MaterialInfo(name = "Lapis Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Lapis Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - return strike(player,20,10,Material.BLUE_CONCRETE,Material.BLUE_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.BLUE_CONCRETE,Material.BLUE_STAINED_GLASS); } - @MaterialInfo(name = "Netherite Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 15 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Netherite Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 15 Damage", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - return strike(player,30,15,Material.BLACK_CONCRETE,Material.GRAY_STAINED_GLASS); + return strike(player,30,NETHERITE_DAMAGE,Material.BLACK_CONCRETE,Material.GRAY_STAINED_GLASS); } - @MaterialInfo(name = "Quartz Bolt",description = "Shoots a bolt of overcharged lightning at your closest enemy within 20 blocks. Deals 15 Damage", cooldownTicks = 20*12) + @MaterialInfo(name = "Quartz Bolt",description = "Shoots a bolt of overcharged lightning at your closest enemy within 20 blocks. Deals 15 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - return strike(player,20,10,Material.WHITE_CONCRETE,Material.WHITE_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.WHITE_CONCRETE,Material.WHITE_STAINED_GLASS); } - @MaterialInfo(name = "Redstone Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Redstone Bolt",description = "Shoots a bolt of colored lightning at your closest enemy within 20 blocks. Deals 10 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - return strike(player,20,10,Material.RED_CONCRETE_POWDER,Material.RED_STAINED_GLASS); + return strike(player,20,NORMAL_DAMAGE,Material.RED_CONCRETE_POWDER,Material.RED_STAINED_GLASS); } - @MaterialInfo(name = "Resin Bolt",description = "Shoots a bolt of resin lightning at your closest enemy within 20 blocks. Deals 7 Damage", cooldownTicks = 20*5) + @MaterialInfo(name = "Resin Bolt",description = "Shoots a bolt of resin lightning at your closest enemy within 20 blocks. Deals 7 Damage", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - return strike(player,20,7,Material.RESIN_BLOCK,Material.ORANGE_STAINED_GLASS); + return strike(player,20,RESIN_DAMAGE,Material.RESIN_BLOCK,Material.ORANGE_STAINED_GLASS); } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/CoastAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/CoastAbility.java index 609df3a..e378db7 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/CoastAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/CoastAbility.java @@ -5,6 +5,7 @@ import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; +import me.trouper.trimserver.utils.text.CustomBossBar; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -25,32 +26,28 @@ public class CoastAbility extends AbstractAbility { private final Map activeUndertoes = new ConcurrentHashMap<>(); - private static final double BASE_UNDERTOE_RADIUS = 5.5; - private static final int BASE_UNDERTOE_DURATION_TICKS = 10 * 20; - private static final double BASE_PULL_STRENGTH = 0.18; - private static final double BASE_DAMAGE_PER_SECOND = 2.0; + private static final double NORMAL_RADIUS = 5.5; + private static final int NORMAL_DURATION = 10 * 20; + private static final double NORMAL_PULL_STRENGTH = 0.18; + private static final double NORMAL_DAMAGE_PER_SECOND = 2.0; - // Cooldowns private static final int DEFAULT_COOLDOWN = 20 * 45; private static final int NETHERITE_COOLDOWN = 20 * 60; private static final int RESIN_COOLDOWN = 20 * 25; - // Netherite Modifiers private static final double NETHERITE_RADIUS_MULTIPLIER = 1.25; private static final double NETHERITE_DURATION_MULTIPLIER = 1.5; private static final double NETHERITE_DAMAGE_MULTIPLIER = 1.5; private static final double NETHERITE_PULL_MULTIPLIER = 1.3; - private static final int NETHERITE_SLOWNESS_AMPLIFIER = 2; + - // Resin Modifiers private static final double RESIN_DAMAGE_MULTIPLIER = 0.8; - public CoastAbility() { super(TrimPattern.COAST); } - private void createUndertoe(Player player, Material material) { + private void createUndertoe(Player player, Material material, double radius, double pullStrength, double damagePerSecond, int duration) { UUID playerUUID = player.getUniqueId(); if (activeUndertoes.containsKey(playerUUID)) { @@ -73,30 +70,15 @@ public class CoastAbility extends AbstractAbility { if (world == null) return; - double currentRadius = BASE_UNDERTOE_RADIUS; - int currentDuration = BASE_UNDERTOE_DURATION_TICKS; - double currentDamage = BASE_DAMAGE_PER_SECOND; - double currentPullStrength = BASE_PULL_STRENGTH; - int slownessAmplifier = 1; - - if (material == Material.NETHERITE_BLOCK) { - currentRadius *= NETHERITE_RADIUS_MULTIPLIER; - currentDuration = (int) (currentDuration * NETHERITE_DURATION_MULTIPLIER); - currentDamage *= NETHERITE_DAMAGE_MULTIPLIER; - currentPullStrength *= NETHERITE_PULL_MULTIPLIER; - slownessAmplifier = NETHERITE_SLOWNESS_AMPLIFIER; - } else if (material == Material.RESIN_BLOCK) { - currentDamage *= RESIN_DAMAGE_MULTIPLIER; - } - new SoundPlayer(centerLocation, Sound.ENTITY_PLAYER_SPLASH_HIGH_SPEED, 1.2f, 0.8f).playWithin(30); new SoundPlayer(centerLocation, Sound.BLOCK_WATER_AMBIENT, 1.0f, 0.5f).playWithin(30); - final double finalRadius = currentRadius; - final int finalDuration = currentDuration; - final double finalDamage = currentDamage; - final double finalPullStrength = currentPullStrength; - final int finalSlownessAmplifier = slownessAmplifier; + final double finalRadius = radius; + final int finalDuration = duration; + final double finalDamage = damagePerSecond; + final double finalPullStrength = pullStrength; + final int finalSlownessAmplifier = 1; + CustomBossBar.showBossBar(main.getPlugin(),player,"Undertoe",finalDuration); BukkitTask task = new BukkitRunnable() { int ticksElapsed = 0; @@ -184,77 +166,77 @@ public class CoastAbility extends AbstractAbility { @MaterialInfo(name = "Amethyst Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean amethystAbility(Player player) { - createUndertoe(player, Material.AMETHYST_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Copper Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean copperAbility(Player player) { - createUndertoe(player, Material.COPPER_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Diamond Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean diamondAbility(Player player) { - createUndertoe(player, Material.DIAMOND_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Emerald Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - createUndertoe(player, Material.EMERALD_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Gold Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean goldAbility(Player player) { - createUndertoe(player, Material.GOLD_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Iron Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean ironAbility(Player player) { - createUndertoe(player, Material.IRON_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Lapis Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean lapisAbility(Player player) { - createUndertoe(player, Material.LAPIS_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Netherite Undertoe", description = "A larger, stronger, and longer-lasting vortex that fiercely pulls, damages, and disorients foes.", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - createUndertoe(player, Material.NETHERITE_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS * NETHERITE_RADIUS_MULTIPLIER, NORMAL_PULL_STRENGTH * NETHERITE_PULL_MULTIPLIER, NORMAL_DAMAGE_PER_SECOND * NETHERITE_DAMAGE_MULTIPLIER, (int) (NORMAL_DURATION * NETHERITE_DURATION_MULTIPLIER)); return true; } @MaterialInfo(name = "Quartz Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean quartzAbility(Player player) { - createUndertoe(player, Material.QUARTZ_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Redstone Undertoe", description = "A swirling vortex pulls and drowns foes.", cooldownTicks = DEFAULT_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - createUndertoe(player, Material.REDSTONE_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND,NORMAL_DURATION); return true; } @MaterialInfo(name = "Resin Undertoe", description = "A slightly weaker vortex that pulls and drowns foes, but recharges faster.", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - createUndertoe(player, Material.RESIN_BLOCK); + createUndertoe(player, Material.AMETHYST_BLOCK, NORMAL_RADIUS, NORMAL_PULL_STRENGTH, NORMAL_DAMAGE_PER_SECOND * RESIN_DAMAGE_MULTIPLIER,NORMAL_DURATION); return true; } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/DuneAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/DuneAbility.java index a83fb54..69dc2bc 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/DuneAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/DuneAbility.java @@ -7,7 +7,7 @@ import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.WormEvent; import me.trouper.trimserver.utils.PlayerUtils; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.visual.DisplayUtils; import org.bukkit.*; import org.bukkit.block.Block; diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/EyeAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/EyeAbility.java index 147ea60..15ca81d 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/EyeAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/EyeAbility.java @@ -25,11 +25,26 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Eye of Power", description = "Allows you to see players hidden with the host trim. Includes variants.") public class EyeAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 30; + public static final int NORMAL_DURATION = 5; + public static final double NORMAL_DAMAGE = 0.1; + public static final double NORMAL_DAMAGE_FAIL_CHANCE = 0.75; + + public static final int NETHERITE_COOLDOWN = 20 * 15; + public static final int NETHERITE_DURATION = 10; + public static final double NETHERITE_DAMAGE = 0.2; + public static final double NETHERITE_DAMAGE_FAIL_CHANCE = 0.50; + + public static final int RESIN_COOLDOWN = 20 * 10; + public static final long RESIN_DURATION = 3; + public static final double RESIN_DAMAGE = 0.1; + public static final double RESIN_DAMAGE_FAIL_CHANCE = 0.80; + public EyeAbility() { super(TrimPattern.EYE); } - public void eyeLasers(Player player, Material beam,Material glow, long durationSeconds) { + public void eyeLasers(Player player, Material beam,Material glow, long durationSeconds, double damagePerTick, double damageFailChance) { AtomicInteger timer = new AtomicInteger(0); Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task)->{ if (timer.getAndIncrement() >= durationSeconds * 20) { @@ -42,11 +57,10 @@ public class EyeAbility extends AbstractAbility { Vector eyeCenter = headLocation.getDirection(); Vector leftRight = new Vector(-eyeCenter.getZ(), 0, eyeCenter.getX()).normalize().multiply(0.2); - // Two eye locations Location leftEye = headLocation.clone().add(leftRight); Location rightEye = headLocation.clone().subtract(leftRight); - Location focus = laser(player,headLocation,eyeCenter,60); + Location focus = laser(player,headLocation,eyeCenter,60,damagePerTick,damageFailChance); BlockDisplayRaytracer.trace(beam,leftEye,focus,0.05,2); BlockDisplayRaytracer.trace(glow,leftEye,focus,0.1,2); @@ -56,7 +70,7 @@ public class EyeAbility extends AbstractAbility { },0,1); } - public Location laser(Player owner, Location start, Vector direction, double distance) { + public Location laser(Player owner, Location start, Vector direction, double distance, double damagePerTick, double damageFailChance) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -73,13 +87,16 @@ public class EyeAbility extends AbstractAbility { if (!(entity instanceof LivingEntity liv) || shaper.activeShellTasks.containsKey(liv.getUniqueId())) return; hissSound.playWithin(30); - int tick = liv.getNoDamageTicks(); - int maxTick = liv.getMaximumNoDamageTicks(); - liv.setNoDamageTicks(0); - liv.setMaximumNoDamageTicks(0); - liv.damage(0.1,DamageSource.builder(DamageType.STING).withDamageLocation(owner.getLocation()).withDirectEntity(owner).build()); - liv.setNoDamageTicks(tick); - liv.setMaximumNoDamageTicks(maxTick); + if (random.nextDouble(1) >= damageFailChance) { + int tick = liv.getNoDamageTicks(); + int maxTick = liv.getMaximumNoDamageTicks(); + + liv.setNoDamageTicks(0); + liv.setMaximumNoDamageTicks(0); + liv.damage(damagePerTick,DamageSource.builder(DamageType.STING).withDamageLocation(owner.getLocation()).withDirectEntity(owner).build()); + liv.setNoDamageTicks(tick); + liv.setMaximumNoDamageTicks(maxTick); + } liv.setFireTicks(20); liv.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS,20,1,true,false,false)); @@ -94,80 +111,80 @@ public class EyeAbility extends AbstractAbility { }).getLoc(); } - @MaterialInfo(name = "Amethyst Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Amethyst Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - eyeLasers(player,Material.PURPLE_CONCRETE_POWDER,Material.MAGENTA_STAINED_GLASS,5); + eyeLasers(player,Material.PURPLE_CONCRETE_POWDER,Material.MAGENTA_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Copper Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Copper Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - eyeLasers(player,Material.LIME_TERRACOTTA,Material.GREEN_STAINED_GLASS,5); + eyeLasers(player,Material.LIME_TERRACOTTA,Material.GREEN_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Diamond Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Diamond Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - eyeLasers(player,Material.LIGHT_BLUE_CONCRETE_POWDER,Material.LIGHT_BLUE_STAINED_GLASS,5); + eyeLasers(player,Material.LIGHT_BLUE_CONCRETE_POWDER,Material.LIGHT_BLUE_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Emerald Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Emerald Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - eyeLasers(player,Material.LIME_CONCRETE_POWDER,Material.LIME_STAINED_GLASS,5); + eyeLasers(player,Material.LIME_CONCRETE_POWDER,Material.LIME_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Gold Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Gold Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - eyeLasers(player,Material.YELLOW_TERRACOTTA,Material.YELLOW_STAINED_GLASS,5); + eyeLasers(player,Material.YELLOW_TERRACOTTA,Material.YELLOW_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Iron Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Iron Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - eyeLasers(player,Material.LIGHT_GRAY_CONCRETE_POWDER,Material.LIGHT_GRAY_STAINED_GLASS,5); + eyeLasers(player,Material.LIGHT_GRAY_CONCRETE_POWDER,Material.LIGHT_GRAY_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Lapis Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Lapis Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - eyeLasers(player,Material.BLUE_CONCRETE,Material.BLUE_STAINED_GLASS,5); + eyeLasers(player,Material.BLUE_CONCRETE,Material.BLUE_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Netherite Laser beam", description = "Shoot lasers from the eye on the chestpiece for 10 seconds", cooldownTicks = 20 * 40) + @MaterialInfo(name = "Netherite Laser beam", description = "Shoot lasers from the eye on the chestpiece for 10 seconds", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - eyeLasers(player,Material.BLACK_CONCRETE,Material.BLACK_STAINED_GLASS,20); + eyeLasers(player,Material.BLACK_CONCRETE,Material.BLACK_STAINED_GLASS,NETHERITE_DURATION,NETHERITE_DAMAGE,NETHERITE_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Quartz Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Quartz Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - eyeLasers(player,Material.WHITE_CONCRETE_POWDER,Material.WHITE_STAINED_GLASS,5); + eyeLasers(player,Material.WHITE_CONCRETE_POWDER,Material.WHITE_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Redstone Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Redstone Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - eyeLasers(player,Material.RED_CONCRETE,Material.RED_STAINED_GLASS,5); + eyeLasers(player,Material.RED_CONCRETE,Material.RED_STAINED_GLASS,NORMAL_DURATION,NORMAL_DAMAGE,NORMAL_DAMAGE_FAIL_CHANCE); return true; } - @MaterialInfo(name = "Resin Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Resin Laser beam", description = "Shoot lasers from the eye on the chestpiece for 5 seconds", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - eyeLasers(player,Material.ORANGE_CONCRETE_POWDER,Material.ORANGE_STAINED_GLASS,5); + eyeLasers(player,Material.ORANGE_CONCRETE_POWDER,Material.ORANGE_STAINED_GLASS,RESIN_DURATION,RESIN_DAMAGE,RESIN_DAMAGE_FAIL_CHANCE); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/FlowAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/FlowAbility.java index b5bfc6e..c4bcbcb 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/FlowAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/FlowAbility.java @@ -5,7 +5,8 @@ import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.CustomBossBar; +import me.trouper.trimserver.utils.text.Text; import org.bukkit.*; import org.bukkit.entity.*; import org.bukkit.event.EventHandler; @@ -24,6 +25,22 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Wind Rider", description = "Summon a breeze to ride through the sky") public class FlowAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 50; + public static final int NORMAL_DURATION = 30; + public static final double NORMAL_HEALTH = 10; + public static final double NORMAL_LAUNCH_STRENGTH = 1; + + public static final int NETHERITE_COOLDOWN = 20 * 90; + public static final int NETHERITE_DURATION = 45; + public static final double NETHERITE_HEALTH = 20; + public static final double NETHERITE_LAUNCH_STRENGTH = 2; + + public static final int RESIN_COOLDOWN = 20 * 30; + public static final int RESIN_DURATION = 20; + public static final double RESIN_HEALTH = 5; + public static final double RESIN_LAUNCH_STRENGTH = 0.7; + + private final Map activeRiders = new HashMap<>(); private final Map activeBreezes = new HashMap<>(); @@ -31,7 +48,7 @@ public class FlowAbility extends AbstractAbility { super(TrimPattern.FLOW); } - private void spawnRideableBreeze(Player player, int duration, Material material) { + private void spawnRideableBreeze(Player player, int duration, Material material, double launchStrength, double health) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -53,7 +70,7 @@ public class FlowAbility extends AbstractAbility { breeze.setCustomNameVisible(true); breeze.addPassenger(player); breeze.setAI(true); - breeze.setInvulnerable(true); + breeze.setHealth(health); breeze.addScoreboardTag("$/TrimServer/ Temp"); activeBreezes.put(player.getUniqueId(), breeze); @@ -62,6 +79,7 @@ public class FlowAbility extends AbstractAbility { world.spawnParticle(Particle.BLOCK_CRUMBLE, spawnLoc, 20, 0.5, 0.5, 0.5, 0.1, material.createBlockData()); SoundPlayer summonSound = new SoundPlayer(spawnLoc, Sound.ENTITY_BREEZE_SHOOT, 1.0f, 0.8f); summonSound.playWithin(10); + CustomBossBar.showBossBar(main.getPlugin(),player,"Wind Rider",duration * 20); BukkitTask task = new BukkitRunnable() { final long endTime = System.currentTimeMillis() + (duration * 1000L); @@ -95,7 +113,7 @@ public class FlowAbility extends AbstractAbility { } TargetingUtils.areaAffect(breeze.getLocation(),1.5,entity -> !entity.equals(player) && !main.man().trustBackend.trusts(player,entity) && !breeze.equals(entity) && !shaper.activeShellTasks.containsKey(entity.getUniqueId()),target->{ - launchEntity(target); + launchEntity(target, launchStrength); world.spawnParticle(Particle.EXPLOSION, target.getLocation(), 10, 0.5, 0.5, 0.5, 0.1); }); } @@ -126,8 +144,8 @@ public class FlowAbility extends AbstractAbility { }); } - private void launchEntity(Entity target) { - Vector launchVector = new Vector(0, 2, 0); + private void launchEntity(Entity target, double strength) { + Vector launchVector = new Vector(0, strength, 0); target.setVelocity(target.getVelocity().add(launchVector)); target.getWorld().spawnParticle( @@ -150,6 +168,8 @@ public class FlowAbility extends AbstractAbility { activeBreezes.remove(player.getUniqueId()); } + CustomBossBar.removeBossBar(player); + Location loc = breeze.getLocation(); breeze.getWorld().spawnParticle(Particle.CLOUD, loc, 50, 1, 1, 1, 0.2); SoundPlayer despawnSound = new SoundPlayer(loc, Sound.ENTITY_BREEZE_DEATH, 1.0f, 1.0f); @@ -179,80 +199,80 @@ public class FlowAbility extends AbstractAbility { } } - @MaterialInfo(name = "Amethyst Wind Rider", description = "Summon an amethyst-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Amethyst Wind Rider", description = "Summon an amethyst-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - spawnRideableBreeze(player, 30, Material.AMETHYST_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.AMETHYST_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Copper Wind Rider", description = "Summon a copper-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Copper Wind Rider", description = "Summon a copper-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - spawnRideableBreeze(player, 30, Material.COPPER_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.COPPER_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Diamond Wind Rider", description = "Summon a diamond-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Diamond Wind Rider", description = "Summon a diamond-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - spawnRideableBreeze(player, 30, Material.DIAMOND_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.DIAMOND_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Emerald Wind Rider", description = "Summon an emerald-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Emerald Wind Rider", description = "Summon an emerald-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - spawnRideableBreeze(player, 30, Material.EMERALD_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.EMERALD_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Gold Wind Rider", description = "Summon a gold-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Gold Wind Rider", description = "Summon a gold-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - spawnRideableBreeze(player, 30, Material.GOLD_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.GOLD_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Iron Wind Rider", description = "Summon an iron-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Iron Wind Rider", description = "Summon an iron-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - spawnRideableBreeze(player, 30, Material.IRON_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.IRON_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Lapis Wind Rider", description = "Summon a lapis-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Lapis Wind Rider", description = "Summon a lapis-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - spawnRideableBreeze(player, 30, Material.LAPIS_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.LAPIS_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Netherite Wind Rider", description = "Summon a powerful netherite-infused breeze to ride", cooldownTicks = 20 * 90) + @MaterialInfo(name = "Netherite Wind Rider", description = "Summon a powerful netherite-infused breeze to ride", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - spawnRideableBreeze(player, 45, Material.NETHERITE_BLOCK); + spawnRideableBreeze(player, NETHERITE_DURATION, Material.NETHERITE_BLOCK,NETHERITE_LAUNCH_STRENGTH,NETHERITE_HEALTH); return true; } - @MaterialInfo(name = "Quartz Wind Rider", description = "Summon a quartz-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Quartz Wind Rider", description = "Summon a quartz-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - spawnRideableBreeze(player, 30, Material.QUARTZ_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.QUARTZ_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Redstone Wind Rider", description = "Summon a redstone-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Redstone Wind Rider", description = "Summon a redstone-infused breeze to ride", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - spawnRideableBreeze(player, 30, Material.REDSTONE_BLOCK); + spawnRideableBreeze(player, NORMAL_DURATION, Material.REDSTONE_BLOCK,NORMAL_LAUNCH_STRENGTH,NORMAL_HEALTH); return true; } - @MaterialInfo(name = "Resin Wind Rider", description = "Summon a resin-infused breeze to ride", cooldownTicks = 20 * 60) + @MaterialInfo(name = "Resin Wind Rider", description = "Summon a resin-infused breeze to ride", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - spawnRideableBreeze(player, 30, Material.RESIN_BLOCK); + spawnRideableBreeze(player, RESIN_DURATION, Material.RESIN_BLOCK,RESIN_LAUNCH_STRENGTH,RESIN_HEALTH); return true; } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/HostAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/HostAbility.java index 0aec17c..0d28f95 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/HostAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/HostAbility.java @@ -4,145 +4,176 @@ import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.utils.SoundPlayer; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.CustomBossBar; +import me.trouper.trimserver.utils.text.Text; import org.bukkit.Bukkit; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; -@PatternInfo(name = "The Host", description = "Disappear into the shadows like Gatsby.") +@PatternInfo(name = "The Host", description = "And like that, he vanishes!") public class HostAbility extends AbstractAbility { + + public static final int NORMAL_DURATION = 6; + public static final int NORMAL_COOLDOWN = 20 * 30; + + public static final int NETHERITE_DURATION = 15; + public static final int NETHERITE_COOLDOWN = 20 * 20; + + public static final int RESIN_DURATION = 5; + public static final int RESIN_COOLDOWN = 20 * 15; public HostAbility() { super(TrimPattern.HOST); } + private final Set hiddenPlayers = new HashSet<>(); public void makeInvisible(Player invis, long seconds) { - AbstractAbility eyeInstance = main.man().abilityBackend.getAbility(TrimPattern.EYE); - EyeAbility eye = (EyeAbility) eyeInstance; - invis.getLocation().getWorld().spawnParticle(Particle.EXPLOSION_EMITTER,invis.getLocation(),1,0,0,0); new SoundPlayer(invis.getLocation(),Sound.BLOCK_REDSTONE_TORCH_BURNOUT,10,0.5F); - invis.addScoreboardTag("$/TrimServer/ Invisible"); + hiddenPlayers.add(invis.getUniqueId()); for (Player player : Bukkit.getOnlinePlayers()) { - if (main.man().trustBackend.trusts(invis,player) || main.man().abilityBackend.getAbility(player).getPattern().equals(TrimPattern.EYE)) continue; + AbstractAbility ability = main.man().abilityBackend.getAbility(player); + if (main.man().trustBackend.trusts(invis,player) || (ability != null && ability.getPattern().equals(TrimPattern.EYE))) continue; player.hidePlayer(main.getPlugin(),invis); - AtomicInteger timer = new AtomicInteger(); - Bukkit.getScheduler().runTaskTimer(main.getPlugin(),(task)->{ - if (timer.getAndIncrement() >= seconds) { - if (!player.isOnline() || !invis.isOnline()) return; - player.showPlayer(main.getPlugin(),invis); - task.cancel(); - return; - } - invis.sendActionBar(Text.color("&aYou are hidden from other players!")); - },0,20); - + } + + CustomBossBar.showBossBar(main.getPlugin(),invis,Text.color("&aYou are hidden from other players!"),20*(int)seconds); + + Bukkit.getScheduler().runTaskLater(main.getPlugin(),(task)->{ + show(invis); + },seconds * 20); + } + + @EventHandler + public void onDeath(PlayerDeathEvent e) { + if (hiddenPlayers.contains(e.getPlayer().getUniqueId())) { + show(e.getPlayer()); } } @EventHandler public void onJoin(PlayerJoinEvent e) { - if (e.getPlayer().getScoreboardTags().contains("$/TrimServer/ Invisible")) { - for (Player player : Bukkit.getOnlinePlayers()) { - player.showPlayer(main.getPlugin(),e.getPlayer()); - } + Player p = e.getPlayer(); + if (hiddenPlayers.contains(e.getPlayer().getUniqueId())) { + show(e.getPlayer()); + return; + } + for (UUID hiddenPlayer : hiddenPlayers) { + Player invis = Bukkit.getPlayer(hiddenPlayer); + if (invis == null) return; + AbstractAbility ability = main.man().abilityBackend.getAbility(p); + if (main.man().trustBackend.trusts(invis,p) || (ability != null && ability.getPattern().equals(TrimPattern.EYE))) return; + p.hidePlayer(main.getPlugin(),invis); } } - @MaterialInfo(name = "Amethyst ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + private void show(Player p) { + if (p == null) return; + hiddenPlayers.remove(p.getUniqueId()); + p.sendActionBar(Text.color("&cYou are now visible again!")); + for (Player player : Bukkit.getOnlinePlayers()) { + player.showPlayer(main.getPlugin(),p); + } + } + + @MaterialInfo(name = "Amethyst ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Copper ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Copper ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Diamond ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Diamond ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Emerald ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Emerald ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Gold ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Gold ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Iron ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Iron ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Lapis ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Lapis ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Netherite ", description = "Grants true invisibility for 10 seconds and makes your attacks stronger", cooldownTicks = 20 * 20) + @MaterialInfo(name = "Netherite ", description = "Grants true invisibility for 10 seconds and makes your attacks stronger", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - makeInvisible(player,10); - player.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,20*6,1,true,false,true)); + makeInvisible(player,NETHERITE_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.STRENGTH,NETHERITE_DURATION * 20,1,true,false,true)); return true; } - @MaterialInfo(name = "Quartz ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Quartz ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Redstone ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Redstone ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,NORMAL_DURATION * 20,0,true,false,true)); return true; } - @MaterialInfo(name = "Resin ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Resin ", description = "Grants true invisibility for 6 seconds but makes your attacks weaker", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - makeInvisible(player,20); - player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,20*6,0,true,false,true)); + makeInvisible(player,NORMAL_DURATION); + player.addPotionEffect(new PotionEffect(PotionEffectType.WEAKNESS,RESIN_DURATION * 10,0,true,false,true)); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RaiserAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RaiserAbility.java index 19a225c..f5762d8 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RaiserAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RaiserAbility.java @@ -5,7 +5,6 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.utils.PlayerUtils; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; import me.trouper.trimserver.utils.visual.DisplayUtils; import org.bukkit.*; @@ -25,13 +24,22 @@ import java.util.UUID; @PatternInfo(name = "Unexpected Levitation", description = "Raiser? I hardly know her!") public class RaiserAbility extends AbstractAbility { + public static final int NORMAL_DURATION = 15; + public static final int NORMAL_COOLDOWN = 20 * 40; + + public static final int NETHERITE_DURATION = 20; + public static final int NETHERITE_COOLDOWN = 20 * 25; + + public static final int RESIN_DURATION = 10; + public static final int RESIN_COOLDOWN = 20 * 15; + public RaiserAbility() { super(TrimPattern.RAISER); } private final Map levitationTasks = new HashMap<>(); - public void raiseEntity(Player caster, LivingEntity target) { + public void raiseEntity(Player caster, LivingEntity target, int durationSeconds) { if (target == null || !PlayerUtils.combatAllowed(target,caster)) return; UUID uuid = target.getUniqueId(); @@ -44,7 +52,7 @@ public class RaiserAbility extends AbstractAbility { double healthThreshold = initialHealth / 2.0; double targetY = initialLocation.getY() + 4.0; int frequency = 2; - int duration = 20 * 7; + int duration = durationSeconds * 20; target.getWorld().playSound(target.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.8f, 1.0f); BlockDisplay hook = BlockDisplayRaytracer.trace(Material.IRON_BLOCK,target.getEyeLocation(),target.getLocation().add(0,128,0),0.3,60); @@ -133,7 +141,7 @@ public class RaiserAbility extends AbstractAbility { } } - @MaterialInfo(name = "Amethyst ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Amethyst ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -142,11 +150,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Copper ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Copper ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -155,11 +163,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Diamond ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Diamond ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -168,11 +176,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Emerald ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Emerald ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -181,11 +189,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Gold ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Gold ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -194,11 +202,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Iron ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Iron ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -207,11 +215,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Lapis ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Lapis ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -220,21 +228,21 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Netherite ", description = "Pins your enemy 4 blocks into the air for 6 seconds. Can raise those with Shaper ability activated too.", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Netherite ", description = "Pins your enemy 4 blocks into the air for 6 seconds. Can raise those with Shaper ability activated too.", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { return TargetingUtils.areaAffect(player.getLocation(),15,target -> !main.man().trustBackend.trusts(player,target) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NETHERITE_DURATION); }); } - @MaterialInfo(name = "Quartz ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Quartz ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -243,11 +251,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Redstone ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Redstone ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -256,11 +264,11 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,NORMAL_DURATION); }); } - @MaterialInfo(name = "Resin ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Resin ", description = "Pins your enemy 4 blocks into the air for 6 seconds, or until they loose half their current health", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -269,7 +277,7 @@ public class RaiserAbility extends AbstractAbility { !main.man().trustBackend.trusts(player,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && main.man().abilityBackend.abilityAllowed(player,target.getLocation()), ent->{ - raiseEntity(player,ent); + raiseEntity(player,ent,RESIN_DURATION); }); } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RibAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RibAbility.java index c094bed..3a82d7e 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RibAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/RibAbility.java @@ -3,6 +3,7 @@ package me.trouper.trimserver.server.systems.abilities.trims; import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; +import me.trouper.trimserver.utils.PlayerUtils; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; @@ -27,13 +28,22 @@ import java.util.Random; @PatternInfo(name = "Nether Eruption", description = "Summons sharp spikes from the ground that damage enemies accompanied by a blast of toxic ash.") public class RibAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 30; + public static final int NORMAL_SPIKE_DAMAGE = 30; + + public static final int NETHERITE_COOLDOWN = 20 * 20; + public static final int NETHERITE_SPIKE_DAMAGE = 50; + + public static final int RESIN_COOLDOWN = 20 * 15; + public static final int RESIN_SPIKE_DAMAGE = 15; + private final Random random = new Random(); public RibAbility() { super(TrimPattern.RIB); } - private void executeEruption(Player caster, Material activatingTrimMaterial, int spikeCount, double areaRadius, int activeDurationTicks, Material groundParticleMaterial) { + private void executeEruption(Player caster, Material activatingTrimMaterial, double spikeDamage, double areaRadius, int activeDurationTicks, Material groundParticleMaterial) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -75,7 +85,7 @@ public class RibAbility extends AbstractAbility { BlockData spikeBlockData = activatingTrimMaterial.createBlockData(); BlockData groundBlockData = groundParticleMaterial.createBlockData(); - for (int i = 0; i < spikeCount; i++) { + for (int i = 0; i < 15; i++) { double angle = random.nextDouble() * 2 * Math.PI; double currentRandomRadius = random.nextDouble() * areaRadius; double dx = Math.cos(angle) * currentRandomRadius; @@ -83,7 +93,6 @@ public class RibAbility extends AbstractAbility { Location spikeBaseCenter = playerCenterLoc.clone().add(dx, 0, dz); - // Find the ground for the spike Block highestBlock = world.getHighestBlockAt(spikeBaseCenter.getBlockX(), spikeBaseCenter.getBlockZ()); Location groundSurfaceLoc = highestBlock.getLocation().add(0.5, 1.0, 0.5); @@ -149,10 +158,10 @@ public class RibAbility extends AbstractAbility { } if (ticksElapsed >= spikeRiseAnimationTicks / 2 && ticksElapsed <= spikeRiseAnimationTicks + 4 && !damageDealt) { - TargetingUtils.areaAffect(finalSpikeBase,1,target -> !target.equals(caster) && !main.man().trustBackend.trusts(caster,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()),target -> { + TargetingUtils.areaAffect(finalSpikeBase,4,target -> !target.equals(caster) && !main.man().trustBackend.trusts(caster,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && PlayerUtils.combatAllowed(target,caster), target -> { damageDealt = true; - target.damage(7.0, caster); + target.damage(spikeDamage, caster); Vector knockDir = new Vector(random.nextGaussian() * 0.15, 0.9 + random.nextDouble()*0.2, random.nextGaussian() * 0.15); target.setVelocity(target.getVelocity().add(knockDir)); new SoundPlayer(target.getLocation(), Sound.ENTITY_PLAYER_HURT_ON_FIRE, 1.0f, 1.0f).playWithin(15); @@ -191,7 +200,6 @@ public class RibAbility extends AbstractAbility { }.runTaskTimer(main.getPlugin(), delay, 1L); } - // Failsafe cleanup for all created displays new BukkitRunnable() { @Override public void run() { @@ -205,80 +213,80 @@ public class RibAbility extends AbstractAbility { }.runTaskLater(main.getPlugin(), activeDurationTicks + spikeRiseAnimationTicks + 40L); } - @MaterialInfo(name = "Eruption (Amethyst)", description = "Erupts spikes of amethyst", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Amethyst)", description = "Erupts spikes of amethyst", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - executeEruption(player, Material.AMETHYST_BLOCK, 10, 5.5, 20 * 5, Material.SMOOTH_BASALT); + executeEruption(player, Material.AMETHYST_BLOCK, NORMAL_SPIKE_DAMAGE, 5.5, 20 * 5, Material.SMOOTH_BASALT); return true; } - @MaterialInfo(name = "Eruption (Copper)", description = "Erupts spikes of oxidized copper", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Copper)", description = "Erupts spikes of oxidized copper", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - executeEruption(player, Material.RAW_COPPER, 10, 5.0, 20 * 5, Material.TUFF); + executeEruption(player, Material.RAW_COPPER, NORMAL_SPIKE_DAMAGE, 5.0, 20 * 5, Material.TUFF); return true; } - @MaterialInfo(name = "Eruption (Diamond)", description = "Erupts spikes of diamond", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Diamond)", description = "Erupts spikes of diamond", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - executeEruption(player, Material.DEEPSLATE_DIAMOND_ORE, 12, 6.0, 20 * 6, Material.DEEPSLATE); + executeEruption(player, Material.DEEPSLATE_DIAMOND_ORE, NORMAL_SPIKE_DAMAGE, 6.0, 20 * 6, Material.DEEPSLATE); return true; } - @MaterialInfo(name = "Eruption (Emerald)", description = "Erupts spikes of emerald", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Emerald)", description = "Erupts spikes of emerald", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - executeEruption(player, Material.DEEPSLATE_EMERALD_ORE, 12, 6.0, 20 * 6, Material.MOSS_BLOCK); + executeEruption(player, Material.DEEPSLATE_EMERALD_ORE, NORMAL_SPIKE_DAMAGE, 6.0, 20 * 6, Material.MOSS_BLOCK); return true; } - @MaterialInfo(name = "Eruption (Gold)", description = "Erupts spikes of gold", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Gold)", description = "Erupts spikes of gold", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - executeEruption(player, Material.DEEPSLATE_GOLD_ORE, 10, 5.0, 20 * 5, Material.NETHER_GOLD_ORE); + executeEruption(player, Material.DEEPSLATE_GOLD_ORE, NORMAL_SPIKE_DAMAGE, 5.0, 20 * 5, Material.NETHER_GOLD_ORE); return true; } - @MaterialInfo(name = "Eruption (Iron)", description = "Erupts spikes of iron", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Iron)", description = "Erupts spikes of iron", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - executeEruption(player, Material.RAW_IRON_BLOCK, 11, 5.5, 20 * 5, Material.RAW_IRON_BLOCK); + executeEruption(player, Material.RAW_IRON_BLOCK, NORMAL_SPIKE_DAMAGE, 5.5, 20 * 5, Material.RAW_IRON_BLOCK); return true; } - @MaterialInfo(name = "Eruption (Lapis)", description = "Erupts spikes of lapis", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Lapis)", description = "Erupts spikes of lapis", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - executeEruption(player, Material.LAPIS_BLOCK, 10, 5.0, 20 * 5, Material.CLAY); + executeEruption(player, Material.LAPIS_BLOCK, NORMAL_SPIKE_DAMAGE, 5.0, 20 * 5, Material.CLAY); return true; } - @MaterialInfo(name = "Eruption (Netherite)", description = "Erupts deadly blackstone spikes", cooldownTicks = 20 * 20) + @MaterialInfo(name = "Eruption (Netherite)", description = "Erupts deadly blackstone spikes", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - executeEruption(player, Material.BLACKSTONE, 20, 10.0, 20 * 8, Material.BLACKSTONE); + executeEruption(player, Material.BLACKSTONE, NETHERITE_SPIKE_DAMAGE, 10.0, 20 * 8, Material.BLACKSTONE); return true; } - @MaterialInfo(name = "Eruption (Quartz)", description = "Erupts spikes of quartz", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Quartz)", description = "Erupts spikes of quartz", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - executeEruption(player, Material.QUARTZ_BLOCK, 11, 5.5, 20 * 5, Material.NETHER_QUARTZ_ORE); + executeEruption(player, Material.QUARTZ_BLOCK, NORMAL_SPIKE_DAMAGE, 5.5, 20 * 5, Material.NETHER_QUARTZ_ORE); return true; } - @MaterialInfo(name = "Eruption (Redstone)", description = "Erupts energized redstone spikes", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Redstone)", description = "Erupts energized redstone spikes", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - executeEruption(player, Material.REDSTONE_BLOCK, 11, 5.5, 20 * 5, Material.REDSTONE_ORE); + executeEruption(player, Material.REDSTONE_BLOCK, NORMAL_SPIKE_DAMAGE, 5.5, 20 * 5, Material.REDSTONE_ORE); return true; } - @MaterialInfo(name = "Eruption (Resin)", description = "Erupts spikes of hardened resin from the ground", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Eruption (Resin)", description = "Erupts spikes of hardened resin from the ground", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - executeEruption(player, Material.RESIN_BLOCK, 12, 6.0, 20 * 6, Material.NETHERRACK); + executeEruption(player, Material.RESIN_BLOCK, RESIN_SPIKE_DAMAGE, 6.0, 20 * 6, Material.NETHERRACK); return true; } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SentryAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SentryAbility.java index c38d800..5b87d12 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SentryAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SentryAbility.java @@ -6,7 +6,7 @@ import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.utils.PlayerUtils; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; import me.trouper.trimserver.utils.visual.CustomDisplayRaytracer; import org.bukkit.*; @@ -29,6 +29,21 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Build Sentry", description = "\"Meet the Engineer.\" Includes Variants.") public class SentryAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 10; + public static final int NORMAL_AMMO = 30; + public static final int NORMAL_MAX_LIFE = 30; + public static final int NORMAL_BULLET_COOLDOWN = 5; + + public static final int NETHERITE_COOLDOWN = 20 * 15; + public static final int NETHERITE_AMMO = 50; + public static final int NETHERITE_MAX_LIFE = 45; + public static final int NETHERITE_BULLET_COOLDOWN = 2; + + public static final int RESIN_COOLDOWN = 20 * 5; + public static final int RESIN_AMMO = 15; + public static final int RESIN_MAX_LIFE = 15; + public static final int RESIN_BULLET_COOLDOWN = 3; + public SentryAbility() { super(TrimPattern.SENTRY); } @@ -132,7 +147,7 @@ public class SentryAbility extends AbstractAbility { CustomDisplayRaytracer.trace(turret.getLocation(),dir,60,0.5,point -> { List hits = new ArrayList<>(w.getNearbyEntities(point.getLoc(), 0.5,0.5,0.5, entity -> { - return entity instanceof LivingEntity living && !(living instanceof Bat) && !living.isDead() && living != owner; + return entity instanceof LivingEntity living && !(living instanceof Shulker) && !living.isDead() && living != owner; })); hits.forEach(t -> { if (t instanceof LivingEntity liv) { @@ -215,80 +230,80 @@ public class SentryAbility extends AbstractAbility { e.getDrops().clear(); } - @MaterialInfo(name = "Amethyst ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Amethyst ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.AMETHYST_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.AMETHYST_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Copper ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Copper ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.COPPER_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.COPPER_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Diamond ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Diamond ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.DIAMOND_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.DIAMOND_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Emerald ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Emerald ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.EMERALD_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.EMERALD_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Gold ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Gold ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.GOLD_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.GOLD_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Iron ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Iron ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.IRON_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.IRON_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Lapis ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Lapis ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.LAPIS_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.LAPIS_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Netherite Sentry", description = "Spawns a supercharged sentry which absolutely shreds the nearest player", cooldownTicks = 20 * 15) + @MaterialInfo(name = "Netherite Sentry", description = "Spawns a supercharged sentry which absolutely shreds the nearest player", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.NETHERITE_BLOCK,Material.CRAFTER,50,60,2); + spawnSentry(player.getLocation(),player,Material.NETHERITE_BLOCK,Material.CRAFTER,NETHERITE_AMMO,NETHERITE_MAX_LIFE,NETHERITE_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Quartz ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Quartz ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.QUARTZ_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.QUARTZ_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Redstone ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Redstone ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.REDSTONE_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.REDSTONE_BLOCK,Material.DISPENSER,NORMAL_AMMO,NORMAL_MAX_LIFE,NORMAL_BULLET_COOLDOWN); return true; } - @MaterialInfo(name = "Resin ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Resin ", description = "Spawns a sentry which shoots the nearest player", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - spawnSentry(player.getLocation(),player,Material.RESIN_BLOCK,Material.DISPENSER,25,60,5); + spawnSentry(player.getLocation(),player,Material.RESIN_BLOCK,Material.DISPENSER,RESIN_AMMO,RESIN_MAX_LIFE,RESIN_BULLET_COOLDOWN); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/ShaperAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/ShaperAbility.java index 769b83e..71319f6 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/ShaperAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/ShaperAbility.java @@ -5,7 +5,6 @@ import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; -import me.trouper.trimserver.utils.Text; import org.bukkit.*; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -15,7 +14,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -37,17 +35,15 @@ public class ShaperAbility extends AbstractAbility implements Listener { private final Map knockbackModifiers = new ConcurrentHashMap<>(); private final Map originalFireTicks = new ConcurrentHashMap<>(); - private static final int BASE_DURATION_TICKS = 8 * 20; - private static final double BASE_SHATTER_DAMAGE = 10.0; - private static final double BASE_SHATTER_RADIUS = 8.0; + private static final int NORMAL_DURATION = 8 * 20; + private static final double NORMAL_SHATTER_DAMAGE = 10.0; + private static final double NORMAL_SHATTER_RADIUS = 8.0; private static final int SLOWNESS_AMPLIFIER = 1; - // Cooldowns - private static final int DEFAULT_COOLDOWN = 20 * 60; + private static final int DEFAULT_COOLDOWN = 20 * 50; private static final int NETHERITE_COOLDOWN = 20 * 90; private static final int RESIN_COOLDOWN = 20 * 40; - // Netherite Modifiers private static final double NETHERITE_DURATION_MULTIPLIER = 1.3; private static final double NETHERITE_SHATTER_DAMAGE_MULTIPLIER = 1.5; private static final double NETHERITE_SHATTER_RADIUS_MULTIPLIER = 1.2; @@ -97,9 +93,9 @@ public class ShaperAbility extends AbstractAbility implements Listener { shellParts.add(bd); } - int duration = BASE_DURATION_TICKS; - double shatterDamage = BASE_SHATTER_DAMAGE; - double shatterRadius = BASE_SHATTER_RADIUS; + int duration = NORMAL_DURATION; + double shatterDamage = NORMAL_SHATTER_DAMAGE; + double shatterRadius = NORMAL_SHATTER_RADIUS; int slownessAmplifier = SLOWNESS_AMPLIFIER; if (blockMaterialForShell == Material.NETHERITE_BLOCK) { diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SilenceAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SilenceAbility.java index 5755056..343c8c2 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SilenceAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SilenceAbility.java @@ -27,12 +27,18 @@ import java.util.Optional; @PatternInfo(name = "Warden's Call", description = "Now I am become warden, destroyer of ears.") public class SilenceAbility extends AbstractAbility { + + public static final double NORMAL_DAMAGE = 10; + public static final int NORMAL_COOLDOWN = 20 * 10; + + public static final double NETHERITE_DAMAGE = 15; + public static final int NETHERITE_COOLDOWN = 20 * 12; public SilenceAbility() { super(TrimPattern.SILENCE); } - public void shootSonicBoom(Player player) { + public void shootSonicBoom(Player player, double damage) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -62,7 +68,7 @@ public class SilenceAbility extends AbstractAbility { PlayerUtils.combatAllowed(entity,player) ); targets.forEach(target -> { - PlayerUtils.dealTrueDamage((LivingEntity) target, DamageSource.builder(DamageType.SONIC_BOOM).withDirectEntity(player).build(), 10); + PlayerUtils.dealTrueDamage((LivingEntity) target, DamageSource.builder(DamageType.SONIC_BOOM).withDirectEntity(player).build(), damage); }); return !targets.isEmpty(); },(point,blockHit) -> { @@ -75,80 +81,80 @@ public class SilenceAbility extends AbstractAbility { },30); } - @MaterialInfo(name = "Amethyst ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Amethyst ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Copper ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Copper ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Diamond ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Diamond ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Emerald Bolt", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Emerald Bolt", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Gold ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Gold ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Iron ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Iron ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Lapis ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Lapis ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Netherite ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*7) + @MaterialInfo(name = "Netherite ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NETHERITE_DAMAGE); return true; } - @MaterialInfo(name = "Quartz ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Quartz ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Redstone ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Redstone ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Resin ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = 20*10) + @MaterialInfo(name = "Resin ", description = "Shoot a sonic blast like the warden. Deals 15 true damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean resinAbility(Player player) { - shootSonicBoom(player); + shootSonicBoom(player, NORMAL_DAMAGE); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SnoutAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SnoutAbility.java index 2d9f753..8125063 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SnoutAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SnoutAbility.java @@ -3,7 +3,7 @@ package me.trouper.trimserver.server.systems.abilities.trims; import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.Verbose; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; @@ -27,6 +27,15 @@ public class SnoutAbility extends AbstractAbility { super(TrimPattern.SNOUT); } + public static final int NORMAL_COOLDOWN = 20 * 45; + public static final int NORMAL_COUNT = 4; + + public static final int NETHERITE_COOLDOWN = 20 * 45; + public static final int NETHERITE_COUNT = 6; + + public static final int RESIN_COOLDOWN = 20 * 20; + public static final int RESIN_COUNT = 3; + /** * Spawns a Piglin Brutes Loyal to the specified player. * @@ -117,111 +126,111 @@ public class SnoutAbility extends AbstractAbility { e.setCancelled(true); } - @MaterialInfo(name = "Amethyst ", description = "Spawns 4 Purple Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Amethyst ", description = "Spawns 4 Purple Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.LIGHT_PURPLE); } return true; } - @MaterialInfo(name = "Copper ", description = "Spawns 4 Gold Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Copper ", description = "Spawns 4 Gold Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.GOLD); } return true; } - @MaterialInfo(name = "Diamond ", description = "Spawns 4 Aqua Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Diamond ", description = "Spawns 4 Aqua Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.AQUA); } return true; } - @MaterialInfo(name = "Emerald ", description = "Spawns 4 Emerald Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Emerald ", description = "Spawns 4 Emerald Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.DARK_GREEN); } return true; } - @MaterialInfo(name = "Gold ", description = "Spawns 4 Yellow Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Gold ", description = "Spawns 4 Yellow Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.YELLOW); } return true; } - @MaterialInfo(name = "Iron ", description = "Spawns 4 Gray Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Iron ", description = "Spawns 4 Gray Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player, player.getEyeLocation(), NamedTextColor.GRAY); } return true; } - @MaterialInfo(name = "Lapis ", description = "Spawns 4 Blue Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Lapis ", description = "Spawns 4 Blue Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player,player.getEyeLocation(),NamedTextColor.DARK_BLUE); } return true; } - @MaterialInfo(name = "Netherite ", description = "Spawns 6 Dark Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Netherite ", description = "Spawns 6 Dark Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < NETHERITE_COUNT; i++) { spawnLoyalPiglin(player,player.getEyeLocation(),NamedTextColor.DARK_GRAY); } return true; } - @MaterialInfo(name = "Quartz ", description = "Spawns 4 White Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Quartz ", description = "Spawns 4 White Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player,player.getEyeLocation(),NamedTextColor.WHITE); } return true; } - @MaterialInfo(name = "Redstone ", description = "Spawns 4 Red Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Redstone ", description = "Spawns 4 Red Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalPiglin(player,player.getEyeLocation(),NamedTextColor.RED); } return true; } - @MaterialInfo(name = "Resin ", description = "Spawns 4 Gold Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = 20 * 45) + @MaterialInfo(name = "Resin ", description = "Spawns 4 Gold Piglin Brutes Loyal to you. They despawn after 30 seconds", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < RESIN_COUNT; i++) { spawnLoyalPiglin(player,player.getEyeLocation(),NamedTextColor.GOLD); } return true; diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SpireAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SpireAbility.java index c3c9b91..cbf1faf 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SpireAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/SpireAbility.java @@ -6,6 +6,7 @@ import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.utils.PlayerUtils; import me.trouper.trimserver.utils.SoundPlayer; import me.trouper.trimserver.utils.TargetingUtils; +import me.trouper.trimserver.utils.text.CustomBossBar; import me.trouper.trimserver.utils.visual.DisplayUtils; import me.trouper.trimserver.utils.visual.BlockDisplayRaytracer; @@ -33,6 +34,18 @@ public class SpireAbility extends AbstractAbility { private final Map activeTasks = new HashMap<>(); private final Map activeProjectiles = new HashMap<>(); + public static final int NORMAL_DURATION = 30; + public static final int NORMAL_HEIGHT = 20; + public static final int NORMAL_COOLDOWN = 20 * 90; + + public static final int NETHERITE_DURATION = 40; + public static final int NETHERITE_HEIGHT = 30; + public static final int NETHERITE_COOLDOWN = 20 * 100; + + public static final int RESIN_DURATION = 15; + public static final int RESIN_HEIGHT = 10; + public static final int RESIN_COOLDOWN = 20 * 60; + public SpireAbility() { super(TrimPattern.SPIRE); } @@ -40,7 +53,9 @@ public class SpireAbility extends AbstractAbility { private void createEnderStorm(Player player, Material material, int duration, int spireHeight) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; - + + CustomBossBar.showBossBar(main.getPlugin(),player,"Ender Storm",duration * 20); + if (activeTasks.containsKey(player.getUniqueId())) { activeTasks.get(player.getUniqueId()).cancel(); activeTasks.remove(player.getUniqueId()); @@ -106,7 +121,6 @@ public class SpireAbility extends AbstractAbility { }); } - // check for players in the sphere and push them inward if they're near the edge if (tickCounter % 5 == 0) { TargetingUtils.areaAffect(sphereCenter,sphereRadius,target -> !main.man().trustBackend.trusts(player,target) && PlayerUtils.combatAllowed(target,player),target -> { double distanceFromCenter = target.getLocation().distance(sphereCenter); @@ -156,7 +170,6 @@ public class SpireAbility extends AbstractAbility { for (int y = 0; y < spireHeight; y += 2) { Location particleLoc = baseLoc.clone().add(0, y, 0); - // Spiral particles up the spire double angle = (y / (double) spireHeight) * 360 * 3; double radius = (spireHeight - y) / (double) spireHeight * 2; double x = Math.cos(Math.toRadians(angle)) * radius; @@ -172,7 +185,6 @@ public class SpireAbility extends AbstractAbility { activeTasks.put(player.getUniqueId(), task); - // Schedule the end of the ability Bukkit.getScheduler().runTaskLater(main.getPlugin(), () -> { if (activeTasks.containsKey(player.getUniqueId())) { endEnderStorm(player); @@ -338,80 +350,80 @@ public class SpireAbility extends AbstractAbility { impactSound.playWithin(5); } - @MaterialInfo(name = "Amethyst Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Amethyst Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - createEnderStorm(player, Material.AMETHYST_BLOCK, 30, 20); + createEnderStorm(player, Material.AMETHYST_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Copper Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Copper Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - createEnderStorm(player, Material.COPPER_BLOCK, 30, 20); + createEnderStorm(player, Material.COPPER_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Diamond Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Diamond Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - createEnderStorm(player, Material.DIAMOND_BLOCK, 30, 20); + createEnderStorm(player, Material.DIAMOND_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Emerald Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Emerald Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - createEnderStorm(player, Material.EMERALD_BLOCK, 30, 20); + createEnderStorm(player, Material.EMERALD_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Gold Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Gold Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - createEnderStorm(player, Material.GOLD_BLOCK, 30, 20); + createEnderStorm(player, Material.GOLD_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Iron Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Iron Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - createEnderStorm(player, Material.IRON_BLOCK, 30, 20); + createEnderStorm(player, Material.IRON_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Lapis Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Lapis Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - createEnderStorm(player, Material.LAPIS_BLOCK, 30, 20); + createEnderStorm(player, Material.LAPIS_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Netherite Ender Storm", description = "Summon a powerful spire that traps players and fires enhanced shulker bullets", cooldownTicks = 20*120) + @MaterialInfo(name = "Netherite Ender Storm", description = "Summon a powerful spire that traps players and fires enhanced shulker bullets", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - createEnderStorm(player, Material.NETHERITE_BLOCK, 45, 25); + createEnderStorm(player, Material.NETHERITE_BLOCK, NETHERITE_HEIGHT, NETHERITE_DURATION); return true; } - @MaterialInfo(name = "Quartz Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Quartz Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - createEnderStorm(player, Material.QUARTZ_BLOCK, 30, 20); + createEnderStorm(player, Material.QUARTZ_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Redstone Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Redstone Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - createEnderStorm(player, Material.REDSTONE_BLOCK, 30, 20); + createEnderStorm(player, Material.REDSTONE_BLOCK, NORMAL_DURATION, NORMAL_HEIGHT); return true; } - @MaterialInfo(name = "Resin Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = 20*90) + @MaterialInfo(name = "Resin Ender Storm", description = "Summon a spire that traps players and fires shulker bullets", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - createEnderStorm(player, Material.RESIN_BLOCK, 30, 20); + createEnderStorm(player, Material.RESIN_BLOCK, RESIN_DURATION, RESIN_HEIGHT); return true; } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/TideAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/TideAbility.java index 140b91c..4d6ca4a 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/TideAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/TideAbility.java @@ -24,11 +24,23 @@ import java.util.List; @PatternInfo(name = "Tidal Wave", description = "No lifeguard on duty, swim at your own risk!") public class TideAbility extends AbstractAbility { + public static final int NORMAL_RADIUS = 10; + public static final int NORMAL_DAMAGE = 6; + public static final int NORMAL_COOLDOWN = 20 * 30; + + public static final int NETHERITE_RADIUS = 12; + public static final int NETHERITE_DAMAGE = 15; + public static final int NETHERITE_COOLDOWN = 20 * 35; + + public static final int RESIN_RADIUS = 5; + public static final int RESIN_DAMAGE = 3; + public static final int RESIN_COOLDOWN = 20 * 6; + public TideAbility() { super(TrimPattern.TIDE); } - public void spawnTidalWave(Player caster) { + public void spawnTidalWave(Player caster, double radius, double damage) { AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); ShaperAbility shaper = (ShaperAbility) shaperInstance; @@ -36,7 +48,7 @@ public class TideAbility extends AbstractAbility { new SoundPlayer(caster.getLocation(), Sound.ENTITY_PLAYER_SPLASH_HIGH_SPEED, 1, 1F).playWithin(30); Vector direction = caster.getLocation().getDirection(); - DisplayUtils.waveFan(caster.getLocation().add(0, 2,0),10,direction,90,0.1, point->{ + DisplayUtils.waveFan(caster.getLocation().add(0, 2,0),radius,direction,90,0.1, point->{ point.getWorld().spawnParticle(Particle.BLOCK_CRUMBLE,point,8,0.1,0.1,0.1,0.1, Material.BLUE_STAINED_GLASS.createBlockData()); TargetingUtils.areaAffect(point,0.3,5,0.3,target -> !main.man().trustBackend.trusts(caster,target) && @@ -49,7 +61,7 @@ public class TideAbility extends AbstractAbility { double verticalMultiplier = 0.2; target.setVelocity(dir.multiply(strength).setY(verticalMultiplier)); target.setRemainingAir(0); - target.damage(6, DamageSource.builder(DamageType.DROWN).withDirectEntity(caster).build()); + target.damage(damage, DamageSource.builder(DamageType.DROWN).withDirectEntity(caster).build()); blockSound.playWithin(10); caster.getWorld().spawnParticle(Particle.FALLING_WATER,target.getLocation().clone().add(0,1,0),10,0.2,1,0.2,0.1); }); @@ -62,80 +74,80 @@ public class TideAbility extends AbstractAbility { } - @MaterialInfo(name = "Amethyst ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Amethyst ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Copper ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Copper ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Diamond ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Diamond ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Emerald", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Emerald", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Gold ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Gold ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Iron ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Iron ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Lapis ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Lapis ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Netherite ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 10) + @MaterialInfo(name = "Netherite ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NETHERITE_RADIUS,NETHERITE_DAMAGE); return true; } - @MaterialInfo(name = "Quartz ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Quartz ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Redstone ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Redstone ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,NORMAL_RADIUS,NORMAL_DAMAGE); return true; } - @MaterialInfo(name = "Resin ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Resin ", description = "Summon a tidal wave in the direction you are looking. Pushes away enemies, deals 6 damage", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - spawnTidalWave(player); + spawnTidalWave(player,RESIN_RADIUS,RESIN_DAMAGE); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/VexAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/VexAbility.java index e2ca375..a1e234c 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/VexAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/VexAbility.java @@ -3,7 +3,7 @@ package me.trouper.trimserver.server.systems.abilities.trims; import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.Verbose; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; @@ -22,6 +22,15 @@ import java.util.UUID; @PatternInfo(name = "Vex Set", description = "Not the Vex!!") public class VexAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 30; + public static final int NORMAL_COUNT = 10; + + public static final int NETHERITE_COOLDOWN = 20 * 45; + public static final int NETHERITE_COUNT = 15; + + public static final int RESIN_COOLDOWN = 20 * 20; + public static final int RESIN_COUNT = 7; + public VexAbility() { super(TrimPattern.VEX); } @@ -101,111 +110,111 @@ public class VexAbility extends AbstractAbility { } } - @MaterialInfo(name = "Amethyst ", description = "Spawns 10 Purple Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Amethyst ", description = "Spawns 10 Purple Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.LIGHT_PURPLE); } return true; } - @MaterialInfo(name = "Copper ", description = "Spawns 10 Gold Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Copper ", description = "Spawns 10 Gold Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.GOLD); } return true; } - @MaterialInfo(name = "Diamond ", description = "Spawns 10 Aqua Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Diamond ", description = "Spawns 10 Aqua Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.AQUA); } return true; } - @MaterialInfo(name = "Emerald", description = "Spawns 10 Emerald Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Emerald", description = "Spawns 10 Emerald Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.DARK_GREEN); } return true; } - @MaterialInfo(name = "Gold ", description = "Spawns 10 Yellow Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Gold ", description = "Spawns 10 Yellow Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.YELLOW); } return true; } - @MaterialInfo(name = "Iron ", description = "Spawns 10 Gray Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Iron ", description = "Spawns 10 Gray Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player, player.getEyeLocation(), NamedTextColor.GRAY); } return true; } - @MaterialInfo(name = "Lapis ", description = "Spawns 10 Blue Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Lapis ", description = "Spawns 10 Blue Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player,player.getEyeLocation(),NamedTextColor.DARK_BLUE); } return true; } - @MaterialInfo(name = "Netherite ", description = "Spawns 15 Dark Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Netherite ", description = "Spawns 15 Dark Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 15; i++) { + for (int i = 0; i < NETHERITE_COUNT; i++) { spawnLoyalVex(player,player.getEyeLocation(),NamedTextColor.DARK_GRAY); } return true; } - @MaterialInfo(name = "Quartz ", description = "Spawns 10 White Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Quartz ", description = "Spawns 10 White Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player,player.getEyeLocation(),NamedTextColor.WHITE); } return true; } - @MaterialInfo(name = "Redstone ", description = "Spawns 10 Red Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Redstone ", description = "Spawns 10 Red Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < NORMAL_COUNT; i++) { spawnLoyalVex(player,player.getEyeLocation(),NamedTextColor.RED); } return true; } - @MaterialInfo(name = "Resin ", description = "Spawns 10 Gold Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = 20 * 30) + @MaterialInfo(name = "Resin ", description = "Spawns 10 Gold Vex Loyal to you. They despawn after 15 seconds", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { player.getWorld().playSound(player, Sound.ENTITY_EVOKER_PREPARE_WOLOLO,10,1); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < RESIN_COUNT; i++) { spawnLoyalVex(player,player.getEyeLocation(),NamedTextColor.GOLD); } return true; diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WardAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WardAbility.java index 3c58eec..a2e6001 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WardAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WardAbility.java @@ -6,11 +6,9 @@ import me.trouper.trimserver.server.systems.abilities.MaterialInfo; import me.trouper.trimserver.server.systems.abilities.AbstractAbility; import me.trouper.trimserver.server.systems.abilities.PatternInfo; import me.trouper.trimserver.utils.SoundPlayer; -import me.trouper.trimserver.utils.Text; +import me.trouper.trimserver.utils.text.Text; import me.trouper.trimserver.utils.Verbose; import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.block.BlockState; import org.bukkit.block.SculkSensor; import org.bukkit.entity.*; import org.bukkit.event.EventHandler; @@ -18,6 +16,7 @@ import org.bukkit.event.block.BlockReceiveGameEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; @@ -34,10 +33,8 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Warden's Assistant", description = "You glazed the warden so much that he just ignores you now. Wardens and sculk sensors won't detect you.") public class WardAbility extends AbstractAbility { - // Map to track active disguises: player UUID -> disguise entity and task private final Map activeDisguises = new HashMap<>(); - // Inner class to track disguise data private static class DisguiseData { final Warden disguise; final BukkitTask expirationTask; @@ -182,6 +179,15 @@ public class WardAbility extends AbstractAbility { removeDisguise(e.getPlayer()); } + @EventHandler + public void onDeath(PlayerDeathEvent e) { + Verbose.send( "onPlayerQuit: %s", e.getPlayer().getName()); + if (!activeDisguises.containsKey(e.getPlayer().getUniqueId())) return; + + Verbose.send( "Player %s died while disguised; removing disguise", e.getPlayer().getName()); + removeDisguise(e.getPlayer()); + } + @EventHandler public void onSensor(BlockReceiveGameEvent e) { if (e.getBlock().getState() instanceof SculkSensor sensor diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WayfinderAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WayfinderAbility.java index 2bb4bbb..28a0293 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WayfinderAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WayfinderAbility.java @@ -26,11 +26,23 @@ import java.util.concurrent.atomic.AtomicInteger; @PatternInfo(name = "Big Step", description = "\"He boot too big for he gotdamn feet.\"") public class WayfinderAbility extends AbstractAbility { + public static final int NORMAL_COOLDOWN = 20 * 5; + public static final double NORMAL_DAMAGE = 30; + public static final double NORMAL_RADIUS = 10; + + public static final int NETHERITE_COOLDOWN = 20 * 4; + public static final double NETHERITE_DAMAGE = 40; + public static final double NETHERITE_RADIUS = 15; + + public static final int RESIN_COOLDOWN = 20 * 2; + public static final double RESIN_DAMAGE = 20; + public static final double RESIN_RADIUS = 4; + public WayfinderAbility() { super(TrimPattern.WAYFINDER); } - public void stomp(Player caster) { + public void stomp(Player caster, double damage, double radius) { if (caster.getLocation().clone().subtract(0,1,0).getBlock().isPassable()) return; AbstractAbility shaperInstance = main.man().abilityBackend.getAbility(TrimPattern.SHAPER); @@ -64,7 +76,7 @@ public class WayfinderAbility extends AbstractAbility { block.setCancelDrop(true); }); - TargetingUtils.areaAffect(caster.getLocation(),10,target -> !target.isDead() && + TargetingUtils.areaAffect(caster.getLocation(),radius,target -> !target.isDead() && !target.equals(caster) && !main.man().trustBackend.trusts(caster,target) && !shaper.activeShellTasks.containsKey(target.getUniqueId()) && @@ -72,7 +84,7 @@ public class WayfinderAbility extends AbstractAbility { SoundPlayer hit = new SoundPlayer(target.getLocation(), Sound.ENTITY_EVOKER_FANGS_ATTACK, 1, 2); Vector direction = target.getLocation().toVector().subtract(caster.getEyeLocation().toVector()).normalize(); target.setVelocity(direction.multiply(0.5).setY(0.3)); - target.damage(15, DamageSource.builder(DamageType.FALLING_BLOCK).build()); + target.damage(damage, DamageSource.builder(DamageType.FALLING_BLOCK).build()); hit.playWithin(10); caster.getWorld().spawnParticle(Particle.DAMAGE_INDICATOR,target.getLocation().clone().add(0,1,0),10,0.2,1,0.2,0.1); }); @@ -82,80 +94,80 @@ public class WayfinderAbility extends AbstractAbility { },10,2); } - @MaterialInfo(name = "Amethyst ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Amethyst ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean amethystAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Copper ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Copper ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean copperAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Diamond ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Diamond ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean diamondAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Emerald Bolt", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Emerald Bolt", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean emeraldAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Gold ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Gold ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean goldAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Iron ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Iron ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean ironAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Lapis ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Lapis ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean lapisAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Netherite ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 3) + @MaterialInfo(name = "Netherite ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NETHERITE_COOLDOWN) @Override public boolean netheriteAbility(Player player) { - stomp(player); + stomp(player,NETHERITE_DAMAGE,NETHERITE_RADIUS); return true; } - @MaterialInfo(name = "Quartz ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Quartz ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean quartzAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Redstone ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Redstone ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = NORMAL_COOLDOWN) @Override public boolean redstoneAbility(Player player) { - stomp(player); + stomp(player,NORMAL_DAMAGE,NORMAL_RADIUS); return true; } - @MaterialInfo(name = "Resin ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = 20 * 4) + @MaterialInfo(name = "Resin ", description = "Jump into the air, creating a seismic disturbance when you land. Deals 5 Damage", cooldownTicks = RESIN_COOLDOWN) @Override public boolean resinAbility(Player player) { - stomp(player); + stomp(player,RESIN_DAMAGE,RESIN_RADIUS); return true; } } diff --git a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WildAbility.java b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WildAbility.java index 051ffe5..6900907 100755 --- a/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WildAbility.java +++ b/src/main/java/me/trouper/trimserver/server/systems/abilities/trims/WildAbility.java @@ -15,6 +15,8 @@ import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; @@ -36,7 +38,6 @@ public class WildAbility extends AbstractAbility { if (shaper.activeShellTasks.containsKey(target.getUniqueId())) return; if (caster.getWorld() != target.getWorld()) return; - // --- Configuration --- final Location casterStartLoc = caster.getLocation().clone().add(0,1,0); final double maxDistance = 20.0; final double pullSpeed = 0.2; @@ -45,13 +46,13 @@ public class WildAbility extends AbstractAbility { final long updateInterval = 1L; final double minPullDistance = 2.0; - // --- Initial Check --- if (casterStartLoc.distanceSquared(target.getLocation()) > maxDistance * maxDistance) return; caster.getWorld().playSound(casterStartLoc, Sound.ENTITY_FISHING_BOBBER_THROW, 1.0f, 0.8f); + target.addPotionEffect(new PotionEffect(PotionEffectType.POISON,4*20,1,true,false,false)); + - // --- Task for Pulling & Visuals --- final List currentVineSegment = new ArrayList<>(1); new BukkitRunnable() { @@ -59,7 +60,6 @@ public class WildAbility extends AbstractAbility { @Override public void run() { - // --- Cancellation Conditions --- if (ticksElapsed >= pullDurationTicks || !caster.isOnline() || !target.isOnline() || @@ -88,8 +88,7 @@ public class WildAbility extends AbstractAbility { target.setVelocity(target.getVelocity().add(pullVelocity)); - // --- Update Vine Visual --- - + BlockDisplay segment = BlockDisplayRaytracer.trace( vineMaterial, currentCasterPos, diff --git a/src/main/java/me/trouper/trimserver/utils/misc/TimerScheduler.java b/src/main/java/me/trouper/trimserver/utils/misc/TimerScheduler.java new file mode 100644 index 0000000..35a225f --- /dev/null +++ b/src/main/java/me/trouper/trimserver/utils/misc/TimerScheduler.java @@ -0,0 +1,6 @@ +package me.trouper.trimserver.utils.misc; + +public interface TimerScheduler { + void runTimer(Runnable task, long initialDelayTicks, long periodTicks); + void cancel(); +} diff --git a/src/main/java/me/trouper/trimserver/utils/text/BossBarConfig.java b/src/main/java/me/trouper/trimserver/utils/text/BossBarConfig.java new file mode 100644 index 0000000..22e5f11 --- /dev/null +++ b/src/main/java/me/trouper/trimserver/utils/text/BossBarConfig.java @@ -0,0 +1,46 @@ +package me.trouper.trimserver.utils.text; + +import net.kyori.adventure.bossbar.BossBar; + + +public class BossBarConfig { + public final int durationTicks; + public final BossBar.Color color; + public final BossBar.Overlay overlay; + public final boolean changeColorOnLowTime; + + public BossBarConfig(int durationTicks, BossBar.Color color, BossBar.Overlay overlay) { + this(durationTicks, color, overlay, true); + } + + public BossBarConfig(int durationTicks, BossBar.Color color, BossBar.Overlay overlay, boolean changeColorOnLowTime) { + this.durationTicks = durationTicks; + this.color = color; + this.overlay = overlay; + this.changeColorOnLowTime = changeColorOnLowTime; + } + + public static BossBarConfig info(int durationTicks) { + return new BossBarConfig(durationTicks, BossBar.Color.BLUE, BossBar.Overlay.PROGRESS); + } + + public static BossBarConfig warning(int durationTicks) { + return new BossBarConfig(durationTicks, BossBar.Color.YELLOW, BossBar.Overlay.PROGRESS); + } + + public static BossBarConfig error(int durationTicks) { + return new BossBarConfig(durationTicks, BossBar.Color.RED, BossBar.Overlay.PROGRESS); + } + + public static BossBarConfig success(int durationTicks) { + return new BossBarConfig(durationTicks, BossBar.Color.GREEN, BossBar.Overlay.PROGRESS); + } + + public static BossBarConfig permanent() { + return new BossBarConfig(0, BossBar.Color.PURPLE, BossBar.Overlay.PROGRESS, false); + } + + public static BossBarConfig timed(int durationTicks, BossBar.Color color) { + return new BossBarConfig(durationTicks, color, BossBar.Overlay.PROGRESS); + } +} diff --git a/src/main/java/me/trouper/trimserver/utils/text/CustomBossBar.java b/src/main/java/me/trouper/trimserver/utils/text/CustomBossBar.java new file mode 100644 index 0000000..047943e --- /dev/null +++ b/src/main/java/me/trouper/trimserver/utils/text/CustomBossBar.java @@ -0,0 +1,280 @@ +package me.trouper.trimserver.utils.text; + +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Static utility class for displaying text on configurable boss bars with timing features + */ +public class CustomBossBar { + + private static final Map activeBossBars = new ConcurrentHashMap<>(); + + // Private constructor to prevent instantiation + private CustomBossBar() {} + + /** + * Shows a boss bar to a player with specified configuration + * + * @param plugin The plugin instance for scheduling tasks + * @param player The player to show the boss bar to + * @param text The text to display + * @param config The boss bar configuration + */ + public static void showBossBar(Plugin plugin, Player player, Component text, BossBarConfig config) { + UUID playerId = player.getUniqueId(); + + // Remove existing boss bar if present + removeBossBar(player); + + // Create new boss bar + BossBar bossBar = BossBar.bossBar(text, 1.0f, config.color, config.overlay); + + // Show to player + player.showBossBar(bossBar); + + // Create and store boss bar data + PlayerBossBarData data = new PlayerBossBarData(bossBar, config); + activeBossBars.put(playerId, data); + + // Start countdown if duration is specified + if (config.durationTicks > 0) { + startCountdown(plugin, player, data); + } + } + + /** + * Shows a boss bar with simple text and default configuration + * + * @param plugin The plugin instance for scheduling tasks + * @param player The player to show the boss bar to + * @param text The text to display + * @param durationTicks How long to show the bar (in ticks) + */ + public static void showBossBar(Plugin plugin, Player player, String text, int durationTicks) { + showBossBar(plugin, player, Component.text(text), + new BossBarConfig(durationTicks, BossBar.Color.BLUE, BossBar.Overlay.PROGRESS)); + } + + /** + * Shows a boss bar with Component text and duration + * + * @param plugin The plugin instance for scheduling tasks + * @param player The player to show the boss bar to + * @param text The text component to display + * @param durationTicks How long to show the bar (in ticks) + */ + public static void showBossBar(Plugin plugin, Player player, Component text, int durationTicks) { + showBossBar(plugin, player, text, + new BossBarConfig(durationTicks, BossBar.Color.BLUE, BossBar.Overlay.PROGRESS)); + } + + /** + * Updates the text of an active boss bar + * + * @param player The player whose boss bar to update + * @param newText The new text to display + */ + public static void updateBossBarText(Player player, Component newText) { + PlayerBossBarData data = activeBossBars.get(player.getUniqueId()); + if (data != null) { + data.bossBar.name(newText); + } + } + + /** + * Updates the text of an active boss bar + * + * @param player The player whose boss bar to update + * @param newText The new text to display + */ + public static void updateBossBarText(Player player, String newText) { + updateBossBarText(player, Component.text(newText)); + } + + /** + * Updates the progress of an active boss bar + * + * @param player The player whose boss bar to update + * @param progress The progress value (0.0 to 1.0) + */ + public static void updateBossBarProgress(Player player, float progress) { + PlayerBossBarData data = activeBossBars.get(player.getUniqueId()); + if (data != null) { + data.bossBar.progress(Math.max(0.0f, Math.min(1.0f, progress))); + } + } + + /** + * Updates the color of an active boss bar + * + * @param player The player whose boss bar to update + * @param color The new color + */ + public static void updateBossBarColor(Player player, BossBar.Color color) { + PlayerBossBarData data = activeBossBars.get(player.getUniqueId()); + if (data != null) { + data.bossBar.color(color); + } + } + + /** + * Removes the boss bar from a player + * + * @param player The player to remove the boss bar from + */ + public static void removeBossBar(Player player) { + UUID playerId = player.getUniqueId(); + PlayerBossBarData data = activeBossBars.remove(playerId); + + if (data != null) { + // Cancel countdown task if running + if (data.countdownTask != null && !data.countdownTask.isCancelled()) { + data.countdownTask.cancel(); + } + + // Hide boss bar + player.hideBossBar(data.bossBar); + } + } + + /** + * Checks if a player has an active boss bar + * + * @param player The player to check + * @return true if the player has an active boss bar + */ + public static boolean hasBossBar(Player player) { + return activeBossBars.containsKey(player.getUniqueId()); + } + + /** + * Gets the remaining time for a player's boss bar in ticks + * + * @param player The player to check + * @return remaining ticks, or -1 if no boss bar or infinite duration + */ + public static int getRemainingTicks(Player player) { + PlayerBossBarData data = activeBossBars.get(player.getUniqueId()); + return data != null ? data.remainingTicks : -1; + } + + /** + * Gets the remaining time for a player's boss bar in seconds + * + * @param player The player to check + * @return remaining seconds, or -1 if no boss bar or infinite duration + */ + public static int getRemainingSeconds(Player player) { + int ticks = getRemainingTicks(player); + return ticks > 0 ? ticks / 20 : ticks; + } + + /** + * Extends the duration of an active boss bar + * + * @param player The player whose boss bar to extend + * @param additionalTicks Additional ticks to add + */ + public static void extendBossBar(Player player, int additionalTicks) { + PlayerBossBarData data = activeBossBars.get(player.getUniqueId()); + if (data != null && data.remainingTicks > 0) { + data.remainingTicks += additionalTicks; + } + } + + /** + * Removes all active boss bars (useful for plugin disable) + */ + public static void removeAllBossBars() { + for (Player player : Bukkit.getOnlinePlayers()) { + removeBossBar(player); + } + activeBossBars.clear(); + } + + /** + * Gets the number of active boss bars + * + * @return number of active boss bars + */ + public static int getActiveBossBarCount() { + return activeBossBars.size(); + } + + /** + * Cleans up disconnected players from the boss bar map + */ + public static void cleanupDisconnectedPlayers() { + activeBossBars.entrySet().removeIf(entry -> { + Player player = Bukkit.getPlayer(entry.getKey()); + if (player == null || !player.isOnline()) { + PlayerBossBarData data = entry.getValue(); + if (data.countdownTask != null && !data.countdownTask.isCancelled()) { + data.countdownTask.cancel(); + } + return true; + } + return false; + }); + } + + private static void startCountdown(Plugin plugin, Player player, PlayerBossBarData data) { + data.remainingTicks = data.config.durationTicks; + + data.countdownTask = new BukkitRunnable() { + @Override + public void run() { + if (!player.isOnline()) { + removeBossBar(player); + return; + } + + data.remainingTicks--; + + // Update progress bar based on remaining time + float progress = (float) data.remainingTicks / data.config.durationTicks; + data.bossBar.progress(Math.max(0.0f, progress)); + + // Change color based on remaining time if configured + if (data.config.changeColorOnLowTime) { + if (progress <= 0.2f) { + data.bossBar.color(BossBar.Color.RED); + } else if (progress <= 0.5f) { + data.bossBar.color(BossBar.Color.YELLOW); + } + } + + // Remove when time is up + if (data.remainingTicks <= 0) { + removeBossBar(player); + } + } + }.runTaskTimer(plugin, 0L, 1L); + } + + /** + * Internal class to hold boss bar data for each player + */ + private static class PlayerBossBarData { + final BossBar bossBar; + final BossBarConfig config; + int remainingTicks; + BukkitTask countdownTask; + + PlayerBossBarData(BossBar bossBar, BossBarConfig config) { + this.bossBar = bossBar; + this.config = config; + this.remainingTicks = config.durationTicks; + } + } +} \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/utils/Text.java b/src/main/java/me/trouper/trimserver/utils/text/Text.java similarity index 89% rename from src/main/java/me/trouper/trimserver/utils/Text.java rename to src/main/java/me/trouper/trimserver/utils/text/Text.java index 5f2e898..a21f7f0 100755 --- a/src/main/java/me/trouper/trimserver/utils/Text.java +++ b/src/main/java/me/trouper/trimserver/utils/text/Text.java @@ -1,4 +1,4 @@ -package me.trouper.trimserver.utils; +package me.trouper.trimserver.utils.text; import me.trouper.trimserver.server.Main; import net.kyori.adventure.text.Component; @@ -11,10 +11,7 @@ import org.bukkit.SoundCategory; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -286,4 +283,30 @@ public class Text implements Main { return formatted.toString().trim(); } + + public static int getLevel(String s) { + HashMap romanToInt = new HashMap(); + romanToInt.put(Character.valueOf('I'), 1); + romanToInt.put(Character.valueOf('V'), 5); + romanToInt.put(Character.valueOf('X'), 10); + romanToInt.put(Character.valueOf('L'), 50); + romanToInt.put(Character.valueOf('C'), 100); + romanToInt.put(Character.valueOf('D'), 500); + romanToInt.put(Character.valueOf('M'), 1000); + int result = 0; + for (int i = 0; i < s.length(); ++i) { + if (i > 0 && romanToInt.get(Character.valueOf(s.charAt(i))) > romanToInt.get(Character.valueOf(s.charAt(i - 1)))) { + result += romanToInt.get(Character.valueOf(s.charAt(i))) - 2 * romanToInt.get(Character.valueOf(s.charAt(i - 1))); + continue; + } + if (romanToInt.get(Character.valueOf(s.charAt(i))) == null) { + return 0; + } + result += (romanToInt.get(Character.valueOf(s.charAt(i)))).intValue(); + } + if (result > 255) { + result = 1; + } + return result; + } } \ No newline at end of file diff --git a/src/main/java/me/trouper/trimserver/utils/visual/Point.java b/src/main/java/me/trouper/trimserver/utils/visual/Point.java index dc369ea..d8808e1 100755 --- a/src/main/java/me/trouper/trimserver/utils/visual/Point.java +++ b/src/main/java/me/trouper/trimserver/utils/visual/Point.java @@ -1,13 +1,9 @@ package me.trouper.trimserver.utils.visual; -import me.trouper.trimserver.utils.Text; -import me.trouper.trimserver.utils.Verbose; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; -import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.List; diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index c0a114e..60ec208 100755 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,14 +6,15 @@ prefix: TrimServer load: STARTUP authors: [ obvWolf ] depend: [ WorldGuard ] +softdepend: [ PlaceholderAPI ] description: Armor trims give you abilities commands: trims: permission: trims.admin description: Command for managing trims. - info: + triminfo: description: Provides info on armor trim abilities. - usage: /info + usage: /triminfo trust: description: Make your friends immune to your abilities. usage: " "