From 91ee3cf8f9cfd9527e1f130a6091b734f4f735bb Mon Sep 17 00:00:00 2001 From: Teriuihi Date: Sun, 9 Feb 2025 21:57:16 +0100 Subject: [PATCH] Add blocking mechanics for snowball hits Introduced a check to disable snowball damage if the target is blocking and the impact angle is within 80 degrees. Extended `SnowballHitConsumer` to include the `Snowball` object for more accurate handling of hits. This improves gameplay by allowing players to block snowball attacks with proper positioning. --- .../com/alttd/ctf/events/SnowballEvent.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/alttd/ctf/events/SnowballEvent.java b/src/main/java/com/alttd/ctf/events/SnowballEvent.java index 7bb51de..2941496 100644 --- a/src/main/java/com/alttd/ctf/events/SnowballEvent.java +++ b/src/main/java/com/alttd/ctf/events/SnowballEvent.java @@ -5,6 +5,7 @@ import com.alttd.ctf.game.GamePhase; import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.team.TeamPlayer; import lombok.extern.slf4j.Slf4j; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Snowball; import org.bukkit.event.EventHandler; @@ -12,6 +13,8 @@ import org.bukkit.event.Listener; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import java.util.Optional; @@ -26,7 +29,7 @@ public class SnowballEvent implements Listener { @FunctionalInterface private interface SnowballHitConsumer { - void apply(Player hitPlayer, Player shooter, TeamPlayer shooterTeamPlayer); + void apply(Player hitPlayer, Player shooter, TeamPlayer shooterTeamPlayer, Snowball snowball); } @FunctionalInterface @@ -36,7 +39,10 @@ public class SnowballEvent implements Listener { @EventHandler public void onSnowballHit(EntityDamageByEntityEvent event) { - handleSnowballHit(event, (hitPlayer, shooter, shooterTeamPlayer) -> { + handleSnowballHit(event, (hitPlayer, shooter, shooterTeamPlayer, snowball) -> { + if (blockedAttack(hitPlayer, snowball)) { //Disable damage when it is blocked + return; + } GameClass shooterClass = shooterTeamPlayer.getGameClass(); shooter.setCooldown(Material.SNOWBALL, shooterClass.getThrowTickSpeed()); @@ -55,6 +61,20 @@ public class SnowballEvent implements Listener { }); } + private boolean blockedAttack(@NotNull Player hitPlayer, @NotNull Snowball snowball) { + if (!hitPlayer.isBlocking()) { + return false; + } + Location playerLocation = hitPlayer.getLocation(); + Vector playerFacing = playerLocation.getDirection().normalize(); + Location snowballLocation = snowball.getLocation(); + Vector impactDirection = snowballLocation.toVector().subtract(playerLocation.toVector()).normalize(); + + double angle = playerFacing.angle(impactDirection); + + return !(Math.toDegrees(angle) > 80); //Blocked if the angle was <= 80 + } + private void handleSnowballThrown(ProjectileLaunchEvent event, SnowballThrownConsumer consumer) { Optional optionalGamePhase = gameManager.getGamePhase(); if (optionalGamePhase.isEmpty()) { @@ -121,6 +141,6 @@ public class SnowballEvent implements Listener { log.debug("The shooter hit a member of their own team"); return; } - consumer.apply(hitPlayer, shooter, teamPlayerHit.get()); + consumer.apply(hitPlayer, shooter, teamPlayerHit.get(), snowball); } }