diff --git a/src/main/java/com/alttd/ctf/events/SnowballEvent.java b/src/main/java/com/alttd/ctf/events/SnowballEvent.java index 1fabd2d..04bf1b2 100644 --- a/src/main/java/com/alttd/ctf/events/SnowballEvent.java +++ b/src/main/java/com/alttd/ctf/events/SnowballEvent.java @@ -3,6 +3,7 @@ package com.alttd.ctf.events; import com.alttd.ctf.game.GameManager; import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game_class.GameClass; +import com.alttd.ctf.game_class.implementations.Mage; import com.alttd.ctf.stats.Stat; import com.alttd.ctf.team.TeamPlayer; import lombok.extern.slf4j.Slf4j; @@ -35,7 +36,7 @@ public class SnowballEvent implements Listener { @FunctionalInterface private interface SnowballThrownConsumer { - void apply(Player shooter, TeamPlayer shooterTeamPlayer); + void apply(Player shooter, TeamPlayer shooterTeamPlayer, Snowball snowball); } @EventHandler @@ -61,10 +62,13 @@ public class SnowballEvent implements Listener { @EventHandler public void onSnowballThrown(ProjectileLaunchEvent event) { - handleSnowballThrown(event, (shooter, shooterTeamPlayer) -> { + handleSnowballThrown(event, (shooter, shooterTeamPlayer, snowball) -> { GameClass shooterClass = shooterTeamPlayer.getGameClass(); shooter.setCooldown(Material.SNOWBALL, shooterClass.getThrowTickSpeed()); shooterTeamPlayer.increaseStat(Stat.SNOWBALLS_THROWN); + if (shooterClass instanceof Mage mage) { + mage.duplicateSnowBalls(shooter, snowball); + } }); } @@ -101,7 +105,7 @@ public class SnowballEvent implements Listener { log.debug("The shooter that threw a snowball was not a team player"); return; } - consumer.apply(shooter, teamPlayer.get()); + consumer.apply(shooter, teamPlayer.get(), snowball); } private void handleSnowballHit(EntityDamageByEntityEvent event, SnowballHitConsumer consumer) { diff --git a/src/main/java/com/alttd/ctf/game_class/GameClassRetrieval.java b/src/main/java/com/alttd/ctf/game_class/GameClassRetrieval.java index 897687e..6e04ca3 100644 --- a/src/main/java/com/alttd/ctf/game_class/GameClassRetrieval.java +++ b/src/main/java/com/alttd/ctf/game_class/GameClassRetrieval.java @@ -1,10 +1,7 @@ package com.alttd.ctf.game_class; import com.alttd.ctf.game.GameManager; -import com.alttd.ctf.game_class.creation.EngineerCreator; -import com.alttd.ctf.game_class.creation.FighterCreator; -import com.alttd.ctf.game_class.creation.TankCreator; -import com.alttd.ctf.game_class.creation.TrapperCreator; +import com.alttd.ctf.game_class.creation.*; import com.alttd.ctf.team.Team; import java.util.ArrayList; @@ -27,6 +24,7 @@ public class GameClassRetrieval { gameClasses.add(TankCreator.createTank(team.getColor())); gameClasses.add(TrapperCreator.createTrapper(team.getColor())); gameClasses.add(EngineerCreator.createEngineer(team.getColor())); + gameClasses.add(MageCreator.createMage(team.getColor())); return gameClasses; } diff --git a/src/main/java/com/alttd/ctf/game_class/creation/MageCreator.java b/src/main/java/com/alttd/ctf/game_class/creation/MageCreator.java new file mode 100644 index 0000000..503abf6 --- /dev/null +++ b/src/main/java/com/alttd/ctf/game_class/creation/MageCreator.java @@ -0,0 +1,63 @@ +package com.alttd.ctf.game_class.creation; + +import com.alttd.ctf.game_class.GameClass; +import com.alttd.ctf.game_class.implementations.Fighter; +import com.alttd.ctf.game_class.implementations.Mage; +import com.alttd.ctf.team.TeamColor; +import lombok.extern.slf4j.Slf4j; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.PotionType; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.List; + +@Slf4j +public class MageCreator { + + private static final MiniMessage miniMessage = MiniMessage.miniMessage(); + + @Contract("_ -> new") + public static @NotNull GameClass createMage(@NotNull TeamColor teamColor) { + return new Mage(getArmor(), getTools(teamColor), getDisplayItem(teamColor), + 20, 100, 5); + } + + @Contract(value = " -> new", pure = true) + private static @NotNull @Unmodifiable List getArmor() { + return (List.of(Material.CHAINMAIL_BOOTS, Material.AIR, Material.AIR, Material.LEATHER_HELMET)); + } + + @Contract("_ -> new") + private static @NotNull @Unmodifiable List getTools(@NotNull TeamColor teamColor) { + return (List.of(getShovel(teamColor))); + } + + private static @NotNull ItemStack getShovel(@NotNull TeamColor teamColor) { + ItemStack shovel = new ItemStack(Material.WOODEN_SHOVEL); + ItemMeta meta = shovel.getItemMeta(); + meta.itemName(miniMessage.deserialize(String.format("Snow shovel", teamColor.hex()))); + meta.setUnbreakable(true); + meta.addEnchant(Enchantment.EFFICIENCY, 1, false); + shovel.setItemMeta(meta); + return shovel; + } + + private static @NotNull ItemStack getDisplayItem(@NotNull TeamColor teamColor) { + ItemStack itemStack = new ItemStack(Material.IRON_SWORD); + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.displayName(miniMessage.deserialize(String.format("Mage", teamColor.hex()))); + itemMeta.lore(List.of( + miniMessage.deserialize("The Mage can throw many snowballs at once"), + miniMessage.deserialize("But it has a long cooldown.") + )); + itemStack.setItemMeta(itemMeta); + return itemStack; + } +} diff --git a/src/main/java/com/alttd/ctf/game_class/implementations/Mage.java b/src/main/java/com/alttd/ctf/game_class/implementations/Mage.java new file mode 100644 index 0000000..68e4548 --- /dev/null +++ b/src/main/java/com/alttd/ctf/game_class/implementations/Mage.java @@ -0,0 +1,62 @@ +package com.alttd.ctf.game_class.implementations; + +import com.alttd.ctf.game_class.GameClass; +import lombok.extern.slf4j.Slf4j; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.Snowball; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@Slf4j +public class Mage extends GameClass { + public Mage(@NotNull List armor, @NotNull List tools, @NotNull ItemStack displayItem, + double health, int throwTickSpeed, int damage) { + super(armor, tools, displayItem, health, throwTickSpeed, damage); + } + + public void duplicateSnowBalls(Player shooter, Snowball snowball) { + Location location = snowball.getLocation(); + PlayerInventory inventory = shooter.getInventory(); + ItemStack itemStack = inventory.getItemInMainHand(); + if (itemStack.getType() != Material.SNOWBALL) { + ItemStack itemInOffHand = inventory.getItemInOffHand(); + if (itemInOffHand.getType() != Material.SNOWBALL) { + log.warn("Unable to find snowballs in main/off hand"); + return; + } + itemStack = itemInOffHand; + } + if (itemStack.getAmount() <= 1) { + return; + } + duplicate(shooter, location, snowball.getVelocity(), itemStack.getAmount() - 1); + itemStack.setAmount(0); + } + + private void duplicate(@NotNull Player shooter, @NotNull Location location, @NotNull Vector velocity, int count) { + for (int i = 0; i < count; i++) { + double offsetX = (Math.random() - 0.5) * 2; + double offsetY = (Math.random() - 0.5) * 2; + double offsetZ = (Math.random() - 0.5) * 2; + + Location newLocation = location.clone().add(offsetX, offsetY, offsetZ); + Snowball snowball = location.getWorld().spawn(newLocation, Snowball.class); + + snowball.setShooter(shooter); + + double velocityChangeX = (Math.random() - 0.5) * 0.2; + double velocityChangeY = (Math.random() - 0.5) * 0.2; + double velocityChangeZ = (Math.random() - 0.5) * 0.2; + + Vector newVelocity = velocity.clone().add(new Vector(velocityChangeX, velocityChangeY, velocityChangeZ)); + + snowball.setVelocity(newVelocity); + } + } +} diff --git a/version.properties b/version.properties index 0dbdc80..b22fa94 100644 --- a/version.properties +++ b/version.properties @@ -1,3 +1,3 @@ -#Fri Feb 28 22:11:49 CET 2025 -buildNumber=80 +#Fri Feb 28 23:59:35 CET 2025 +buildNumber=83 version=0.1