Updated the abilities to use constants to make balancing easier, might change it to config variables later.

This commit is contained in:
thetrouper
2025-05-31 18:35:34 -05:00
parent 913877a22c
commit 613eef05d8
40 changed files with 1385 additions and 562 deletions

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -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));

View File

@@ -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();
registerPlaceholders();
BlockDisplayRaytracer.cleanup();
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();
}
}

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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" -> {

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {
}
}

View File

@@ -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));
}
}

View File

@@ -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<TrimPattern, AbstractAbility> registeredAbilities = new HashMap<>();
private record AbilityCooldown(UUID who, TrimPattern pattern, TrimMaterial material) {};
public Cooldown<AbilityCooldown> getCooldowns() {
return onCooldown;
}
public record AbilityCooldown(UUID who, TrimPattern pattern, TrimMaterial material) {};
private final Cooldown<AbilityCooldown> 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<Component> 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() {

View File

@@ -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);
}
}

View File

@@ -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);
};
}
/**

View File

@@ -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;

View File

@@ -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;
@@ -23,6 +22,15 @@ 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);
}
@@ -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);
}
}

View File

@@ -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<UUID, BukkitTask> 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;
}
}

View File

@@ -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;

View File

@@ -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);
if (random.nextDouble(1) >= damageFailChance) {
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.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;
}
}

View File

@@ -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<UUID, BukkitTask> activeRiders = new HashMap<>();
private final Map<UUID, Breeze> 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;
}
}

View File

@@ -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<UUID> 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;
}
}

View File

@@ -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<UUID, BukkitTask> 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);
});
}
}

View File

@@ -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;
}
}

View File

@@ -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<Entity> 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;
}
}

View File

@@ -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<UUID, AttributeModifier> knockbackModifiers = new ConcurrentHashMap<>();
private final Map<UUID, Integer> 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) {

View File

@@ -28,11 +28,17 @@ 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;
}
}

View File

@@ -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;

View File

@@ -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<UUID, BukkitTask> activeTasks = new HashMap<>();
private final Map<UUID, UUID> 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);
}
@@ -41,6 +54,8 @@ public class SpireAbility extends AbstractAbility {
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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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<UUID, DisguiseData> 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

View File

@@ -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;
}
}

View File

@@ -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<BlockDisplay> 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,7 +88,6 @@ public class WildAbility extends AbstractAbility {
target.setVelocity(target.getVelocity().add(pullVelocity));
// --- Update Vine Visual ---
BlockDisplay segment = BlockDisplayRaytracer.trace(
vineMaterial,

View File

@@ -0,0 +1,6 @@
package me.trouper.trimserver.utils.misc;
public interface TimerScheduler {
void runTimer(Runnable task, long initialDelayTicks, long periodTicks);
void cancel();
}

View File

@@ -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);
}
}

View File

@@ -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<UUID, PlayerBossBarData> 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;
}
}
}

View File

@@ -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<Character, Integer> romanToInt = new HashMap<Character, Integer>();
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;
}
}

View File

@@ -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;

View File

@@ -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 <trim>
usage: /triminfo <trim>
trust:
description: Make your friends immune to your abilities.
usage: "<add|remove|list> <player>"