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.
This commit is contained in:
Teriuihi 2025-02-09 21:57:16 +01:00
parent 4af509eb5f
commit 91ee3cf8f9

View File

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